With the recent years of Android platform updates, the storage model has evolved. Starting Android 10 (API 29), the model has become purpose-focused rather than location-focused. We’ll get to that in a bit. But first, let’s understand the back story.
Anyone who has saved files on local storage, be it SQLite database or in form of other files, has declared READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE permissions. The premise was simple. Any app that wants to read files stored on the file system will request READ_EXTERNAL_STORAGE permission and the same for write permission. This gave apps access to a broader spectrum of file locations.
For the majority of the apps, this level of access might not be needed. In this new age of privacy, users get spooked easily when it comes to asking permissions and starting Android 10 (API 29), this is exactly what the team sought out to solve.
Android storage model has now been revamped to avoid asking users permission for storage access by providing some level of access by default. Apps can now read/write into their app-specific directories without asking users. This gives apps scoped access to storage.
IMPORTANT! Internal storage works as expected. Apps can access their app-specific directory without any restrictions.
- Files are now attributed to the apps which created/edited them. This means photos clicked by a camera app will be attributed to the same app and it doesn’t need any permissions to access/edit these files.
- As an effort to reduce disk clutter, dedicated file directories for images, videos, audio, downloads, etc will be used in shared storage.
- Access to the top-level directories in shared storage is not available anymore. If any app uses a custom top-level directory, it is highly recommended to move to app-specific directories in the default folders.
Environment.getExternalStorageDirectory()API is now deprecated. The path returned by this will not be accessible and Android Studio will also warn when targeting API 29 and above.
- Runtime permission now gives only read access to media.
On Android 10, any access to media files will only work with MediaStore APIs. Any file path-based APIs like
File will not work. However, after taking feedback from the community, this behavior has been reversed in Android 11. The level of access will still be scoped however file path-based APIs can be used.
To work with
File APIs on Android 10,
requestLegacyExternalStorage manifest flag will have to be used.
🚧 NOTE: This flag will not work on Android 11 and all apps must make changes according to scoped storage.
Location Meta-data 📍
Location meta-data associated with files is now gated behind a new permission
By default, the location params will not be included in the
ExifInterface API. LATITUDE and LONGITUDE columns in the MediaStore will also return
null on API 29 and above.
All Files access
There are apps like file managers and backup apps which are supposed to have wide access to storage and users rely on them to perform certain operations. For such use cases, new permission i.e.
MANAGE_EXTERNAL_STORAGE has been introduced.
- This permission gives write access to all shared files.
- Since this is special permission, the apps using this permission will be subject to a manual Google Play review. The review team will decide if this permission is actually required or if scoped storage might also work.
- This permission will have to be manually enabled by the users from settings.
For actual code samples, you can head on to the below resources for a clearer understanding.
- Preparing for scoped storage (Android Dev Summit ‘19)
- Storage access with Android 11
- What’s new in shared storage (Google I/O’19)
- Files for miles: Where to store them all? (Android Dev Summit ‘18)
- Android Developers Guide
I have also created a sample app on GitHub which implements some file operations on Internal and Shared storage. You can try this app on different API levels to see how different operations are affected.
Hope this article helped in getting a gist of changes and hoped you learned something!