Understanding Intents and Intent-Filters in Android

Intents or Intent messaging is the Android’s way to pass messages/information to various components of Android. An Intent object contains information that the target component can act upon. Through Intents, your apps can trigger Activities, Services and Broadcast Receivers.
The most common use of intents in any application is to directly launch
an Activity or Service to perform action on the data being passed with
the Intent object.

A sample use of Intent is shown in the following example.
1. To launch an Activity

Intent intent = new Intent(context, TagetActivity.class);
startActivity(intent);

2. To launch a Service

Intent intent = new Intent(context, TargetService.class);
startService(intent);

To pass some data within your intents you need pass them within the Intent object like this.

intent.put(key, value);

This way you can pass basic data-types that are supported by the
Intent class. In these examples, we are specifying the component names
explicitly, i.e, TagetActivity activity and TargetService service. These
intents are examples of Explicit Intents wherein you specify the target component that you want to handle your data.

There would be situations where you would want the user to choose the
target component, or to put in another way, the target component is
determined dynamically at run-time depending on various factors. For an
example, you would like to write a E-Mail app. The basic requirement
would be that whenever a user clicks on an e-mail address, your app
should be triggered, and it should be designed to capture the e-mail
address that was clicked. This is where, Implicit Intents
come into picture. Since, the e-mail address link that the user clicks
on might not necessarily be a part of your application, you do not have
the privilege of launching your Compose Activity on the click event of
the link. What would you do in such a case?

What happens when the e-mail link is clicked?
When an email link is clicked, the app would create an Implicit Intent
setting it up with the proper data and broadcast it. Something like
this:

Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.put(Intent.EXTRA_EMAIL, {email addresses}];
startActivity(intent);

In the above code snippet, we can see that the Intent here doesn’t
specify the component name. However, it specifies an action and the list
of email addresses. For this example, we just need to pass a string
array with just one email address that the user has clicked on.

How would Android know which activity should be launched (or service
for example). In such cases, Android tries to find the best match, i.e,
the component that can handle such a payload. In case it finds multiple
components, it gives the user a choice to make. For instance, if you
have multiple email clients installed and all of them can handle such
type of Intents, the user gets a list of all these apps (see image). He
can then select one which would launch that particular component
(Activity for this example). If it fails to find any components to
handle this Intent, an exception will be thrown (ActivityNotFoundException
in this case). Here we have two email applications that can handle this
intent. The user is given a choice to select one of them when an e-mail
link is clicked. Depending on the user’s choice, the corresponding
activity will be launched.

How do we write an Activity that can handle such Intents?

We have to specify or rather design one of our activity, the compose
screen of our email client that can handle such intents. For that, we
need to specify Intent-Filters for this specific activity in the AndroidManifest.xml file.

<activity android:name=”.ComposeActivity”
    android:label=”@string/app_name”>
    <intent-filter android:label=”@string/app_name”>
         <action android:name=”android.intent.action.SEND” />
         <data android:scheme=”mailto” />
         <category android:name=”android.intent.category.DEFAULT”/>
    </intent-filter>
</activity>

The above code itself is self-explanatory. Your activity now can handle
intents that are launched with this signature. The action is “android.intent.action.ACTION_SEND
and the data scheme is “mailto”, i.e, any email address. So, in your
ComposeActivity, you can retrieve the email address list by querying the
intent for the key, EXTRA_EMAIL
and you will get the list of email addresses (one in this case).
Typically, you will need to populate the Send To address field of your
ComposeActivity now.

The intent resolution process tries to find a best match for the intent.
Once it finds an Intent and launches the Activity with or without user
interruption(in case multiple matches are found), the responsibility of
handling the intent now lies with the target component. To finish off
the article, here is the way to extract the email address that had been
clicked.

Bundle data = getIntent().getExtras();
String[] emailAddresses = data.get(Intent.EXTRA_EMAIL);

The developer docs
on Intent, Intent Filters and Intent Resolution mechanism is a nice
read to understand the Intent mechanism of Android. You can find other
examples of the types of data and schemes that you can design your apps
for. 

5 thoughts on “Understanding Intents and Intent-Filters in Android

Leave a Reply