With <intent-filter>, Only Advertise What You Can Fulfill
It seems like only yesterday that I pointed out problems when
apps have <intent-filter>
elements that they do not support.
But, that was a bit over 8 years ago. Time flies!
(in related news: I’m getting old)
In that post, my example was an app that had an <intent-filter>
matching one
from a popular app (Barcode Scanner) that many other apps would launch. In this
case, the offending app could not fulfill the contract of that <intent-filter>
, largely
because the activity in question was not exported. At the time, a bug
caused non-exported activities to still show up in the chooser, though fortunately
this has since been fixed.
More generally: if your app has an <intent-filter>
, there is an implied contract
that your app needs to fulfill. If you are not going to fulfill that contract, do
not have that <intent-filter>
, or at least make it user-controllable.
For example, some file managers advertise activities for the ACTION_OPEN_DOCUMENT
<intent-filter>
,
or ACTION_GET_CONTENT
.
In theory, this is fine, if such activities fulfill the contract. In the case of
ACTION_OPEN_DOCUMENT
, apps are expecting to get back a Uri
that works with
DocumentsContract
,
perhaps by way of DocumentFile
. And they are expecting the Uri
to support
basic things, like getType()
and openInputStream()
on ContentResolver
.
If your activity will return such a Uri
, great! If not… why are you advertising
the ACTION_OPEN_DOCUMENT
<intent-filter>
?
My guess is that the file manager developers are offering a subset of ACTION_OPEN_DOCUMENT
support, with an eye towards environments that lack such an activity, such as
Android TV.
If so, that too is fine, but those activities should either be completely opt-in
by the user, or at least opt-out only on devices that lack a real ACTION_OPEN_DOCUMENT
implementation. You can do this by putting the <intent-filter>
on an <activity-alias>
that you enable and disable based on the device and based on user input. This lets
you toggle the availability of that <intent-filter>
without affecting the general
availability of the activity itself.
Frankly, it would not surprise me if some future version of Android adopted
a protected activity Intent
approach, akin to how it has the concept of
protected broadcasts, ones that only system apps can send. And, it would not surprise
me if ACTION_OPEN_DOCUMENT
were protected in this fashion.
But, in general, if you have an <intent-filter>
, make sure that it does what
other apps will expect. In particular, if the protocol for that Intent
involves startActivityForResult()
/setResult()
, then make sure that your result
matches expectations. This is no different that completely supporting the
API of some interface
or abstract class
that you implement… except that
there is no compiler telling you what to do, just some balding guy.