Storage updates in Android 11

Android 11 further enhances the platform, giving better protection to app and user data on external storage. The preview release introduces several enhancements that were announced last year at Android Dev Summit, such as opt-in raw file path access for media, batch edit operations for media, and an updated UI for the Storage Access Framework.

To help ease the transition to using scoped storage, the platform introduces further improvements for developers. To learn more about how to migrate your app to using scoped storage based on your app's use cases, see the scoped storage section on this page, the Android storage use cases and best practices guide, and the Medium article titled Modern User Storage on Android.

As always, we invite you to provide feedback to help shape the next version of Android. Use the issue tracker to send us your comments.

We're interested in hearing your feedback! Please take this short survey to let us know how you're using the feature. In particular, tell us about use cases impacted by this feature.

Scoped storage enforcement

To give developers additional time for testing, apps that target Android 10 (API level 29) can still request the requestLegacyExternalStorage attribute. This flag allows apps to temporarily opt out of the changes associated with scoped storage, such as granting access to different directories and different types of media files. After you update your app to target Android 11, the system ignores the requestLegacyExternalStorage flag.

Maintain compatibility with Android 10

If your app opts out of scoped storage when running on Android 10 devices, it's recommended that you continue to set requestLegacyExternalStorage to true in your app's manifest file. That way, your app can continue to behave as expected on devices that run Android 10.

Migrate data to directories that are visible when using scoped storage

If your app uses the legacy storage model and previously targeted Android 10 or lower, you might be storing data in a directory that your app cannot access when the scoped storage model is enabled. Before you target Android 11, migrate data to a directory that's compatible with scoped storage. In most cases, you can migrate data to your app-specific directory.

If you have data to migrate, it's possible to preserve the legacy storage model when a user upgrades to the new version of your app that targets Android 11. That way, the user retains access to app data that's stored in directories where your app had previously saved the data. To enable the legacy storage model for an upgrade, set the preserveLegacyExternalStorage attribute to true in your app's manifest.

Note: Most apps shouldn't need to use preserveLegacyExternalStorage. This flag is designed only for the situation where you migrated app data into a location that's compatible with scoped storage, and you want users to retain access to the data when updating your app. Using this flag makes it harder to test how scoped storage affects users of your app because when users update your app, it continues to use the legacy storage model.

If you use preserveLegacyExternalStorage, the legacy storage model remains in effect only until the user uninstalls your app. If the user installs or reinstalls your app on a device that runs Android 11, then your app cannot opt out the scoped storage model, regardless of the value of preserveLegacyExternalStorage.

Test scoped storage

To enable scoped storage in your app, regardless of your app's target SDK version and manifest flag values, enable the following app compatibility flags:

To disable scoped storage and use the legacy storage model instead, unset both flags.

Manage device storage

On Android 11, apps that use the scoped storage model can access only their own app-specific cache files. If your app needs to manage device storage, do the following:

  1. Check for free space by invoking the ACTION_MANAGE_STORAGE intent action.
  2. If there isn't enough free space on the device, prompt the user to give your app consent to clear all caches. To do so, invoke the ACTION_CLEAR_APP_CACHE intent action.

App-specific directory on external storage

On Android 11, apps cannot create their own app-specific directory on external storage. To access the directory that the system provides for your app, call getExternalFilesDirs().

Media file access

To make it easier to access media while retaining user privacy, Android 11 adds the following capabilities.

Perform batch operations

For consistency across devices and added user convenience, Android 11 adds several methods to the MediaStore API. These methods are particularly useful for apps that want a streamlined flow for modifying specific media files, such as editing a photo in-place.

The added methods are the following:

createWriteRequest()
Request that the user grant your app write access to the specified group of media files.
createFavoriteRequest()
Request that the user marks the specified media files as some of their "favorite" media on the device. Any app that has read access to this file can see that the user has marked the file as a "favorite".
createTrashRequest()

Request that the user place the specified media files in the device's trash. Items in the trash are permanently deleted after a system-defined time period.

createDeleteRequest()

Request that the user permanently delete the specified media files immediately, without placing them in the trash beforehand.

After calling any of these methods, the system builds a PendingIntent object. After your app invokes this intent, users see a dialog that requests their consent for your app to update or delete the specified media files.

For example, here is how to structure a call to createWriteRequest():

Kotlin

val urisToModify = /* A collection of content URIs to modify. */
val editPendingIntent = MediaStore.createWriteRequest(contentResolver,
        urisToModify)

// Launch a system prompt requesting user permission for the operation.
startIntentSenderForResult(editPendingIntent.intentSender, EDIT_REQUEST_CODE,
    null, 0, 0, 0)

Java

List<Uri> urisToModify = /* A collection of content URIs to modify. */
PendingIntent editPendingIntent = MediaStore.createWriteRequest(contentResolver,
                  urisToModify);

// Launch a system prompt requesting user permission for the operation.
startIntentSenderForResult(editPendingIntent.getIntentSender(),
    EDIT_REQUEST_CODE, null, 0, 0, 0);

Evaluate the user's response and either proceed or, if the user did not consent, explain to the user why your app needs the permission:

Kotlin

override fun onActivityResult(requestCode: Int, resultCode: Int,
                 data: Intent?) {
    ...
    when (requestCode) {
        EDIT_REQUEST_CODE ->
            if (resultCode == Activity.RESULT_OK) {
                /* Edit request granted; proceed. */
            } else {
                /* Edit request not granted; explain to the user. */
            }
    }
}

Java

@Override
protected void onActivityResult(int requestCode, int resultCode,
                   @Nullable Intent data) {
    ...
    if (requestCode == EDIT_REQUEST_CODE) {
        if (resultCode == Activity.RESULT_OK) {
            /* Edit request granted; proceed. */
        } else {
            /* Edit request not granted; explain to the user. */
        }
    }
}

You can use this same general pattern with createFavoriteRequest(), createTrashRequest(), and createDeleteRequest().

Access files using direct file paths and native libraries

To help your app work more smoothly with third-party media libraries, Android 11 allows you to use APIs other than the MediaStore API to access media files from shared storage. You can instead choose to access media files directly using either of the following APIs:

  • The File API.
  • Native libraries, such as fopen().

If your app doesn't have any storage permissions, you can access media files that are attributed to your app using direct file paths. If your app has the READ_EXTERNAL_STORAGE permission, it can access all media files using direct file paths, regardless of whether the files are attributed to your app.

If you access media files directly, it's recommended that you opt out of scoped storage by setting requestLegacyExternalStorage to true in your app's manifest file. That way, your app behaves as expected on devices that run Android 10.

Performance

When you perform sequential reads of media files using direct file paths, the performance is comparable to that of the MediaStore API.

When you perform random reads and writes of media files using direct file paths, however, the process can be up to twice as slow. In these situations, we recommend using the MediaStore API instead.

Available values from the media store

When you access an existing media file, you can use the value of the DATA column in your logic. That's because this value has a valid file path. However, don't assume that the file is always available. Be prepared to handle any file-based I/O errors that could occur.

To create or update a media file, on the other hand, don't use the value of the DATA column. Instead, use the values of the DISPLAY_NAME and RELATIVE_PATH columns.

Access to data from other apps

To protect user privacy, Android 11 further restricts your app's access to other apps' private directories.

Access to data directories on internal storage

Change details

Change Name: APP_DATA_DIRECTORY_ISOLATION

Change ID: 143937733

How to toggle

As you test your app's compatibility with Android 11, you can toggle this change on or off using the following ADB commands:

adb shell am compat enable (143937733|APP_DATA_DIRECTORY_ISOLATION) PACKAGE_NAME
adb shell am compat disable (143937733|APP_DATA_DIRECTORY_ISOLATION) PACKAGE_NAME

For more information about the compatibility framework and toggling changes, see Test your app's compatibility with Android 11.

Android 9 (API level 28) started to restrict which apps could make the files in their data directories on internal storage world-accessible to other apps. Apps that target Android 9 or higher cannot make the files in their data directories world-accessible.

Android 11 expands upon this restriction. If your app targets Android 11, it cannot access the files in any other app's data directory, even if the other app targets Android 8.1 (API level 27) or lower and has made the files in its data directory world-readable.

Access to app-specific directories on external storage

On Android 11, apps can no longer access files in any other app's dedicated, app-specific directory within external storage.

Document access restrictions

To give developers time for testing, the following changes related to the Storage Access Framework (SAF) take effect only if your app targets Android 11.

Access to directories

You can no longer use the ACTION_OPEN_DOCUMENT_TREE intent action to request access to the following directories:

  • The root directory of the internal storage volume.
  • The root directory of each SD card volume that the device manufacturer considers to be reliable, regardless of whether the card is emulated or removable. A reliable volume is one that an app can successfully access most of the time.
  • The Download directory.

Access to files

You can no longer use the ACTION_OPEN_DOCUMENT_TREE or the ACTION_OPEN_DOCUMENT intent action to request that the user select individual files from the following directories:

  • The Android/data/ directory and all subdirectories.
  • The Android/obb/ directory and all subdirectories.

Test the change

To test this behavior change, do the following:

  1. Invoke an intent with the ACTION_OPEN_DOCUMENT action. Check that the Android/data/ and Android/obb/ directories both don't appear.
  2. Do one of the following:
  3. Invoke an intent with the ACTION_OPEN_DOCUMENT_TREE action. Check that the Download directory appears and the action button associated with the directory is grayed out.

Permissions

Android 11 introduces the following changes related to storage permissions.

Target any version

The first dialog presents a link called Allow in settings
Figure 1. Dialog shown when an app uses scoped storage and requests the READ_EXTERNAL_STORAGE permission.

The following changes take effect in Android 11, regardless of your app's target SDK version:

  • The Storage runtime permission is renamed to Files & Media.
  • If your app hasn't opted out of scoped storage and requests the READ_EXTERNAL_STORAGE permission, users see a different dialog compared to Android 10. The dialog indicates that your app is requesting access to photos and media, as shown in Figure 1.

    Users can see which apps have the READ_EXTERNAL_STORAGE permission in system settings. On the Settings > Privacy > Permission manager > Files and media page, each app that has the permission is listed under Allowed for all files.

    Note: If your app targets Android 11, keep in mind that this access to "all files" is read-only. To read and write to all files in shared storage using this app, you need to have the all files access permission.

Target Android 11

If your app targets Android 11, both the WRITE_EXTERNAL_STORAGE permission and the WRITE_MEDIA_STORAGE privileged permission no longer provide any additional access.

Keep in mind that, on devices that run Android 10 (API level 29) or higher, your app can contribute to well-defined media collections such as MediaStore.Downloads without requesting any storage-related permissions. Learn more about how to request only the necessary permissions when working with media files in your app.

All files access

The majority of apps that require shared storage access can follow scoped storage best practices such as the Storage Access Framework or MediaStore API. However, some apps have a core use case that requires broad access of files on a device, but cannot do so efficiently using the privacy-friendly storage best practices.

For example, an anti-virus app's primary use case might require regular scanning of many files across different directories. If this scanning requires repeated user interactions to select directories using the system file picker, it may provide a poor user experience. Other use cases—such as file manager apps, backup and restore apps, and document management apps—may require similar considerations.

An app can request a special app access called All files access from the user by doing the following:

  1. Declare the MANAGE_EXTERNAL_STORAGE permission in the manifest.
  2. Use the ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION intent action to direct users to a system settings page where they can enable the following option for your app: Allow access to manage all files.

To determine whether your app has been granted the MANAGE_EXTERNAL_STORAGE permission, call Environment.isExternalStorageManager().

The MANAGE_EXTERNAL_STORAGE permission grants the following:

  • Read and write access to all files within shared storage.

  • Access to the contents of the MediaStore.Files table.

  • Access to the root directory of both the USB on-the-go (OTG) drive and the SD card.

  • Write access to all internal storage directories⁠, except for /Android/data/, /sdcard/Android, and most subdirectories of /sdcard/Android. This write access includes file path access.

    Apps that are granted this permission still cannot access the app-specific directories that belong to other apps because these directories appear as subdirectories of Android/data/ on a storage volume.

When an app has the MANAGE_EXTERNAL_STORAGE permission, it can access these additional files and directories using either the MediaStore API or file paths. When you use the Storage Access Framework, however, you can only access a file or directory if you could do so without having the MANAGE_EXTERNAL_STORAGE permission.

Enable for testing

To explore how the all files access permission affects your app, you can enable the permission for testing purposes. To do so, run the following command on the machine that's connected to your test device:

adb shell appops set --uid PACKAGE_NAME MANAGE_EXTERNAL_STORAGE allow

Google Play notice

This section provides a notice for developers who publish apps on Google Play.

To limit broad access to shared storage, the Google Play store has updated its policy to evaluate apps that target Android 11 and request All files access through the MANAGE_EXTERNAL_STORAGE permission.

You should request the MANAGE_EXTERNAL_STORAGE permission only when your app cannot effectively make use of the more privacy-friendly APIs, such as Storage Access Framework or the Media Store API. Additionally, the app's usage of the permission must fall within permitted uses, and must be directly tied to the core functionality of the app. If your app includes a use case that's similar to the following examples, it's likely to be allowed to request the MANAGE_EXTERNAL_STORAGE permission:

  • File managers
  • Backup and restore
  • Anti-virus apps
  • Document management apps

Due to COVID-19 related considerations, apps that target Android 11 and need the MANAGE_EXTERNAL_STORAGE permission cannot be uploaded to Google Play until early 2021. This includes new apps as well as updates to existing apps. To learn more, read the updated policy from the Policy Help Center.

For now, if you think the manage external storage permission is needed for your app, it's recommended that you don't update your target SDK to Android 11 at this time. If you target Android 10, consider using the requestLegacyExternalStorage flag.