One factor contributing to Android’s success in the smartphone market is the large number of third-party application developers in Java. The other not-so-well-known yet important factor is the ease with which developers can write complex applications with Android’s very good inter-application communication mechanism (IACM), facilitating component re-use and faster turn-around while writing new applications. This article explores intents-the heart of Android’s IACM.
First, let’s get familiar with the Android terminology used in this article:
Activity: The user interface part of an application. An application can have one or more activities.
Service: Code that runs in the background (typically to perform a long operation) and does not interact with the user.
Broadcast Receiver: Code that registers (listens) for a particular broadcast message.
What are intents?
In Android, intentdescribes an operation to be performed. For example, it can say open a browser, send an SMS, make a phone call, etc. In some cases, an intent can also describe something that has happened in the past, and is now being reported to the Android system. Examples of this include reporting that the battery status has changed, a head-set has been plugged in, a camera button was pressed, etc. This category is mostly used by the Android OS to send system-wide notifications about a certain event, and is usually referred to as System Broadcast Intents. These can only be sent by the system, not by an application. Intents can be sent between Activities, Services and Broadcast Receivers. Applications use intents for both inter- and intra-application communication.
The components of an intent
An intent itself is an object of the Intent class, which meets the descriptions we talked about earlier. Broadly, the descriptions can be classified as given below:
Component Name (Optional) Describes what component should handle the intent. It is specified by the fully qualified class name of the component and the package name, with the project name, e.g., com.example.project.lfy.SampleActivity with com.example.project.
Action Describes what action to be taken; e.g., ACTION_DIAL to specify make a phone call.
Data Contains data required for the action; e.g., the phone number to call.
Category Provides additional information about the action to perform; e.g., CATEGORY_LAUNCHER means it should appear in the Launcher as a top-level application.
Extras (Optional) Key-value pairs holding additional information, if any. Mostly used in the broadcast intents. For example, while reporting battery status, the intent describes battery capacity, temperature, etc, as extras.
Types of intents
Intents are divided into two groups:
a) Explicit intents: These explicitly specify the name of the target component to handle the intent; in these, the optional component name field (above) is set to a particular value, through the setComponent() or setClass() methods.
b) Implicit intents: These do not specify a target component, but include enough information for the system to determine which of the available components is best to run for that intent. Consider an app that lists the available restaurants near you. When you click a particular restaurant option, the application has to ask another application to display the route to that restaurant. To achieve this, it could either send an explicit intent directly to the Google Maps application, or send an implicit intent, which would be delivered to any application that provides the Maps functionality (e.g., Yahoo Maps).
For implicit intents, Android figures out the right component that can handle them. This process is called Intent Resolution, which maps an Intent to an Activity, Broadcast Receiver or Service (or sometimes two or more activities/receivers) that can handle it. If an activity wants to receive a particular intent, it can do so in the two ways mentioned below:
a) It should specify the same in the Android Manifest.xml, in the <intent-filter> tags, as shown below:
<intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter>
b) It can explicitly register a Broadcast Receiver using registerReceiver(BroadcastReceiver, IntentFilter)
Types of intent broadcasts
There are three different types of broadcasts used by the Android System to broadcast intents:
a) Normal Broadcast: Sent asynchronously, all registered Broadcast Receivers will receive it. The order in which receivers receive it is undefined. Intents are sent with the context.sendBroadcast() method.
b) Ordered Broadcast: This is delivered sequentially to each eligible Broadcast Receiver; the order is defined by the priority of the associated Intent Filters, using the android:priority attribute in the Android Manifest.xml. Any Broadcast Receiver receiving an ordered broadcast can stop further sending by the abortBroadcast() method. The sender of an ordered broadcast can choose to be notified when the broadcast has completed. The isOrderedBroadcast() method returns true if the current receiver processes an ordered broadcast. These intents are sent using the context.sendOrderedBroadcast() method.
c) Sticky Broadcast: This is retained by the system even after it has been sent; this means that whenever you register a receiver for these intents, you will get a cached copy of the intent that was recently sent. ACTION_BATTERY_CHANGED, an intent that describes the changes in battery status, is a good example of a sticky broadcast.
The sample code available at http://opensourceforu.efytimes.com/article_source_code/dec12/intents_android.zip creates a simple intent to launch the contacts list; it also listens to the battery status change intent and provides the battery capacity. This sample code can be tested with Eclipse, running an Android emulator.
Having introduced readers to Android intents, in the next article, we will look at how Android prevents applications from sending system-level intents.