Virtual Files FAQ (Sorta)
I largely ignored virtual files with the N Developer Previews, because what little documentation exists is self-contradictory. I couldn’t figure out why anyone would care about them, and the lack of documentation suggests that Google does not care much about them, so why worry?
But, an Ian Lake Stack Overflow answer scared me, which is why I have poked around a bit at virtual files to come up with this set of fictionally-asked questions. Hopefully, these will help frame the role of virtual files plus highlight some of the places where we have “known unknowns” regarding them.
What is a Virtual File?
A virtual file is an extension on an existing under-discussed concept
in Android: a
Uri does not have to map to anything directly
usable by arbitrary apps.
Say What, Now?
Uri is a largely-opaque identifier, representing some piece of content
(or, occasionally, a collection of content). Roughly speaking, you can
divide the uses of a
Uri into two groups:
The app holding the
Urineeds the actual content itself, such as needing the bytes of an image to decode into a
Bitmapand show in an
The app holding the
Uriis merely an intermediary, getting the
Urifrom one place (e.g.,
MediaStore) and passing it to another place (e.g., an
ACTION_VIEW-supporting activity that happens to handle the content type identified by that
Uri representing a virtual file can only be used in the second scenario.
You cannot get at the content of a virtual file.
Why Does the Documentation Say That We Should Get a Stream, Then?
Our primary documentation on Android 7.0’s virtual files — all five paragraphs of it — has:
The virtual files feature allows your DocumentsProvider to return document URIs that can be used with an ACTION_VIEW intent even if they don’t have a direct bytecode representation.
It also has:
Since an app cannot directly open a virtual file by using the openInputStream() method, your app does not receive any virtual files if you include the CATEGORY_OPENABLE category.
However, it then has:
Your app can retrieve the URI of the virtual file and get an input stream
Other evidence, such as puttering around the Android source code, suggests that the first two statements are correct. Besides, there are two of those, and only one contradicting it, and so majority rules, right?
What Can You Do With a Virtual File?
Use it with an
Intent. No other use cases are documented,
as far as I can tell.
What’s This About
The Storage Access Framework documentation
has long suggested that you
CATEGORY_OPENABLE to your
ACTION_OPEN_DOCUMENT and related
The documentation for
indicates that the
role of this category is to limit responses to those where you get a
openInputStream() and related methods on
What is implied by the virtual files “documentation” is that if you only
Uri, and not the content, you could skip
and the user might have more choices of where to pick content from.
I am Using
ACTION_GET_CONTENT, So This Doesn’t Concern Me, Right?
Wrong. That’s what scared me about
Ian Lake’s Stack Overflow answer
that I mentioned earlier. According to him,
CATEGORY_OPENABLE might return a
Uri that represents a virtual file.
This is perfectly reasonable from the documentation, but I have not seen
very many examples of
I have not seen where anyone ran into a case where
Uri that could not be opened.
Are There Other Intent Actions For Which CATEGORY_OPENABLE Applies?
ACTION_CREATE_DOCUMENT are the three
Intent actions for which
is documented to apply.
Beyond that, I have no idea.
In principle, any
Intent action that is documented to return a
Uri, such as
should be subject to the same rules. However, some developers may not have
CATEGORY_OPENABLE on their
<intent-filter>, even though they return openable
Also, note that there are
Uri values other than those for virtual
files that cannot be opened. For example, the
Uri for a contact
is not openable. Hence, the standard Contacts app does not have
CATEGORY_OPENABLE on its
Is Anyone Serving Virtual Files?
Until this gets better documentation, hopefully nobody is.
In reality, Google rarely adds something to Android without a vision in mind, so I would not be the least bit surprised if an app like Google Drive started offering up virtual files.
Why Would I Want to Receive a Virtual File?
If your app supports the notion of linking your own content to other content accessible to the user, expanding your scope to include virtual files may give the user more possible things to link.
However, since you do not have access to the actual content, you cannot upload that content to a server. Hence, this is only good for an on-device link feature, not an “attach”, “import”, or other verbs that implies that your app has access to the content itself. In particular, it is not useful for cases where the user might be working with your app’s data somewhere other than the original device (e.g., a Web app).
OK, So What Really Changed in Android 7.0?
DocumentsProvider — the source of the content that the user
browses in the Storage Access Framework UI —
for the metadata on a document, to indicate that it is a virtual document
and should be filtered out for clients requesting openable
So, What Should I Do?
If you are using
ACTION_GET_CONTENT, and you are trying to use the
content itself (e.g., you pass the
Uri to Picasso to populate an
CATEGORY_OPENABLE to your
Experts might start contemplating where requesting virtual files, or
possibly serving them from
ACTION_GET_CONTENT or a
might be useful for their apps.
Beyond that, sit tight, and wait for more documentation.
(note: it might be a long wait, so be sure to pack a lunch)
Learn second-generation Android app development — with Kotlin and the Android Jetpack — through CommonsWare’s Android app development training!