All You Need to Know About Scoped Storage in Android 10
The future of in-app storage on Android devices is here
Scoped storage is the newly introduced storage system by Android. But before diving into scoped storage, let us first discuss what shared storage is and its requirements in Android.
- All apps have their own private directory in internal storage, i.e Android/data/your package name, not visible to other apps.
- Most of the current apps require broad storage permissions to perform simple functions. For example, downloading an image or as an image picker, etc. At the time of uninstalling the app, most of the time, files don’t get deleted. This results in insufficient storage.
Android 10 comes up with a solution: scoped storage.
What Is Scoped Storage?
- It’s a concept of storing files, images, etc. separately, called Collections, which restrict the conventional access of the whole storage.
- Better attribution: This means that the system knows which app created which file. It is useful when the app is uninstalled, so all the data related to the app is also uninstalled.
- Protecting app data: Internal app directories and external app directories are private.
- Protect user data: The downloaded image cannot be used by another app.
- Unrestricted access to its individual app storage (internal/external): No permission required.
- Unrestricted access to media files and download collections: E.g. Save the image file without permission.
- Only media collections can be read with storage permissions.
- Location metadata
ACCESS_MEDIA_LOCATIONfor the location of the image.
- For files like PDFs, text, etc. use System Picker.
- Reading and writing outside of a collection requires the “System Picker”.
How Do We Implement It?
ACTION_OPEN_DOCUMENTto select a file.
ACTION_OPEN_DOCUMENT_TREEto select a folder: This will ask for permission in Android 10, for full access to that folder.
- Content access using raw file paths.
- Save image file using the MediaStore API.
The purpose of using the IS_PENDING flag in MediaStore
When you insert an item that is marked as pending intent (value 1), by default, it will be hidden from other apps on the device.
This can be used when you use long-running downloads like video downloading from a URL. Once the download is completed, set the pending intent to 0 to reveal it to other apps to the device.
- In the above example, we have not set/specified the path to store the image, so the OS automatically chooses the path based on the file type. Here, we took the image/JPEG, so it will store the image to the pictures folder by default.
- You can also choose the file path with
VOLUME_EXTERNAL_PRIMARYto store in primary storage. And to get list of storages available on the phone use
- Upon getting a document URI returned, we can use it.
[ContentResolver.takePersistableUriPermission]to persist the permission across restarts.
- If your app uses scoped storage, raw file path access is limited to the app-specific directories in external storage, even if your app has been granted the
READ_EXTERNAL_STORAGEpermission. If your app attempts to use a raw path to open a file within external storage that doesn’t reside in the app-specific directory, a
FileNotFoundExceptionoccurs. For example, the path for a file outside the app-specific directory is
/sdcard/DCIM/ABC.JPG. Instead, your app should use methods in the MediaStore API.
- In Android Q and above, it isn’t possible to modify or delete items in MediaStore directly, and explicit permission must usually be obtained to do this. The way it works is that the OS will throw a
RecoverableSecurityException, which we can catch here. Inside, there’s an
IntentSenderwhich the activity can use to prompt the user to grant permission to the item so it can be either updated or deleted.
Manifest file, we can still add that we want to use the permission access like in lower versions than Android 10. But it is only used by 2% of Android apps, and it is also going to be deprecated in the next version of Android.
Manifest flag default value is “
true” for apps targeting Android 9 (and lower).
- It is runtime permission (not visible in settings).
- No guarantees that you will always have this permission even if you have
- To get an exact number of bytes of files, Use
MediaStore.setReqiuedOriginal(), if it isn’t a success then an exception occurs.
Modify and Delete Media Resources
- User concerns needed while editing or deleting media resources.
- Consent required even for file path access.
- Bulk edit/delete in the same dialog (next Android release).
Dos and Don’ts
- Don’t use a static path. Lock down the file path access.
- Use MediaStore (recommended).
- MediaStore should be used properly, for example, don’t put your music files in the picture directory.
- Non-media files should be in the download directory (recommended).
Special App Access
- Only apps granted by Google will have complete access to storage.
- Submit the declaration form to Google Play.
- Whitelisted apps by Google.
Next Release Changes
- Update to permission UI: User will see a different permission UI based on updates and whether they’re using scoped storage or not. I.e., before, ten apps would see board access to storage and after, ten media collections have access to storage.
- Enable file path and native libraries for reading media.
- Updating media file and modifying APIs.
- Protecting external app directories.
- Enforcement to target SDK.
- Read files not created by your app need
- To edit and delete files not contributed by your app, you need explicit user concern.
WRITE_EXTERNAL_STORAGEwill be deprecated in the next Android release and will give read permission only when used.
Non-media file access
To access non-media files by other apps, use System Picker with SAF( Storage Access Framework). Runtime permission will be requested for complete access to that app.
Things to Remember
If Android 10 is within the scope of your application, kindly use MediaStore and System Picker for file and document access.
Have a look at the scoped storage example: