Uri Access Lifetime: Still Shorter Than You Might Think
Almost exactly four years ago, I wrote about
issues with accessing content at a
That post is even more relevant now than it was back then, but the material
there is a bit out of date. So, here’s a new-and-improved look at the issue.
Your app gets a
Uri from some outside source. Perhaps you used
ACTION_OPEN_DOCUMENT to get a
Uri to some
user-selected content. Perhaps you have an activity with an
set up to respond to
ACTION_SEND or something, and
you got a
Uri that way.
How long can you use that
Uri to access the content that it points to?
Some developers think that you have indefinite access to it, and that
Uri value can be saved safely to persistent storage. For a
Uri, that might almost work, though the file could always be moved
However, you do not have long-term access to the content
identified by a
Uri. It is best to think of a
as being akin to an HTTPS URL to some content, where that content can
only be accessed if the session is authenticated (e.g., via a session
cookie). Just because you can download content from that URL today does
not mean that you can download content from that URL tomorrow, as the
session may well have timed out.
You might then think that you have access as long as your process is running, and that access rights lapse at that point. That’s what I originally thought… and that’s not right either.
Instead, only the component instance that received the
Uri can access the content.
And, for the
Intent actions that I listed, that means the
that receives the result can access the content… but not other activity instances
within your app, nor any services, etc.
For short-term use, you might hand the
Uri off to a repository.
The repository can load the content and deliver it to various components
of your app using a reactive API. Or you can consume the content directly
in the receiving activity in other ways, such as handing a
Uri to an image
to your favorite image-loading library (e.g., Glide, Picasso, Coil).
If you absolutely need to get the
Uri to another activity in your app:
Attach it to the
Intentyou use to start that other activity via
Intentbased on what the other activity needs to do
This extends the permission that your first activity has to the second activity, so it
too can access the content. The same basic approach would hold true for getting the
Uri to a
If you need durable access — such as being able to access the content tomorrow — you have two main options that I know of:
If you used
ACTION_CREATE_DOCUMENT, or similar Storage Access Framework actions, you can try using
ContentResolverto get long-term access to the content.
Otherwise, before your component is destroyed, make a local copy of the content in your app’s portion of internal storage (e.g.,
getCacheDir()). This approach sucks, as it duplicates the content, and changes to the original edition of the content will not be reflected in the copy. Use appropriate UI terms (e.g., “import”) to help the user understand that this is what is going on.