How Do We Distinguish Never-Asked from Stop-Asking in Android M's Runtime Permissions

How Do We Distinguish Never-Asked From Stop-Asking in Android M's Runtime Permissions?

As per the current example: https://github.com/googlesamples/android-RuntimePermissions/blob/master/Application/src/main/java/com/example/android/system/runtimepermissions/MainActivity.java#L195

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResults) {
if (requestCode == REQUEST_CAMERA) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
doThing();
//STORE FALSE IN SHAREDPREFERENCES
} else {
//STORE TRUE IN SHAREDPREFERENCES
}
}

Store a boolean in SharedPreferences with key as your permission code and value as indicated above, to indicate whether that preference has been denied before.

Sadly, you probably can't check against a preference that has been accepted and later denied while your app is running. The final spec is not available, but there's a chance that your app either gets restarted or gets mock values until the next launch.

Android M - check runtime permission - how to determine if the user checked Never ask again?

Developer Preview 2 brings some changes to how permissions are requested by the app (see also http://developer.android.com/preview/support.html#preview2-notes).

The first dialog now looks like this:

Sample Image

There's no "Never show again" check-box (unlike developer preview 1). If the user denies the permission and if the permission is essential for the app it could present another dialog to explain the reason the app asks for that permission, e.g. like this:

Sample Image

If the user declines again the app should either shut down if it absolutely needs that permission or keep running with limited functionality. If the user reconsiders (and selects re-try), the permission is requested again. This time the prompt looks like this:

Sample Image

The second time the "Never ask again" check-box is shown. If the user denies again and the check-box is ticked nothing more should happen.
Whether or not the check-box is ticked can be determined by using Activity.shouldShowRequestPermissionRationale(String), e.g. like this:

if (shouldShowRequestPermissionRationale(Manifest.permission.WRITE_CONTACTS)) {...

That's what the Android documentation says (https://developer.android.com/training/permissions/requesting.html):

To help find the situations where you need to provide extra
explanation, the system provides the
Activity.shouldShowRequestPermissionRationale(String) method. This
method returns true if the app has requested this permission
previously and the user denied the request. That indicates that you
should probably explain to the user why you need the permission.

If the user turned down the permission request in the past and chose
the Don't ask again option in the permission request system dialog,
this method returns false. The method also returns false if the device
policy prohibits the app from having that permission.

To know if the user denied with "never ask again" you can check again the shouldShowRequestPermissionRationale method in your onRequestPermissionsResult when the user did not grant the permission.

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == REQUEST_PERMISSION) {
// for each permission check if the user granted/denied them
// you may want to group the rationale in a single dialog,
// this is just an example
for (int i = 0, len = permissions.length; i < len; i++) {
String permission = permissions[i];
if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
// user rejected the permission
boolean showRationale = shouldShowRequestPermissionRationale( permission );
if (! showRationale) {
// user also CHECKED "never ask again"
// you can either enable some fall back,
// disable features of your app
// or open another dialog explaining
// again the permission and directing to
// the app setting
} else if (Manifest.permission.WRITE_CONTACTS.equals(permission)) {
showRationale(permission, R.string.permission_denied_contacts);
// user did NOT check "never ask again"
// this is a good place to explain the user
// why you need the permission and ask if he wants
// to accept it (the rationale)
} else if ( /* possibly check more permissions...*/ ) {
}
}
}
}
}

You can open your app setting with this code:

Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivityForResult(intent, REQUEST_PERMISSION_SETTING);

There is no way of sending the user directly to the Authorization page.

Android Marshmallow and Above Device - how to know “Never ask again” is checked by the user

Look like similar question has been asked before you can get your answer here How Do We Distinguish Never-Asked From Stop-Asking in Android M's Runtime Permissions?

Android M Permissions : Confused on the usage of shouldShowRequestPermissionRationale() function

After M Preview 1, if the dialog is displayed for the first time, there is no Never ask again checkbox.

If the user denies the permission request, there will be a Never ask again checkbox in the permission dialog the second time permission is requested.

So the logic should be like this:

  1. Request permission:

    if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(context, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE);
    } else {
    //Do the stuff that requires permission...
    }
  2. Check if the permission was denied or granted in onRequestPermissionsResult.

    If the permission was denied previously, this time there will be a Never ask again checkbox in the permission dialog.

    Call shouldShowRequestPermissionRationale to see if the user checked Never ask again. shouldShowRequestPermissionRationale method returns false only if the user selected Never ask again or device policy prohibits the app from having that permission:

    if (grantResults.length > 0){
    if(grantResults[0] == PackageManager.PERMISSION_GRANTED) {
    //Do the stuff that requires permission...
    }else if (grantResults[0] == PackageManager.PERMISSION_DENIED){
    // Should we show an explanation?
    if (ActivityCompat.shouldShowRequestPermissionRationale(context, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
    //Show permission explanation dialog...
    }else{
    //Never ask again selected, or device policy prohibits the app from having that permission.
    //So, disable that feature, or fall back to another situation...
    }
    }
    }

So, you won't have to track if a user checked Never ask again or not.

Android Permissions should be asked on startup or only when needed?

If a user doesn't know why they need to accept a specific permisson, they may be suspicious and refuse (eg. camera).

If they click on a functionnality like 'Scan code' they will know why they are being asked for that permission and accept.

If you asked beforehand and the user refused, when you get to the part where you need that permission, it won't work. This is why they changed it to dynamic permissions in Android 6.

How do I request android runtime permissions the way like in image below?

What you're seeing is permission screen for legacy apps that was added in android 10:

If your app targets Android 5.1 (API level 22) or lower, users see a
permissions screen when using your app on a device that runs Android
10 or higher for the first time, as shown in Figure 1. This screen
gives users the opportunity to revoke access to permissions that the
system previously granted to your app at install time.



Related Topics



Leave a reply



Submit