30

In Android 12, if an app requests fine location permission via ACCESS_FINE_LOCATION, the user might elect to only grant coarse location permission. Unfortunately, not all APIs work with coarse location permission — in particular, AFAICT, to look up the SSID of the connected WiFi network, we need fine location permission, not coarse location permission.

If you re-request fine location permission, the user will be asked to upgrade your access, but the user might decline. As a result, we need a way to gracefully determine that the user granted us coarse location permission and that we are still eligible to request the upgrade.

This sample project just has a button to trigger a requestPermissions() for ACCESS_FINE_LOCATION, along with four labels to report:

  • Were we granted fine location permission? (checkSelfPermission() for ACCESS_FINE_LOCATION)
  • Were we granted coarse location permission? (checkSelfPermission() for ACCESS_COARSE_LOCATION)
  • Should we prompt the user with rationale for our request, for fine permission? (shouldShowRequestPermissionRationale() for ACCESS_FINE_LOCATION)
  • Should we prompt the user with rationale for our request, for coarse permission? (shouldShowRequestPermissionRationale() for ACCESS_COARSE_LOCATION)

Running this after a fresh install on an Pixel 3a XL running the final beta of Android 12, I get the following results after the listed sequence of actions:

Action Has Fine Permission? Has Coarse Permission? Prompt for Fine? Prompt for Coarse?
launch the app no no no no
click button and grant approximate location while using the app no yes no no
click button again and choose "Keep approximate location" no yes yes no
click button a 3rd time and choose "Keep approximate location" no yes no no

While these all make some sense individually, the problem is that the second and fourth results are the same:

  • I have coarse location access
  • I am not told that I need to show rationale

The problem is that if the user tries clicking the button a 4th time, we're into the "don't ask again" state, and no permission dialog appears. All the previous times, a permission dialog appears, either to initially grant the permission or to grant the upgrade. I would like to be able to detect the 4th or later attempt, so I can show my own dialog that says "sorry, you need to go to Settings and grant the permission manually now". However, other than by tracking the count of requests myself, I do not know how to identify this case distinctly.

So, my question is: is there a way, using some existing permission or location APIs, to determine that I am no longer allowed to re-request ACCESS_FINE_LOCATION, and that further requests will result in immediate failures? In particular, the answer needs to be able to distinguish between the second and fourth rows in that table, so between "the user only granted coarse access" and "the user only granted coarse access, and you tried the upgrade twice, which the user rejected each time".

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • 1
    Could you use the change in state to determine what to do? If I interpret the table correctly, if you checked the current state before the first permission request you'd get "no no no no", and after the request you have "no yes no no". So there's a difference there. On the fourth request you'd go from "no yes no no" to (I presume) "no yes no no", i.e. no change in state. – Michael Oct 12 '21 at 12:07
  • @Michael: "So there's a difference there" -- yes, but that difference may be fairly separated in time, across separate processes. I know that if I track where we were in a file (e.g., `SharedPreferences`), I can handle this, but that leads to possible synchronization problems if the user later fiddles with permissions in Settings. I am trying to determine if there is a way to determine when we get to the fourth state without tracking the details in a persistent data store myself. – CommonsWare Oct 12 '21 at 12:11
  • _"but that difference may be fairly separated in time"_. What I meant was check once before `requestPermissions` and again when you get `onRequestPermissionsResult`. – Michael Oct 12 '21 at 12:13
  • @Michael: That would allow me to determine that I just went from the third state to the fourth state. However, unless I store something in a file, I will not know two weeks from now that I got to the fourth state and can no longer request the permission upgrade. – CommonsWare Oct 12 '21 at 12:16
  • 2
    Don't you always get a callback with a result, event if no dialog was shown? That's the way I remember it anyway. So what I'm talking about here is to always read the state twice: once before `requestPermissions`, then again when you get the results callback, and then compare the two. I'm not suggesting that you persist anything. – Michael Oct 12 '21 at 12:22
  • @Michael: OK, I think I see what you are proposing now. If I start in state 2/4, and I end in state 3, that means that I must have been in state 2 previously. If I start in state 2/4, and I end in state 4, that means that I must have been in state 4 previously. I can give that a try -- thanks! – CommonsWare Oct 12 '21 at 13:19
  • Can this situation be caused by bugs of shouldShowRequestPermissionRationale() ? https://issuetracker.google.com/issues/202194056 https://issuetracker.google.com/issues/196084857 – Maxdestroyer Oct 28 '21 at 14:24
  • @Maxdestroyer: Those issues certainly make it seem like Google did not think through `shouldShowRequestPermissionRationale()` with this permission-downgrade scenario. The second link is a bit closer than the first is to my scenario, but neither are an exact match. I hope in the next week or two to try [the solution suggested by Michael](https://stackoverflow.com/questions/69530502/how-can-we-determine-if-we-can-request-location-permission-upgrade-in-android-12?noredirect=1#comment122915022_69530502), which seems promising. – CommonsWare Oct 28 '21 at 14:37
  • @CommonsWare did you find any other solution ? or still using what michael suggested ? – kartic chaudhary Nov 11 '21 at 10:41
  • @karticchaudhary: To be honest, I have not circled back to this. It is on my to-do list. – CommonsWare Nov 11 '21 at 12:31
  • @CommonsWare running in to the exact same issue. Again I don't think Google thought this through. Regardless if anyone has an answer to this question it would be much appreciated. – lostintranslation Sep 30 '22 at 15:58
  • It can be considered as a bad solution, but what if you show a popup dialog before actually asking for a permission to not to "waste" asking attempts? – Lukáš Anda Oct 04 '22 at 14:40

1 Answers1

0

UPDATE:

Per the issue tracker this was fixed in Dec 7, 2021

Marked as fixed. The issue has been fixed and it will be available in a future build.

user16930239
  • 6,319
  • 2
  • 9
  • 33