As of Android 11, apps targeting SDK 30+ will not show a user an option to grant background location permission to an app more than once. If not initially granted, it requires users to go to a settings page. How do we bring a user to the proper settings page?
When a feature in your app requests background location on a device that runs Android 11 or higher, the system dialog doesn't include a button to enable background location access. In order to enable background location access, users must set the Allow all the time option for your app's location permission on a settings page, as described in the guide on how to Request background location.
https://developer.android.com/about/versions/11/privacy/location#change-details
The user-visible label of the settings option that grants background location (for example, Allow all the time in figure 3). You can callgetBackgroundPermissionOptionLabel() to get this label. The return value of this method is localized to the user's device language preference.
https://developer.android.com/training/location/permissions#request-location-access-runtime
While Android provides a new API to get this settings page label, there is no documented API to bring up this settings page directly. The closest you can come is to bring up the app-specific settings page as described below. From there, the user must perform at least two taps to drill down to Permissions -> Location to enable background access. This is an onerous process that many users will fail to complete.
The lack of an API to bring up a settings page has been documented for a long time in this question, but is far more important as of the release of Android 11, as there is no other way of granting background permission.
How to programmatically open the Permission Screen for a specific app on Android Marshmallow?
It is possible to bring the user to the proper settings page the very first time the user is asked using code like this: requestPermissions(arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION), PERMISSION_REQUEST_BACKGROUND_LOCATION)
. This will work only once. If the user denies the permission (or even accidentally hits back or leaves the screen without granting), this will never work again, and the user must manually drill-down in settings as described above.
Is there there really no way for an app to help users grant background location permission after an initial denial other than to instruct them to go hunting for the right page in Settings?
Am I missing something? If not, isn’t this a major Android 11 usability problem?
A full example of code needed to trigger the proper settings page in a first time prompt, but the inability to do it ever again is here:
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { if (checkSelfPermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION) != PackageManager.PERMISSION_GRANTED ) { if (shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_BACKGROUND_LOCATION)) { val builder = AlertDialog.Builder(this) builder.setTitle("This app needs background location access") builder.setMessage("Please grant location access so this app can detect beacons in the background.") builder.setPositiveButton(android.R.string.ok, null) builder.setOnDismissListener { requestPermissions( arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION), PERMISSION_REQUEST_BACKGROUND_LOCATION ) } builder.show() } else { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) { val builder = AlertDialog.Builder(this) builder.setTitle("Functionality limited") builder.setMessage("Since background location access has not been granted, this app will not be able to discover beacons in the background. Please go to Settings -> Applications -> Permissions and grant background location access to this app.") builder.setPositiveButton(android.R.string.ok, null) builder.setOnDismissListener { val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) val uri: Uri = Uri.fromParts("package", packageName, null) intent.data = uri // This will take the user to a page where they have to click twice to drill down to grant the permission startActivity(intent) } builder.show() } } } } else { if (!shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)) { requestPermissions( arrayOf( Manifest.permission.ACCESS_FINE_LOCATION /*Manifest.permission.ACCESS_BACKGROUND_LOCATION*/ ), PERMISSION_REQUEST_FINE_LOCATION ) } else { val builder = AlertDialog.Builder(this) builder.setTitle("Functionality limited") builder.setMessage("Since location access has not been granted, this app will not be able to discover beacons. Please go to Settings -> Applications -> Permissions and grant location access to this app.") builder.setPositiveButton(android.R.string.ok, null) builder.setOnDismissListener { val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) val uri: Uri = Uri.fromParts("package", packageName, null) intent.data = uri // This will take the user to a page where they have to click twice to drill down to grant the permission startActivity(intent) } builder.show() } }
If you ask for ACCESS_FINE_LOCATION and ACCESS_BACKGROUND_LOCATION at once then permission dialog will not shown. First ask for fine location and if user accepts then ask for background location.
Starting in Android 11, whenever your app requests a permission related to location, microphone, or camera, the user-facing permissions dialog contains an option called Only this time. If the user selects this option in the dialog, your app is granted a temporary one-time permission.
Credits for the answer to @Stephen Ruda
I have run into the exact same problem. I agree that this is an issue for any developer who needs background location permission. I would like to add additional notes for other readers:
(1) On API 30+ you will first need basic location permissions before asking for background location permission - otherwise, it won't go to the permission screen at all.
(2) When you ask for background location permission and it sends them to the permission request screen, it will only 'lock' the user out if they ONLY hit the back button. If they tap any of the options and then back the request will work again.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With