Scoped Storage Stories: DocumentFile
Android 10 is greatly restricting access to external storage
via filesystem APIs. Instead, we need to use other APIs to work with content.
This is the third post in a series where we will explore how to work with those
alternatives, starting with the Storage Access Framework (SAF).
Whether you use ACTION_OPEN_DOCUMENT or ACTION_CREATE_DOCUMENT, you wind up
with a Uri that points to the ���document���. Your primary use of that Uri is
with ContentResolver and its openInputStream() and openOutputStream() methods,
so you can read and/or write the document. This is not that different from having
a File and using the FileInputStream and FileOutputStream constructors to
be able to read and/or write the document.
However, File has a lot of other useful methods, such as:
getName() to get the filename
exists() to confirm that an actual file exists at the path wrapped by the File
delete() to delete the file
and so on
The way to get similar functionality for your document Uri is
via DocumentFile.
DocumentFile can wrap a File or a document Uri and give you an API that
resembles a subset of File functionality, including the three methods that I listed
above.
If you have a document Uri, you can wrap it in a DocumentFile via
DocumentFile.fromSingleUri(). You can then call getName(), exists(), delete(),
and other methods, such as:
getType() to get the MIME type associated with the content
length() to get the length of the content (i.e., how many bytes you could read in
from the InputStream)
renameTo() to rename the content
and so on
However, there are some limitations:
The ���name��� for a piece of content is not necessarily a filename with an extension.
It is a ���display name���, and it should be something that the user might recognize.
However, if you are expecting SomethingLike-This.png, you may be disappointed. The
display name might be a classic filename, but it does not have to be.
canWrite() is somewhat broken, in that
it may return true for a Uri that you cannot write to
Note that you can also get a DocumentFile for a File via DocumentFile.fromFile().
This allows you to treat document Uri values and files the same, so that portions
of your app can be written independently of where the data comes from.
Previously, I covered:
The basics of using the Storage Access Framework
Getting durable access to the selected content
In my next post in this series��� while I am not
the Lorax, I will speak for the
(document) trees.


