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:
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:
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:
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:
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...
}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
Android - Apply Selectableitembackground in Xml with Support V7
Setexactandallowwhileidle - Is Not Exact as of Developer Reference
Using Notifyitemremoved or Notifydatasetchanged with Recyclerview in Android
How to Use Google Login API with Cordova/Phonegap
How to Use Recyclerview.Scrolltoposition() to Move the Position to the Top of Current View
Android: Picasso Load Image Failed . How to Show Error Message
How to Set the Output Image Use Com.Android.Camera.Action.Crop
Scrolling with Multiple Listviews for Android
How to Block Outgoing Calls and Text Sms
Facebook Authentication Without Login Button
Android: Adding Static Header to the Top of a Listactivity
Java.Lang.Unsatisfiedlinkerror: Dalvik.System.Pathclassloader
Android - Communicating Between Two Devices
Rate Google Play Application Directly in App
Calling Startintentsenderforresult from Fragment (Android Billing V3)