1

I'm dealing with on demand permissions in Android and I found a confusing situation. My objective is to display a dialog with a "go to app settings" button if the user has selected "Never ask again" in a permission.

OK, if the user selects "Never ask again" then, next time you request the permission you can know it doing this in the method onRequestPermissionsResult

public boolean checkIfShouldShowGoToSettingsDialog(String permissions[], int[] grantResults){
    for (int i=0; i<permissions.length; i++){
        if (grantResults[i] == PackageManager.PERMISSION_DENIED && !ActivityCompat.shouldShowRequestPermissionRationale(SectionManager.getInstance().getCurrentActivity(), permissions[i])) {
            return true;
        }
    }
    return false;
}

The problem is that if you do that, each time you call requestPermission(), then, onRequestPermissionsResult is being called again even with the permission denied previously and even with the checkbox selected. So checkIfShouldShowGoToSettingsDialog is returning true because the permission is DENIED and shouldShowRequestPermissionRationale is returning false. I don't want that. I want to display the "go to app settings" dialog only the first time the user has selected "Don't ask again".

So I tried something:

I added this validation before calling requestPermission(). I tried removing the permissions which returns false to the method shouldShowRequestPermissionRationale() because it's supposed that those permissions has the checkbox selected:

public String[] removePermanentlyDeniedPermissionsFromArray(String[] permissions){
    List<String> result = new ArrayList<>();
    for (String permission : permissions) {
        if (ActivityCompat.shouldShowRequestPermissionRationale(SectionManager.getInstance().getCurrentActivity(), permission)) {
            result.add(permission);
        }
    }
    return result.toArray(new String[result.size()]);
}

It worked perfectly but... the problem is that the first time you open the app, the first time you are going to request the permissions... shouldShowRequestPermissionRationale() returns FALSE for all of them! so no permissions are being requested.

Then, how can I avoid a callrequestPermission() if the user has checked "Never ask again" ?

halfer
  • 19,824
  • 17
  • 99
  • 186
NullPointerException
  • 36,107
  • 79
  • 222
  • 382
  • there is no wat AFAIK. You could keep the state 'already shown' stored somewhere – Blackbelt May 30 '18 at 10:21
  • https://stackoverflow.com/questions/31928868/how-do-we-distinguish-never-asked-from-stop-asking-in-android-ms-runtime-permis – CommonsWare May 30 '18 at 10:33
  • have you checked my answer on this [SO](https://stackoverflow.com/questions/50639292/detecting-wether-a-permission-can-be-requested-or-is-permanently-denied/50639402#50639402)? – Sagar Jun 19 '18 at 09:20

2 Answers2

0

I am very happy to answer your questions. In my past projects, I also encountered similar problems. The following is my solution. (1) In order to avoid duplicate prompts, we must save a successful token when the user first agrees. Wait until the next operation, first determine whether the user has agreed, if you have agreed, then no longer prompt. Otherwise, prompt the user again. (2) Here we need to use an open source framework for quickly saving reminder tags. Why use this framework? Because it has a method that can set the validity period of a tag directly. Specific usage can be viewed here: https://github.com/yangfuhai/ASimpleCache

mxbhxx
  • 1
  • 1
0

So here is the wrong use of shouldShowPermissionRationale. That is true if permission was denied earlier (without clicking on check box). For first time it is always false. Check the doc

/**
     * Gets whether you should show UI with rationale for requesting a permission.
     * You should do this only if you do not have the permission and the context in
     * which the permission is requested does not clearly communicate to the user
     * what would be the benefit from granting this permission.
     * <p>
     * For example, if you write a camera app, requesting the camera permission
     * would be expected by the user and no rationale for why it is requested is
     * needed. If however, the app needs location for tagging photos then a non-tech
     * savvy user may wonder how location is related to taking photos. In this case
     * you may choose to show UI with rationale of requesting this permission.
     * </p>
     *
     * @param activity The target activity.
     * @param permission A permission your app wants to request.
     * @return Whether you can show permission rationale UI.
     *
     * @see #checkSelfPermission(android.content.Context, String)
     * @see #requestPermissions(android.app.Activity, String[], int)
     */

Process for requesting runtime permission

1.Generate the list of Permissions which are not granted.

List<String> permissionList = new ArrayList<>()
if(somePermission == PackageManager.PERMISSION_DENIED){
   permissionList.add(somePermission);
}
//so on
String[] permissionArray = permissionList.toArray(new String[permissionArray.size()]);

2.In case of multiple permissions being asked at the same time, rationale might get complicated, So simply ignore it.

3.Request the permission with above generated Array.

4.In case permission is denied, redirect the user to settings screen if permission is mandatory for the app to run.

Best Practice:

Always group the permissions that are mandatory and optional within the app and ignore the rejections for optional permissions.

Mohammed Atif
  • 4,383
  • 7
  • 28
  • 57