Adapting to Scoped Storage
One way or another, it seems likely that apps will be given filtered external storage eventually. While opting out is a good tactical decision, you need to plan out your work to discontinue or minimize your use of external storage. This is particularly true if you want to have files that remain on the device after your app is uninstalled.
Consuming Content
Perhaps there is content that already exists that you want to be able to read in. You might even want to modify that content yourself, if appropriate.
ACTION_OPEN_DOCUMENT
The best general-purpose solution is the Storage Access Framework. Specifically, for existing content, ACTION_OPEN_DOCUMENT
is the Android equivalent of the “file open” dialogs that you might see on other platforms. The biggest difference is that you are really opening content, not files.
Offering the user the opportunity to pick a piece of content is merely a matter of a single startActivityForResult()
call:
startActivityForResult(
Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE); type = "*/*"
},
REQUEST_DOC
)
If there is a particular MIME type associated with your desired content, use that in place of */*
.
In onActivityResult()
, if the result is for your request code (RESULT_DOC
here) and the result code is RESULT_OK
, then the Intent
should have a Uri
that points to the piece of content. You can use that directly with ContentResolver
and methods like openInputStream()
/openOutputStream()
. And you can use DocumentFile.fromSingleUri()
to create a DocumentFile
to help you get at things like a display name or the content’s length in bytes.
Inbound Actions
You might also consider setting up a suitable activity to support ACTION_VIEW
and/or ACTION_SEND
. Then, in onCreate()
and onNewIntent()
, you can get the Uri
that the user wished your app to view or send. At that point, you can use ContentResolver
, though perhaps not DocumentFile
, to work with the content.
Other Options
If you need access to images, audio files, or video files, the next chapter will give you some additional options.
There are also a variety of miscellaneous ways to get Uri
values from the user, by way of other apps, such as the clipboard and drag-and-drop.
Creating Content
Perhaps you want to create new content from scratch, rather than working with something that already exists.
Filesystem… Maybe
You are welcome to still use getExternalFilesDir()
and similar methods on Context
. This requires the user to navigate into Android/data/.../files/
— where ...
is your application ID — in order to get access to those files. That is not particularly user-friendly.
ACTION_CREATE_DOCUMENT
ACTION_CREATE_DOCUMENT
works much like ACTION_OPEN_DOCUMENT
, except that you will get a Uri
where you can create a new piece of content, rather than it pointing to an existing piece of content. This offers the user the most flexibility and is not that difficult to use for most cases.
Media
If you wish to save images, audio files, or video files for the user, MediaStore
and related classes may be relevant options.
Sharing Content
If you want to get your content to another app directly, such as via ACTION_VIEW
or ACTION_SEND
, your only options in a world of scoped storage are:
-
FileProvider
(or equivalentContentProvider
implementations) MediaStore
Prev Table of Contents Next
This book is licensed under the Creative Commons Attribution-ShareAlike 4.0 International license.