Approximate location

The dialog refers only to approximate location and
         contains 3 buttons, one above the other
Figure 1. System permissions dialog that appears when your app requests ACCESS_COARSE_LOCATION only.

Android 12 (API level 31) builds upon recent platform changes to the location permissions model, including background location and one-time permissions. When an app targets Android 12, users can request that the app retrieve only approximate location information, even when the app requests the ACCESS_FINE_LOCATION runtime permission.

If your app requests ACCESS_COARSE_LOCATION but not ACCESS_FINE_LOCATION, then the change described on this page has no effect. Figure 1 shows the user-facing dialog that appears when your app targets Android 12 and requests only ACCESS_COARSE_LOCATION.

To better respect user privacy, it's recommended that you only request ACCESS_COARSE_LOCATION. You can fulfill most use cases even when you have access to only approximate location information.

If your app targets Android 12 and you request the ACCESS_FINE_LOCATION permission, you must also request the ACCESS_COARSE_LOCATION permission. You must include both permissions in a single runtime request. If you try to request only ACCESS_FINE_LOCATION, the system ignores the request and logs the following error message in Logcat: ACCESS_FINE_LOCATION must be requested with ACCESS_COARSE_LOCATION.

User choice between approximate location and precise location

The dialog has 2 sets of options, one above the other
Figure 2. System permissions dialog that appears when your app targets Android 12 and requests both ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION in a single runtime request.

When your app requests both ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION, the system permissions dialog includes the following new options for the user:

  • Precise: Provides the location accuracy that the ACCESS_FINE_LOCATION permission provides.
  • Approximate: Provides the location accuracy that the ACCESS_COARSE_LOCATION permission provides.

Figure 2 shows that the dialog contains a visual cue for both new options, to help the user choose. After the user decides on a location accuracy, they tap one of three buttons to select the duration of the permission grant. These buttons are the same as the ones that appear in location permission dialogs on devices that run Android 11 (API level 30).

On Android 12, users can navigate to system settings to set the preferred location accuracy for any app, regardless of that app's target SDK version. This is true even when your app is installed on a device running Android 11 or lower, and then upgrades to Android 12. If the user downgrades your app's location access from precise to approximate, either from the permission dialog or in system settings, the system restarts your app's process. For these reasons, it's especially important that you follow best practices for requesting runtime permissions.

User choice affects permission grants

The following table shows the permissions that the system grants your app, based on the options that the user chooses in the permissions runtime dialog:

Precise Approximate
While using the app ACCESS_FINE_LOCATION and
ACCESS_COARSE_LOCATION
ACCESS_COARSE_LOCATION
Only this time ACCESS_FINE_LOCATION and
ACCESS_COARSE_LOCATION
ACCESS_COARSE_LOCATION
Deny No location permissions No location permissions

To determine which permissions the system has granted to your app, check the return value of your permissions request. You can use Jetpack libraries in code that's similar to the following, or you can use platform libraries, where you manage the permission request code yourself.

Kotlin

val locationPermissionRequest = registerForActivityResult(
        ActivityResultContracts.RequestMultiplePermissions()
    ) { permissions ->
        when {
            permissions.getOrDefault(Manifest.permission.ACCESS_FINE_LOCATION, false) -> {
                // Precise location access granted.
            }
            permissions.getOrDefault(Manifest.permission.ACCESS_COARSE_LOCATION, false) -> {
                // Only approximate location access granted.
            } else -> {
                // No location access granted.
            }
        }
    }

// ...

// Before you perform the actual permission request, check whether your app
// already has the permissions, and whether your app needs to show a permission
// rationale dialog. For more details, see Request permissions.
locationPermissionRequest.launch(arrayOf(
    Manifest.permission.ACCESS_FINE_LOCATION,
    Manifest.permission.ACCESS_COARSE_LOCATION))

Java

ActivityResultLauncher<String[]> locationPermissionRequest =
    registerForActivityResult(new ActivityResultContracts
        .RequestMultiplePermissions(), result -> {
            Boolean fineLocationGranted = result.getOrDefault(
                    Manifest.permission.ACCESS_FINE_LOCATION, false);
            Boolean coarseLocationGranted = result.getOrDefault(
                    Manifest.permission.ACCESS_COARSE_LOCATION,false);
            if (fineLocationGranted != null && fineLocationGranted) {
                // Precise location access granted.
            } else if (coarseLocationGranted != null && coarseLocationGranted) {
                // Only approximate location access granted.
            } else {
                // No location access granted.
            }
        }
    );

// ...

// Before you perform the actual permission request, check whether your app
// already has the permissions, and whether your app needs to show a permission
// rationale dialog. For more details, see Request permissions.
locationPermissionRequest.launch(new String[] {
    Manifest.permission.ACCESS_FINE_LOCATION,
    Manifest.permission.ACCESS_COARSE_LOCATION
});

User choice also affects background location

If the system grants the ACCESS_BACKGROUND_LOCATION permission to your app, the user's choices in the location permissions dialog also apply to background location.

For example, if the user grants your app the ACCESS_BACKGROUND_LOCATION permission but grants only approximate location access in the foreground, your app has only approximate location access in the background as well.

Upgrade to precise location

Approximate location might affect your app if it currently relies on having access to precise location using the ACCESS_FINE_LOCATION permission.

Before you ask the user to upgrade your app's access to precise location, consider whether your app's use case absolutely requires this level of precision. If your app needs to pair a device with nearby devices over Bluetooth or Wi-Fi, consider using companion device pairing or the new Bluetooth permissions, instead of requesting the ACCESS_FINE_LOCATION permission.

To request that the user upgrade your app's location access from approximate to precise, do the following:

  1. If necessary, explain why your app needs the permission.
  2. Request the ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION permissions together again. Because the user has already allowed the system to grant approximate location to your app, the system dialog is different this time, as shown in figure 3 and figure 4:
The dialog contains the options 'Change to precise
         location', 'Only this time', and 'Deny'.
Figure 3. The user previously selected Approximate and While using the app (in the dialog from figure 2).
The dialog contains the options 'Only this time' and
         'Deny'.
Figure 4. The user previously selected Approximate and Only this time (in the dialog from figure 2).

Test how your app handles approximate location

To evaluate whether you need to update your app to support user-configurable location accuracy, complete the tests described in this section.

Handle approximate location request from dialog

To check how your app handles a user's request for your app to have approximate location access from the new dialog, do the following:

  1. Request both ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION.
  2. In the dialog that appears (figure 2), select Approximate near the top, and either While using the app or Only this time near the bottom.
  3. Check whether your app's use cases still work as expected, even when your app only has approximate location access.

Handle approximate location downgrade from system settings

Figure 5. An app's location permissions screen in system settings now includes Use precise location. This option is independent from the location access settings that appear closer to the top of the screen.

To check how your app handles a user's request to change your app's location access from precise to approximate in system settings, do the following:

  1. Request both ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION.
  2. In the dialog that appears (figure 2), select Precise near the top, and either While using the app or Only this time near the bottom.
  3. Navigate to your app's permissions screen in system settings.
  4. On the location permission screen, turn off Use precise location. This option appears in figure 5.

    As with any permission downgrade, the system restarts your app's process.

  5. Check whether your app's use cases still work as expected, even when your app only has approximate location access.

Handle precise location upgrade from system settings

To check how your app handles a user's request to change your app's location access from approximate to precise in system settings, do the following:

  1. Request both ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION.
  2. In the dialog that appears (figure 2), select Approximate near the top, and either While using the app or Only this time near the bottom.
  3. Navigate to your app's permissions screen in system settings.
  4. On the location permission screen, turn on Use precise location, as shown in figure 5.

    Because this permission change is an upgrade, the system doesn't restart your app.

  5. Check whether your app receives more accurate location data in its location-based use cases.

Check for location requirements in your app's SDK dependencies

Check whether your app uses any SDKs that depend on the ACCESS_FINE_LOCATION permission. Consult this article on Medium about Getting to know the behaviors of your SDK dependencies.