Storage Shifts
Android 10 introduced what Google calls “scoped storage” and what the author of this book called “the death of external storage”.
Android 11 tweaks scoped storage some more, improving things in some areas and causing new and exciting challenges in others.
Recapping What Happened in Android 10
Before we dive into the Android 11 changes to scoped storage, let’s quickly review what happened in Android 10.
You can learn more about scoped storage in Android 10 in the "The Death of External Storage" chapter of Elements of Android Q!
Limited Filesystem Access
While apps can still use getExternalFilesDir() and other methods on Context to work with external and removable storage, everything else has been blocked. Notably, the methods on Environment like getExternalStorageDirectory() and getExternalStoragePublicDirectory() are deprecated. And, if you try to use those directories, you will find that your app lacks access, even if you hold READ_EXTERNAL_STORAGE and/or WRITE_EXTERNAL_STORAGE.
Roughly speaking, there are three alternatives for addressing this limitation.
Alternative #1: Storage Access Framework
For general-purpose content, Google expects you to use the Storage Access Framework:
-
ACTION_OPEN_DOCUMENTto have the user choose a piece of content -
ACTION_CREATE_DOCUMENTto create a new piece of content in a user-chosen location -
ACTION_OPEN_DOCUMENT_TREEto have the user choose a “document tree” (e.g., a directory) that you can then use for reading and writing
The actual mechanics of the Storage Access Framework did not change in Android 10, merely its importance.
Alternative #2: MediaStore
For apps that work with media and wish to place content in common media locations, MediaStore is still an option. However, the behavior of MediaStore changed some in Android 10 and again in Android 11 — we will explore that more in the next chapter.
Alternative #3: Opt Out of the Change
You could add android:requestLegacyExternalStorage="true" to the <application> element in the manifest to say that you want the “legacy” storage model. In other words, android:requestLegacyExternalStorage="true" has your app running on Android 10 behave much as it would on Android 9.
Alternatively, simply having a targetSdkVersion below 29 would give you the same effect.
Prev Table of Contents Next
This book is licensed under the Creative Commons Attribution-ShareAlike 4.0 International license.