22
votes

If a user denies a runtime permission with Never ask again checked, does this disable any future ability to ask for the same permission? Does the user have to go through settings to enable that permission?

In my application, when I call

ActivityCompat.requestPermissions(this, 
            new String[]{Manifest.permission.READ_PHONE_STATE}, 
            0)

and that permission has previously been denied with Never ask again checked, it won't show a dialog box at all. Is this the expected behavior?

3

3 Answers

41
votes

Yes it will disable. But, you can do something to detect if the user have set some permissions not to request again. You can check it in the onRequestPermissionsResult() method

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    for(String permission: permissions){
            if(ActivityCompat.shouldShowRequestPermissionRationale(this, permission)){
                //denied
                Log.e("denied", permission);
            }else{
                if(ActivityCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED){
                    //allowed
                    Log.e("allowed", permission);
                } else{
                    //set to never ask again
                    Log.e("set to never ask again", permission);
                    //do something here.
                }
            }
        }
}

I have prepared a helper library for permission to handle such contition here on GitHub.

21
votes

Yes James McCracken this is the expected behavior. And FYI you can't open that request permission dialog, if the user has selected Never Ask Again. But you can show the information to user.

@Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case REQUEST_CODE:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    Toast.makeText(MainActivity.this, "Permission Granted", Toast.LENGTH_SHORT).show();
                    // do your work here
                } else if (Build.VERSION.SDK_INT >= 23 && !shouldShowRequestPermissionRationale(permissions[0])) {
                    Toast.makeText(MainActivity.this, "Go to Settings and Grant the permission to use this feature.", Toast.LENGTH_SHORT).show();
                   // User selected the Never Ask Again Option
                } else {
                    Toast.makeText(MainActivity.this, "Permission Denied", Toast.LENGTH_SHORT).show();
                }
                break;
        }
    } 

And if you want to open Settings Screen after the user has selected "Never ask Again" option then use below code

Intent i = new Intent();
i.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
i.addCategory(Intent.CATEGORY_DEFAULT);
i.setData(Uri.parse("package:" + context.getPackageName()));
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
i.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
context.startActivity(i);
19
votes

This is expected behaviour.

From the documentation:

When the system asks the user to grant a permission, the user has the option of telling the system not to ask for that permission again. In that case, any time an app uses requestPermissions() to ask for that permission again, the system immediately denies the request. The system calls your onRequestPermissionsResult() callback method and passes PERMISSION_DENIED, the same way it would if the user had explicitly rejected your request again. This means that when you call requestPermissions(), you cannot assume that any direct interaction with the user has taken place.