Intent Filter And Intent Resolution

What is an IntentFilter?

  • An IntentFilter is a component that specifies the type of intents that the component would like to receive.
  • For example, by declaring an intent filter for an activity, you make it possible for other apps to directly start your activity with a certain kind of intent.
  • If you do not declare any intent filters for an activity, then it can be started only with an explicit intent.
  • Explicit Intents don’t depend on any IntentFilters whether they are included in the Manifest or not and always get delivered to the right component.
  • Declare one or more intent filters for each of your app components with an <intent-filter> element in your manifest file.
  • Each intent filter specifies the type of intents it accepts based on the intent’s action, data, and category.
  • The system will deliver an implicit intent to your app component only if the intent can pass through one of your intent filters.
  • An app component (Activity/Service/Broadcast Receiver) should declare separate filters for each unique job it can do.
  • For example, an Activity can declare 2 IntentFilters, one for reading a QRCode and one for generating a QRCode.
  • If an Intent is provided to launch this Activity, based on the contents of the Intent, this Activity performs the appropriate task.

The <intent-filter> Manifest tag

  • Each intent filter is defined by an <intent-filter> element in the app’s manifest file, nested in the corresponding app component (such as an <activity> element). Include the following tags within the <intent-filter> tag
  • <action>: Specify the ACTION String value accepted by this component
  • <data>: Specify the type of data accepted by this component consisting of MIME type and the URI made up of scheme, host, port and path.
  • <category>: Specify the category of Intents accepted by this component. To receive implicit Intents, specify CATEGORY_DEFAULT in the IntentFilter.
  • A single IntentFilter may include more than one <action>,<category> and <data>. In this case the target component must be able to handle any or all combination of Intents.
  • To allow several specific combinations of <action>, <category> and <data>, define multiple IntentFilters.
  • Each IntentFilter will be tested against an incoming Intent to satisfy the <action>, <category> and <data> tests. The Intent will be delivered to the component only if it can pass all the tests for atleast one IntentFilter.

How to manage IntentFilter for Activity, Service and BroadcastReceiver

  • To prevent other apps from running a Service, don’t declare IntentFilters for your Service.
  • For Activities, the IntentFilters must always be defined in the Manifest.
  • For Broadcast Receivers, they may be defined in the Manifest or dynamically registered using the registerReceiver() and unregisterReceiver() methods

Example of an elaborate IntentFilter

  • The Main Activity above opens when the user launches the app using the launcher icon.
  • The ACTION_MAIN action indicates this is the main entry point and does not expect any intent data.
  • The CATEGORY_LAUNCHER category indicates that this activity’s icon should be placed in the system’s app launcher. If the <activity> element does not specify an icon with icon, then the system uses the icon from the <application> element.
  • These two must be paired together in order for the activity to appear in the app launcher.
  • Users can navigate to the TestActivity using an Explicit Intent or an implicit Intent from some other app which uses an Intent to match one of the two Intent Filters created above.

Intent Resolution Process

  • To start an Activity using an implicit Intent, the system checks three aspects
    1. Intent Action
    2. Intent Category
    3. Intent Data (URI and Type)

Action Test

  • Intent Filter can define 0 or more <action> elements.
  • If the IntentFilter has 0 <action> elements, no Intent will match the filter.
  • If the Intent has no action set, then it may still pass the test with an IntentFilter where atleast one action is specified.
  •  The Intent must match one of the actions listed from the filter above in order to pass the test with this filter.

Category Test

  • Every category in the Intent must match with a category in the IntentFilter.
  • The IntentFilter may have more categories than the Intent and the latter can still pass the test.
  • Even an Intent with no categories can pass the test regardless of what categories are defined inside the IntentFilter.
  • Android automatically applies the the CATEGORY_DEFAULT category to all implicit intents passed to startActivity() and startActivityForResult(). For your Activity to receive implicit Intents, it must include a category for “android.intent.category.DEFAULT” in its intent filters.

Data Test

  • IntentFilter declares 0 or more <data> elements to specify the types of Intent data accepted by it.
  • The <data> elements can further specify the MIME type and URI structure which appears as <scheme>://<host>:<port>/<path>.
  • For example, in http://slidenerd.com:80/vivz/testapp.php, the scheme is http, the host is slidenerd.com, the port is 80, the path is vivz/testapp.php

General Rules for both MIME type and URI

  • Both the URI and the MIME type of an Intent are compared with the URI and MIME type specified in the <data> of an IntentFilter.
  • If the Intent has no URI or MIME type specified, it passes the data test only if the IntentFilter also has no URI or MIME type specified.
  • If the Intent has a URI but no MIME type which can be explicitly declared or directly inferred from the URI, it’ll pass the data test only if its URI format matches the format of the IntentFilter’s URI specification and the IntentFilter doesn’t contain a MIME type either
  • An Intent with MIME type and no URI passes the test with an IntentFilter that also contains a MIME type but no URI.
  • If an Intent has both URI and MIME type where the MIME type is either explicit or inferable from the URI, it needs to pass both the MIME type and URI test. For the MIME type test, its MIME type should match with the one specified in the Filter. The Intent passes the URI test only if its URI matches the URI in the filter or if the URI contains content: or file: and the IntentFilter does not specify a URI. If the IntentFilter only specifies a MIME type, it is assumed to support a URI containing file: or content: by default.
  • Components are able to get data from a file or ContentProvider.

Specific URI comparison Rules

  • If a scheme is not specified, the host is ignored.
  • If a host is not specified, the port is ignored.
  • If both the scheme and host are not specified, the path is ignored.
  • If a filter specifies only a scheme, all URIs with that scheme match the filter.
  • If a filter specifies a scheme and an authority but no path, all URIs with the same scheme and authority pass the filter, regardless of their paths.
  • If a filter specifies a scheme, an authority, and a path, only URIs with the same scheme, authority, and path pass the filter.
  • A path specification can contain a wildcard asterisk (*) to require only a partial match of the path name.