PSA: file: Scheme Ban in N Developer Preview
If you are building an app against N Developer Preview 1, with a
targetSdkVersion
of 'N'
, it appears that
you can no longer use file:
Uri
values in many places. In particular, based on my testing:
-
You cannot use a
file:
Uri
as the “data” of anIntent
to be used with an activity, such as for anACTION_VIEW
Intent
, whether to be used immediately or to be wrapped in aPendingIntent
. In other words,startActivity(Intent.ACTION_VIEW, Uri.fromFile(...))
will not work. -
You cannot pass a
file:
Uri
in anIntent
extra, such asEXTRA_OUTPUT
forACTION_IMAGE_CAPTURE
. -
You cannot put a
file:
Uri
on the clipboard, using things likeClipData.newUri()
.
If you try to do these sorts of things,
you will crash with a FileUriExposedException
exception.
This is coming from an updated edition of StrictMode
.
StrictMode.VmPolicy.Builder
has a penaltyDeathOnFileUriExposure()
method that triggers the detection of file:
Uri
values and
the resulting FileUriExposedException
exceptions. And, it appears
that this is pre-configured, much as how StrictMode
is pre-configured
to apply penaltyDeathOnNetwork()
(the source of your
NetworkOnMainThreadException
crashes) on Android 4.0+.
It is unclear if this is a “trial balloon” and will be rescinded before Android N ships, or whether this is the expected behavior for the final shipping product. You may wish to keep track of this issue to perhaps find out more about these sorts of plans.
Assuming that it is here to stay, if you plan to use the latest
targetSdkVersion
once Android N ships,
you need to start using content:
Uri
values:
-
Apps that have been producing
file:
Uri
values will need to use things likeFileProvider
to producecontent:
Uri
values instead -
Apps that have been consuming
file:
Uri
values will need to make sure that they also supportcontent:
Uri
values… and do so correctly
I can understand why Google is doing this. They have been beating the
drum for some time now to try to get developers to switch off of
file:
Uri
values.
However, I worry.
Too many apps do not handle content:
Uri
values well. They assume
that a content:
Uri
must be coming from MediaStore
and do some
unfortunate things, such as trying to query for a DATA
column, in hopes
of scoring a file path. FileProvider
does not handle this, resulting
in crashes. I had to write
a LegacyCompatCursorWrapper
just to help
developers using FileProvider
to better cope with poorly-written
client apps.
This includes dealing with broken apps from the likes of
Samsung,
Twitter,
and Google.
This is not a problem that is somehow limited to inexperienced developers
or small firms. In the case of Twitter and Google, I think that they have
fixed their apps, but I am sure that plenty of others are out there.
After all, I see countless questions from people on Stack Overflow,
using older broken advice, trying to just strip the path off a Uri
and
use it to access the filesystem.
Now Google is trying to force developers to publish content:
Uri
values. That only works if a preponderance of consumers of
content:
Uri
values
do so properly. I fear that too many do not. Developers will be
caught between the Scylla of Android N and the Charybdis of user complaints
that the app does not work with with XYZ other app that screwed up
consuming the content:
Uri
. Experienced developers can work around
this, by keeping targetSdkVersion
low or possibly cooking up some
reflection-based hack to de-fang StrictMode
. Newcomers to Android will
wonder why all of the existing blog posts, Stack Overflow answers,
and older books are broken when it comes to working with Uri
.
On the engineering side, I don’t have a better answer, other than for
Google to include some sort of content:
Uri
compatibility testing
as part of evaluating apps for the Play Store.
I really hope that Google will do more to educate developers about
this exception and
how to correctly produce and consume content:
Uri
values. Since
FileUriExposedException
is not included in
the N Developer Preview “Behavior Changes” documentation,
I do not hold out much hope. Heck, at this moment, the only pages
indexed on Google for the search term of FileUriExposedException
are
things that I wrote, since the N Developer Preview JavaDocs are only
distributed in ZIP form.
Time will tell whether FileUriExposedException
and the revised
StrictMode
are a figment of my
imagination, are a fluke of the N Developer Preview 1, or are here to stay.
However,
let this serve as a wakeup call: use file:
Uri
values at your
own peril going forward.