Android Q privacy change: User control over app access to device location

As of Android Q Beta 1, this change has the following properties:

  • Affects your app if you request access to the user's location while in the background
  • Mitigate by using new permission to access location in the background and by ensuring graceful degradation in the absence of background location updates
  • Behavior is always enabled on Android Q
Screen capture of user-facing dialogFigure 1. Dialog requesting user consent for location

Android Q gives users more control over when apps can get access to device location. When an app running on Android Q requests location access, users see the dialog shown in Figure 1. This dialog allows users to grant location access to two different extents: while in use (foreground only) or all the time (foreground and background).

To support the additional control that users have over an app's access to location information, Android Q introduces a new location permission, ACCESS_BACKGROUND_LOCATION . Unlike the existing ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION permissions, the new permission only affects an app's access to location when it's running in the background. An app is considered to be in the background unless one of its activities is visible or the app is running a foreground service.

Request background location

If your app targets Android Q and needs to access the user's location when running in the background, you must declare the new permission in your app's manifest file:

<manifest>
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
  <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
</manifest>

If your app runs on Android Q but targets Android 9 (API level 28) or lower, the following behavior applies:

  • If your app declares a <uses-permission> tag for either ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION , the system automatically adds a <uses-permission> tag for ACCESS_BACKGROUND_LOCATION during installation.
  • If your app requests either ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION , the system automatically adds ACCESS_BACKGROUND_LOCATION to the request.

Request background location access

If your app's use case requires access to location information when running in the background, it's important to consider the extent to which you need this access:

  • Your app's use case relies on a continuation of a user-initiated action , such as navigation or a smart home action. In that case, configure your foreground service so that it can retain access to a user's location after the user presses the Home button on their device or turns their device display off, even if the user has requested that your app have access to their location only in the foreground.
  • Your app's use case relies on periodic checks of a user's location all the time, such as geofencing or location sharing. In that case, your app should explain to the user that they need to allow your app to access their location all the time in order to operate correctly, then request access to background location.

Continuation of user-initiated action

In cases where the user has given your app foreground-only access to location, the user might still launch a workflow that requires your app to access their location, even after the user presses the Home button on their device or turns their device's display off.

To retain access to the user's location in this specific use case, start a foreground service that you've declared as having a foreground service type of "location" in your app's manifest:

<service
    android:name="MyNavigationService"
    android:foregroundServiceType="location" ... >
    ...
</service>

Before starting the foreground service, make sure that your app still has access to the user's location:

Kotlin

val permissionAccessCoarseLocationApproved = ActivityCompat
    .checkSelfPermission(this, permission.ACCESS_COARSE_LOCATION) ==
    PackageManager.PERMISSION_GRANTED

if (permissionAccessCoarseLocationApproved) {
   // App has permission to access location in the foreground. Start your
   // foreground service that has a foreground service type of "location".
} else {
   // Make a request for foreground-only location access.
   ActivityCompat.requestPermissions(this,
       arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION),
       YOUR_PERMISSION_REQUEST_CODE
   )
}

Java

boolean permissionAccessCoarseLocationApproved =
    ActivityCompat.checkSelfPermission(this,
        permission.ACCESS_COARSE_LOCATION) ==
        PackageManager.PERMISSION_GRANTED;

if (permissionAccessCoarseLocationApproved) {
    // App has permission to access location in the foreground. Start your
    // foreground service that has a foreground service type of "location".
} else {
   // Make a request for foreground-only location access.
   ActivityCompat.requestPermissions(this, new String[] {
        Manifest.permission.ACCESS_COARSE_LOCATION},
       YOUR_PERMISSION_REQUEST_CODE);
}

Periodic checks of user's location

Your app might have a use case that requires access to the user's location all the time. Such use cases include geofencing and location sharing with friends and family.

If these conditions apply to your app, you can continue requesting location updates without any changes, as long as the user grants your app all-the-time access to their location:

<!-- It's unnecessary to include a foreground service type for services that must have
     access to the user's location "all the time" in order to run successfully.-->
<service
    android:name="MyFamilyLocationSharingService" ... >
    ...
</service>

Although your app can request access to location in the background, the user has the option to reduce your app's access to foreground only or revoke access entirely. For this reason, whenever your app starts a service, check whether the user still allows your app to access location information in the background.

If the user has requested that your app access location only in the foreground, it's a best practice for your app to display a custom dialog, alerting the user that your app cannot function properly without access to their location all the time. After the user acknowledges this dialog, you can request background location, at which time the system dialog shown in Figure 2 appears:

Screen capture of user-facing dialogFigure 2. Dialog requesting user consent for all-the-time access to location

An example of this permission-checking logic appears in the following code snippet:

Kotlin

val permissionAccessCoarseLocationApproved = ActivityCompat
    .checkSelfPermission(this, permission.ACCESS_COARSE_LOCATION) ==
    PackageManager.PERMISSION_GRANTED

if (permissionAccessCoarseLocationApproved) {
   val backgroundLocationPermissionApproved = ActivityCompat
       .checkSelfPermission(this, permission.ACCESS_BACKGROUND_LOCATION) ==
       PackageManager.PERMISSION_GRANTED

   if (backgroundLocationPermissionApproved) {
       // App can access location both in the foreground and in the background.
       // Start your service that doesn't have a foreground service type
       // defined.
   } else {
       // App can only access location in the foreground. Display a dialog
       // warning the user that your app must have all-the-time access to
       // location in order to function properly. Then, request background
       // location.
       ActivityCompat.requestPermissions(this,
           arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION),
           YOUR_PERMISSION_REQUEST_CODE
       )
   }
} else {
   // App doesn't have access to the user's location at all. Make full request
   // for permission.
   ActivityCompat.requestPermissions(this,
       arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION,
               Manifest.permission.ACCESS_BACKGROUND_LOCATION),
       YOUR_PERMISSION_REQUEST_CODE
   )
}

Java

boolean permissionAccessCoarseLocationApproved =
    ActivityCompat.checkSelfPermission(this, permission.ACCESS_COARSE_LOCATION)
        == PackageManager.PERMISSION_GRANTED;

if (permissionAccessCoarseLocationApproved) {
   boolean backgroundLocationPermissionApproved =
           ActivityCompat.checkSelfPermission(this,
               permission.ACCESS_BACKGROUND_LOCATION)
               == PackageManager.PERMISSION_GRANTED;

   if (backgroundLocationPermissionApproved) {
       // App can access location both in the foreground and in the background.
       // Start your service that doesn't have a foreground service type
       // defined.
   } else {
       // App can only access location in the foreground. Display a dialog
       // warning the user that your app must have all-the-time access to
       // location in order to function properly. Then, request background
       // location.
       ActivityCompat.requestPermissions(this, new String[] {
           Manifest.permission.ACCESS_BACKGROUND_LOCATION},
           YOUR_PERMISSION_REQUEST_CODE);
   }
} else {
   // App doesn't have access to the user's location at all. Make full request
   // for permission.
   ActivityCompat.requestPermissions(this, new String[] {
        Manifest.permission.ACCESS_COARSE_LOCATION,
        Manifest.permission.ACCESS_BACKGROUND_LOCATION
        },
        YOUR_PERMISSION_REQUEST_CODE);
}

Follow location best practices

By checking and requesting location permissions in the ways shown in this guide, your app can successfully keep track of its access level regarding the user's location.

For more information about how to keep your users' data safe, see the permissions best practices guide.

Ask only for the permissions you need

Ask for permissions only when needed. For example:

  • Don't request a location permission at app startup unless absolutely necessary.
  • If your app targets Android Q and needs access to location information only when running in the foreground, don't request ACCESS_BACKGROUND_LOCATION .

Support graceful degradation if permission isn't granted

To maintain a good user experience, design your app so that it can gracefully handle the following situations:

  • Your app doesn't have any access to location information.
  • Your app doesn't have access to location information when running in the background.

Similar Articles:

Your Apps Know Where You Were Last Night, and They’re Not Keeping It Secret

Your Apps Know Where You Were Last Night, and They’re Not Keeping It Secret

Apps on smartphones are selling and sharing our location data 24/7

Apps on smartphones are selling and sharing our location data 24/7

Carriers Swore They'd Stop Selling Location Data. Will They Ever?

Carriers Swore They'd Stop Selling Location Data. Will They Ever?

Facebook Filed A Patent To Calculate Your Future Location

Facebook Filed A Patent To Calculate Your Future Location