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:


Prev Table of Contents Next

This book is licensed under the Creative Commons Attribution-ShareAlike 4.0 International license.