Search code examples
androidandroid-dialogfragmentillegalstateexception

IllegalStateException - Can not perform this action after onSaveInstanceState when calling DialogFragment.show() method


I'm developing an Android 6.0 app example on how to request ACCESS_FINE_LOCATION permission, just like in the following image.

enter image description here

When selecting the DENY option I want to show to the user a custom Dialog but it throws the following exception:

IllegalStateException - Can not perform this action after onSaveInstanceState

which is thrown when calling the method:

grantPermissionDialog.show(getSupportFragmentManager(),"GrantPermissionDialog");

within the onRequestPermissionsResult method

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if(requestCode == REQUEST_ACCESS_FINE_LOCATION){
        if(grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
            Toast.makeText(this, "Location permission granted", Toast.LENGTH_LONG).show();
        }else{
            grantPermissionDialog.show(getSupportFragmentManager(),"GrantPermissionDialog");
        }
    }
}

I suppose this is because of the call to the getSupportFragmentManager() method. Here is my GrantPermissionDialog code.

public class GrantPermissionDialog extends DialogFragment {

private int statusCode;
private String message="El permiso de ubicación es necesario para que esta aplicación funcione.";
private String positiveButtonText="Salir";
private String negativeButtonText="Solicitar permiso";
public static int EXIT_APPLICATION=0;
public static int REQUEST_PERMISSION=1;

@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    builder.setMessage(message);
    builder.setPositiveButton(positiveButtonText, new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int id) {
                statusCode = EXIT_APPLICATION;
        }
    });
    builder.setNegativeButton(negativeButtonText, new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int id) {
            statusCode = REQUEST_PERMISSION;
        }
    });
    return builder.create();
}


public int getStatusCode() {
    return statusCode;
}

}

Any ideas on how to solve this issue?


Solution

  • This is a known scenario and is very well explained here. According to that article, it's caused

    because you attempted to commit a FragmentTransaction after the activity’s state had been saved

    You should move your show() dialog code to "onPostResume()" and use a flag as described here

    private boolean mRequestPermissionsWithResult = false;    
    
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if(requestCode == REQUEST_ACCESS_FINE_LOCATION){
            if(grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
                Toast.makeText(this, "Location permission granted", Toast.LENGTH_LONG).show();
            }else{
                mRequestPermissionsWithResult = true;
            }
        }
    }
    
    @Override
    protected void onPostResume() {
        super.onPostResume();
        if (mRequestPermissionsWithResult) {
            grantPermissionDialog.show(getSupportFragmentManager(),"GrantPermissionDialog");
        }
        mRequestPermissionsWithResult = false;
    }