3

If an app calls ActivityCompat.requestPermissions(...), then the OS displays a dialog with Deny and Permit buttons. There is also a "never show this again" tick box.

However, there's no way that I can see for the app to know whether the user has ticked this box. Within onRequestPermissionsResult(...), the grantResults parameter is PERMISSION_DENIED if the user clicks Deny and also if the user ticks the tick box before clicking Deny.

So is there anyway an app can find out whether the user doesn't want to see that dialog again?

Adil Hussain
  • 30,049
  • 21
  • 112
  • 147
Gruntcakes
  • 37,738
  • 44
  • 184
  • 378

3 Answers3

6

You can use shouldShowRequestPermissionRationale() - it will return false in a few cases:

  • You've never asked for the permission before
  • The user has checked the 'never again' checkbox
  • The permission has been disabled by policy (say, in a work situation)

By combining this with a shared preference to store if you've ever asked for permission, you can effectively determine if they'll actually see the dialog when you call requestPermissions().

Adil Hussain
  • 30,049
  • 21
  • 112
  • 147
ianhanniballake
  • 191,609
  • 30
  • 470
  • 443
  • For anyone stumbling across this answer and wanting a more in depth explanation of how to combine the [shouldShowRequestPermissionRationale()](https://developer.android.com/reference/androidx/core/app/ActivityCompat#shouldShowRequestPermissionRationale(android.app.Activity,java.lang.String)) method with a value in shared preferences, see my answer in [here](https://stackoverflow.com/a/73826849/1071320). – Adil Hussain Sep 23 '22 at 11:17
1

As Ian Lake has hinted (here), we can use persistent storage (e.g. shared preferences) as a heuristic to determine when a call into requestPermissions() will be ignored by the operating system.

In my opinion, the point at which we should save this boolean value in persistent storage is when the user taps the positive button in the "request permission rationale" popup and thus triggers a second call to requestPermissions().

Subsequently, if shouldShowRequestPermissionRationale() returns false and our boolean value in persistent storage returns true, then we should direct the user to the Settings app instead of making a third call to the requestPermissions() method.

For a concrete example of the above, see this small app which I have put together to demonstrate this workaround exactly.

All of the above said, it's a huge shame that the Android APIs do not allow us to ask a very simple question of the operating system: "Has the user denied the permission permanently?"

Adil Hussain
  • 30,049
  • 21
  • 112
  • 147
0

Cases which may occurs and values which you'll receive after checkSelfPermission(..) (flag) and shouldShowRequestPermissionRationale(..) (shouldShow) call:

  1. After first app install / never ask for this permission: flag=-1, shouldShow=false
  2. User clicked deny before: flag=-1, shouldShow=true
  3. User clicked allow before: flag=0, shouldShow=false
  4. User clicked don't ask again before: flag=-1, shouldShow=false
  5. If user switch permission to deny in settings: flag=-1, shouldShow=true

As you can see, where is no difference between 1st case and the 4rd one. So, that's why you need to save the information about previous permission requests (it's the first request of permission or not). I save this info in app preferences.

SerjantArbuz
  • 982
  • 1
  • 12
  • 16