Privacy in Android Q
Android Q extends the transparency and control that users have over data and app capabilities. For developers, these features can affect specific behaviors or data that your app may be depending on.
All developers should review the privacy features and test their apps. Impacts can vary based on each app's core functionality, targeting, and other factors.
Top privacy changes
SCOPED STORAGE
New limits on access to files in shared external storage. Complete most work with files in app-specific directories or strongly-typed media collections.
DEVICE LOCATION
New user option to allow access to device location only while your app is in the foreground.
BACKGROUND APP STARTS
New restrictions on launching activities from the background without user interaction.
HARDWARE IDENTIFIERS
New restrictions on access to device hardware identifiers such as IMEI, serial number, MAC, and similar data.
CAMERA AND CONNECTIVITY
New restrictions on access to full camera metadata, and FINE location permission now required for many connectivity workflows.
Get started with privacy updates
- Review the privacy features — Learn about what's changing and assess your app.
- Test your app on Android Q — Get the Beta as soon as possible, test, migrate as needed.
- Update your app — Targeting Q if possible, test with users via beta channels or other groups.
Android Q privacy checklist
Android Q privacy features extend the transparency and control that users have over their data and the capabilities they give to apps. These features might mean that specific behaviors or data that your app is depending on may no longer be available. This checklist gives you an overview of the key features to test for, as well as other privacy changes to keep in mind.
The impacts on your app can be minimized if your app is following current best practices for handling user data. We recommend getting started as soon as possible with testing and updating your apps.
For complete details, see the documentation for each feature. Also see the release notes for changes at each beta build.
Key behavior change | Apps affected | Mitigation strategy | How to enable | |
---|---|---|---|---|
Scoped storage New sandbox view into external storage, giving access to app-specific files and media collections | Apps that access and share files in external storage | Work in app-specific directory and media collection directories Learn more | Target Android Q | |
More user control over location permissions New foreground-only permission that gives users more control over app access to device location | Apps that request the user's location while in the background | Ensure graceful degradation in the absence of background location updates Use new permission to access location in the background Learn more | Install app on device running Android Q | |
Background activity starts New restrictions on launching activities from the background | Apps that launch activities without user interaction | Use notification-triggered activities Learn more | Enabled by default; turn on Allow background activity starts developer option to disable restrictions | |
Non-resettable hardware identifiers New restrictions on accessing device serial and IMEI | Apps that access device serial or IMEI | Use an identifier that the user can reset Learn more | Install app on device running Android Q | |
Permission for wireless scanning Access to some Wi-Fi, Wi-Fi Aware, and Bluetooth scanning methods requires fine location permission | Apps using Wi-Fi and Bluetooth APIs | Request ACCESS_FINE_LOCATION permission for related use cases Learn more | Target Android Q |
Other privacy changes
Android Q introduces many other privacy changes that you should keep in mind when testing and updating your app:
Data & identifiers | Camera & connectivity | Permissions | ||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Android Q places the following Non-resettable device identifiers
Android Q privacy change: Scoped storageAs of Android Q Beta 3, apps that target Android 9 (API level 28) or lower see no change, by default, to how storage works from previous Android versions. As you update your existing app to work with scoped storage, you can use a new manifest attribute to enable the new behavior for your app on Android Q devices, even if your app is targeting Android 9 or lower. To give users more control over their files and to limit file clutter, Android Q changes how apps can access files on the device's external storage, such as the files stored at the path Note: The permissions specific to media collections that were introduced in earlier beta releases— This guide describes the files included in the sandboxed view, as well as how to update your app so that it can continue to share, access, and modify files that are saved on an external storage device. This guide also explains several considerations related to location information in photographs, media access from native code, and use of column names in content queries. To learn more about changes to external storage in Android Q, see the section that discusses Improvements in creating files on external storage. Note: If you encounter issues with using this feature, send us a bug report using this hotlist. Sandboxed view of files in external storageBy default, if your app targets Android Q, it has a sandboxed view of the files that are on an external storage device. The app can store files intended for itself under an app-specific directory in the sandbox using An app that has a sandboxed view always has access to the files that it creates, both inside and outside its app-specific directory. However, your app can access files that other apps have created only if these files reside in one of the following well-defined media collections:
In order to access any other file that another app has created, including files in a "downloads" directory, your app must use the Storage Access Framework, which allows the user to select a specific file. The sandboxed view also imposes the following media data restrictions:
To access media files in native code, retrieve the file using Preserve your app's files after uninstallIf an app has a sandboxed view into external storage and the app is then uninstalled, all files within the app-specific directory are cleaned up. To preserve these files after an uninstall, save them to a directory within the Opt out of sandboxed viewWarning: Scoped storage will be required in next year's major platform release for all apps, independent of target SDK level. Therefore, you should ensure that your app works with scoped storage well in advance. To do so, make sure that the behavior is enabled on Android Q devices running your app. Most apps that already follow storage best practices should work with scoped storage after making minimal changes. Before your app is fully compatible or tested, you can temporarily opt out of the scoped storage behavior based on your app's target SDK level or a new manifest attribute called
Note: To test how an app targeting Android 9 or lower works with scoped storage, you can opt in to the behavior by setting the value of Set up a virtual external storage deviceOn devices without removable external storage, use the following command to enable a virtual disk for testing purposes: adb shell sm set-virtual-disk true
Summary of sandboxed view file accessThe following table summarizes how an app that has a sandboxed view can access files in external storage:
*You can use the Storage Access Framework to access each of the locations shown in the preceding table without requesting any permissions. Adapt specific types of usage patterns to the changeThis section provides advice for several specific types of media-based apps to adapt to the storage behavior change taking place in apps that target Android Q. It's a best practice to use the sandboxed view unless your app needs access to a file that doesn't reside in either the app-specific directory or the Share media filesSome apps allow users to share media files with each other. For example, social media apps give users the ability to share photos and videos with friends. To access the media files that users want to share, use the In cases where you provide a suite of companion apps—such as a messaging app and a profile app—set up file sharingusing Work in documentsSome apps use documents as the unit of storage in which users enter data that they might want to share with peers or import into other documents. Several examples include a user opening a business productivity document or opening a book that's saved as an In these cases, allow the user to choose the file to open by invoking the The ActionOpenDocument sample on GitHub shows how to use Manage groups of filesFile management and media creation apps typically manage groups of files in a directory hierarchy. These apps can invoke the Using this interface, users can access files from any installed instance of The ActionOpenDocumentTree sample on GitHub shows how to use Note: When using Access and edit media contentThis section provides best practices for loading and storing media files in external storage so that your app continues to provide a good user experience in Android Q. Note: In a future release, when apps that have a sandboxed view of external storage request the Storage runtime permission, they can view a file only if the file resides in the app-specific directory or one of the media collections: If an app attempts to open files outside of its package-specific path using a raw file-system view, an error occurs: either a Access filesDon't load media files using the deprecated
Note: You can view the set of pending media files by calling The following code snippet shows how to access media files: // Load thumbnail of a specific media item. val mediaThumbnail = resolver.loadThumbnail(item, Size(640, 480), null) // Open a specific media item. resolver.openFileDescriptor(item, mode).use { pfd -> // ... } // Find all videos on a given storage device, including pending files. val collection = MediaStore.Video.Media.getContentUri(volumeName) val collectionWithPending = MediaStore.setIncludePending(collection) resolver.query(collectionWithPending, null, null, null).use { c -> // ... }
Access from native code You might encounter situations where your app needs to work with a particular media file in native code, such as a file that another app has shared with your app or a media file from the user's media collection. In these cases, begin your media file discovery in your Java-based or Koltin-based code, then pass the file's associated file descriptor into your native code. The following code snippet shows how to pass a media object's file descriptor into your app's native code: Uri contentUri = ContentUris.withAppendedId( android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, cursor.getLong(Integer.parseInt(BaseColumns._ID))); String fileOpenMode = "r"; ParcelFileDescriptor parcelFd = resolver.openFileDescriptor(uri, fileOpenMode); if (parcelFd != null) { int fd = parcelFd.detachFd(); // Pass the integer value "fd" into your native code. Remember to call // close(2) on the file descriptor when you're done using it. }
To learn more about accessing files in native code, see the Files for Miles talk from Android Dev Summit '18, starting at 15:20. Update other apps' media filesNote: Expect the following behavior to take effect in a future beta release of Android Q. To modify a given media file that another app originally saved to an external storage device, catch the Location information in picturesSome photographs contain location information in their Exif metadata, which allows users to view the place where a photograph was taken. Because this location information is sensitive, Android Q by default hides this information from your app if it has a sandboxed view into external storage. This restriction to location information is different from the one that applies to camera characteristics. If your app needs access to a photograph's location information, complete the following steps:
An example of this process appears in the following code snippet: Uri photoUri = Uri.withAppendedPath( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, cursor.getString(idColumnIndex)); final double[] latLong; // Get location data from the ExifInterface class. photoUri = MediaStore.setRequireOriginal(photoUri); InputStream stream = getContentResolver().openInputStream(photoUri); if (stream != null) { ExifInterface exifInterface = new ExifInterface(stream); double[] returnedLatLong = exifInterface.getLatLong(); // If lat/long is null, fall back to the coordinates (0, 0). latLong = returnedLatLong != null ? returnedLatLong : new double[2]; // Don't reuse the stream associated with the instance of "ExifInterface". stream.close(); } else { // Failed to load the stream, so return the coordinates (0, 0). latLong = new double[2]; }
Column names in content queriesIf your app's code uses a column name projection, such as If your code depends on a library that expects a column name that's undefined in the Android API, such as Android Q privacy change: Restrictions to background activity startsAs of Android Q Beta 3, this change has the following properties:
We're interested in hearing your feedback! Report issues you find when using this feature during the Android Q beta program. Android Q places restrictions on when apps can start activities. This behavior change helps minimize interruptions for the user and keeps the user more in control of what's shown on their screen. This behavior change applies to all apps running on Android Q, even those that target Android 9 (API level 28) or lower. In addition, even if your app targets Android 9 or lower and is originally installed on a device running Android 9 or lower, the behavior change still takes effect after the device is upgraded to Android Q. As long as your app starts activities as a direct result of user interaction, however, your app most likely isn't affected by this change. In fact, the majority of apps are unaffected by this change. Note: If you find that your app is affected, send us feedback. Conditions that allow for activity startsApps running on Android Q can start activities only when one or more of the following conditions are met:
Note: In a future beta release of Android Q, apps that have been granted the Warning messagesIf your app is running the latest beta version of Android Q and tries to launch an activity from the background, the platform sends a warning message to logcat and displays the following warning toast message: Background activity start from package-name blocked.
The restrictions associated with starting activities in the background in Android Q are similar to how the system blocks activity launches after the device has entered a screen pinning state. Note: The warning toast will not appear in the public release of Android Q. Create notifications for time-sensitive eventsIn nearly all cases, apps that are in the background should create notifications to provide information to the user instead of directly starting an activity. In specific cases, your app might need to get the user's attention urgently, such as an ongoing alarm or incoming call. You might have previously configured your app to launch a background activity for this purpose. To provide the same behavior on a device running Android Q, complete the steps shown in the following sections. Create a high-priority notificationWhen creating the notification, make sure that you include a descriptive title and message. Optionally, you can also provide a full-screen intent. An example notification appears in the following code snippet: val fullScreenIntent = Intent(this, CallActivity::class.java) val fullScreenPendingIntent = PendingIntent.getActivity(this, 0, fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT) val notificationBuilder = NotificationCompat.Builder(this, CHANNEL_ID) .setSmallIcon(R.drawable.notification_icon) .setContentTitle("Incoming call") .setContentText("(919) 555-1234") .setPriority(NotificationCompat.PRIORITY_HIGH) .setCategory(NotificationCompat.CATEGORY_CALL) // Use a full-screen intent only for the highest-priority alerts where you // have an associated activity that you would like to launch after the user // interacts with the notification. Also, if your app targets Android Q, you // need to request the USE_FULL_SCREEN_INTENT permission in order for the // platform to invoke this notification. .setFullScreenIntent(fullScreenPendingIntent, true) val incomingCallNotification = notificationBuilder.build()
Display the notification to the userWhen displaying your notification to the user, they can then choose, based on their current context, whether to acknowledge or dismiss your app's alert or reminder. For example, the user can choose whether to accept or reject an incoming phone call. If your notification is an ongoing one, such as an incoming phone call, associate the notification with a foreground service. The following code snippet shows how to display a notification that's associated with a foreground service: // Provide a unique integer for the "notificationId" of each notification. startForeground(notificationId, notification)
Note: The system UI may choose to display a heads-up notification, instead of launching your full-screen intent, while the user is using the device. Benefits of notificationsThis notification-based alert and reminder system provides several advantages for users:
Disable the behavior changeIt's recommended that you keep this behavior change enabled. That way, you can be more confident that users can continue interacting with your app as expected when Android Q is installed on their devices. If this change prevents you from testing a core workflow in your app, however, you can disable the behavior change during testing by completing one of the following tasks:
Note: After Android Q is released to the public, this developer option will continue to be available.
Android Q privacy change: User control over app access to device locationAs of Android Q Beta 3, this change has the following properties:
We're interested in hearing your feedback! Report issues you find when using this feature during the Android Q beta program. Figure 1. Dialog requesting user consent for locationAndroid 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, Request background locationIf your app targets Android Q and needs to access the device 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:
Caution: Although your app can request and receive the Request background location accessNote: This section applies to all apps running on Android Q, regardless of which version they target. 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:
Continuation of user-initiated actionNote: If your app doesn't require location access while running in the background, it's a best practice to target Android Q and not request the new background location permission. That way, your app only receives location updates while it's in use. An example of such an app appears in the LocationUpdatesForegroundService project on GitHub. 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 device's location in this specific use case, start a foreground service that you've declared as having a foreground service type of <service android:name="MyNavigationService" android:foregroundServiceType="location" ... > ... </service>
Before starting the foreground service, make sure that your app still has access to the device's location: 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 device's locationYour app might have a use case that requires access to the device'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 device's location "all the time" in order to run successfully.--> <service android:name="MyFamilyLocationSharingService" ... > ... </service>
An example of such an app is the LocationUpdatesPendingIntent project on GitHub. Figure 2. Notification reminding user that they've granted an app "all-the-time" access to device locationEach time the user chooses to allow your app all-the-time access to device location, the system schedules a notification to send to the user. This notification reminds the user that they've allowed your app to access device location all the time. An example notification appears in Figure 2. 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 a workflow within 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 3 appears: Figure 3. Dialog requesting user consent for all-the-time access to locationAn example of this permission-checking logic appears in the following code snippet: 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 device'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); }
Design for device upgrade scenariosIf a user completes the following steps:
...then the system automatically updates your app's default location permission state based on its target SDK version and its defined permissions, as shown in the following table: Table 1. Changes in location permission state after device upgrade to Android Q
Note: Even after the system automatically updates your app's access to device location, the user has the option to change this level of access. The user might reduce your app's access to foreground only or revoke access entirely. For this reason, before accessing the device's location updates, follow best practices to check whether the user still allows your app to receive this location information. Follow location best practicesBy checking and requesting location permissions in the ways shown in this guide, your app can successfully keep track of its level of access to device location. For more information about how to keep your users' data safe, see the permissions best practices guide. Ask only for the permissions you needAsk for permissions only when needed. For example:
Support graceful degradation if permission isn't grantedTo maintain a good user experience, design your app so that it can gracefully handle the following situations:
Additional resourcesFor more information about changes regarding an app's access to device location, see the following additional resources: Samples
Android Q privacy: Changes to data and identifiersThis document describes several restrictions placed on accessing data and system identifiers. These changes help protect users' privacy. Some of these changes affect all apps running on Android Q while other changes affect only apps that target Android Q. Changes affecting all appsThe following changes affect all apps running on Android Q, even if they target Android 9 (API level 28) or lower. Contacts affinityStarting in Android Q, the platform no longer keeps track of contacts affinity information. As a result, if your app conducts a search on the user's contacts, the results are no longer ordered by frequency of interaction. The Contacts Provider guide contains a notice describing the specific fields and methods that are obsolete on all devices as of Android Q. Randomized MAC addressesDevices running on Android Q transmit randomized MAC addresses by default. If your app handles an enterprise use case, the platform provides several new APIs:
Access to /proc/net filesystemAndroid Q removes access to Non-resettable device identifiersStarting in Android Q, apps must have the
Note: If your app is the device or profile owner app, you need only the If your app uses non-resettable device identifiers for ad-tracking or user analytics purposes, create an Android Advertising ID for those specific use cases instead. To learn more, see best practices for unique identifiers. Access to clipboard dataUnless your app is the default input method editor (IME) or is the app that currently has focus, your app cannot access clipboard data. Changes affecting apps targeting Android QThe following change affects apps only if they target Android Q. Access to USB serial requires user permissionIf your app targets Android Q, your app can only read the serial number after the user has granted your app permission to access the USB device or accessory.
Android Q privacy: Changes to camera and connectivityThis document describes several restrictions placed on accessing camera and connectivity information. These changes help protect users' privacy. Some of these changes affect all apps running on Android Q while other changes affect only apps that target Android Q. Changes affecting all appsThe following change affects all apps running on Android Q, even if they target Android 9 (API level 28) or lower. Access to all camera information requires permissionAndroid Q changes the breadth of information that the If your app doesn't have the
Changes affecting apps targeting Android QThe following changes affect apps only if they target Android Q. Restriction on enabling and disabling Wi-FiApps targeting Android Q cannot enable or disable Wi-Fi. The If needed, use a settings panel to prompt users to enable and disable Wi-Fi. Wi-Fi network configuration restrictionsTo protect user privacy, manual configuration of the list of Wi-Fi networks is now restricted to system apps and device policy controllers (DPCs). A given DPC can be either the device owner or the profile owner. If your app doesn't fall into one of these categories and targets Android Q, the following methods no longer return useful data:
If your app needs to connect to Wi-Fi networks, use the following alternative methods:
Fine location permission needed for telephony, Wi-Fi, Bluetooth APIsUnless your app has the Note: If your app is running on Android Q but targets Android 9 (API level 28) or lower, you can use the affected APIs as long as your app has the Telephony
Wi-Fi
Bluetooth
|