The Death of External Storage: More of the Story
A month ago, I wrote a blog post about the changes in external storage on Android Q.
I intentionally skipped one finding, because it really seemed like a bug. However, apparently, it is working as intended.
So, let’s revisit what you can do with the external storage filesystem in Android Q.
And, as a reminder: unless Google changes things, these rules affect all apps,
targetSdkVersion (except for apps already installed on a device that
gets the Q upgrade).
UPDATE 2019-05-13: Google changed things.
UPDATE 2019-06-08: With Q Beta 4 out, the story is now much simpler. I am leaving the original post here for historical reasons.
Where Can You Write?
UPDATE 2019-04-28: The behavior of
is more complicated than that.
However, you can:
Create files in the root of external storage (
Create directories in the root of external storage
Create files in those directories that you created
Basically, if it already exists — such as directories that were created as part of setting up the device — you have no write access. If you create it yourself, though, you do have write access.
What Can You Read?
If you wrote it, you can read it.
However, that is it. You cannot read the contents of files or directories that were created by other means, using filesystem APIs.
What Permissions Do You Need?
No, Seriously, What Permissions Do You Need?
None. This was the part that I thought was a security bug.
If you have
targetSdkVersion 'Q', or if you have
targetSdkVersion 28, you can
write to the root of external storage and read back what you wrote, without any
this holds true for at least some older
targetSdkVersion values, but I only
tested these two.
The reason why
WRITE_EXTERNAL_STORAGE are deprecated
is that all of external storage — except for existing files and directories —
- You do not need any permissions
- What you create is removed when the app is uninstalled or if the user clears storage for the app
What Can Other Apps Do With Your Files?
What you create and write in external storage via the filesystem is inaccessible to other apps via the filesystem, no matter where it is.
What you create in
getExternalFilesDir() will be accessible via the Storage
Access Framework, but what you create in the root of external storage is not.
As a result, anything you put in the root of external storage (or custom directories
off of the root) is private to your app, except to the extent that you expose
FileProvider or something.
What About the User and a USB Cable?
Similarly, what happens here depends on which portion of the external storage filesystem that you use.
getExternalFilesDir() and kin:
Files and directories that you create are visible to the user
Files and directories that the user creates are visible to you
For the root of external storage:
Files and directories that you create are not visible to the user (
MediaScannerConnectionseems to not work for those files, and
ACTION_MEDIA_SCANNER_SCAN_FILEhas been deprecated with no stated replacement)
Files and directories that the user creates are not visible to you
Even as a developer,
adb does not show app-created files in the external storage root
directory. Nor does Android Studio’s Device File Explorer.
So, What Should I Do Now?
In general, my previous recommendations still hold up:
Use the methods on
getExternalFilesDir()to find places to write, if you need to make the files available to the user via USB
Use the Storage Access Framework
FileProviderto make your content available to other apps for outbound requests (e.g.,
If applicable, support
ACTION_SENDin your manifest, so other apps can use those
Intentactions to send you content
If you have existing code that writes files to the root of external storage or
some custom directory off of it, that code will continue to run. However, the user
will be unable to access those files, except through your app. In general, it
will be better to migrate those to
getExternalFilesDir(), if user access to those
files is important.
It is entirely possible that there are yet other combinations, scenarios, and mysteries yet to be discovered. The key is that you should test your app early and often on Android Q.
Learn second-generation Android app development — with Kotlin and the Android Jetpack — through CommonsWare’s Android app development training!