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.