If Your Activity Has an <intent-filter>, Export It

Slightly less than two years ago, I pointed out a problem in Android where an activity that has an <intent-filter> , but is marked as not being exported ( android:exported="false" ), screws up the chooser. The chooser ignores the exported flag and offers up the non-exported activity to the user… then promptly crashes if the user actually chooses it.

Dianne Hackborn specifically called this out as being a bug in the app:

would generally consider this a bug in the app – if you have an activity that you aren’t allowing other apps to launch, why the heck are you publishing an intent filter that they will match to try to launch?

What would be nice, of course, is if Google paid attention to its own advice.

The AOSP Music app has five activities that violate this rule:

VideoBrowserActivity

ArtistAlbumBrowserActivity

AlbumBrowserActivity

NowPlayingActivity

TrackBrowserActivity

As a result, apps trying to start activities that match the <intent-filter> will crash with a SecurityException . I filed an issue about this over six months ago, with no response to date.

The lesson to you is: don’t be like Google. Instead, be like Google.

If your activity should not be visible to third parties, simply drop the <intent-filter> and use an explicit Intent to start it. You can still include things like an action string on the Intent , but use the explicit class or ComponentName control the routing of the Intent . Dropping the <intent-filter> will cause your activity to be non-exported by default, and you will not show up in choosers when you are not an eligible option.

I still would like the chooser to take permissions, exported status, etc. into account. Maybe I’ll write my own chooser someday…

Interested in learning Kotlin? Check out the Klassbook for Kotlin language lessons that you can run right in your browser!

— Apr 30, 2014