There are two types of intents
- Explicit Intents – you must name the component that will receive the intent. You’ll usually use Explicit Intents in your own app’s where you know the component’s class
- Implicit Intents – the component isn’t named so you won’t know which component will receive the intent. You declare a general action that the component must perform. The System then looks for suitable components by matching the contents of the intent to intent filters of all the apps on the device. If there is a match, then the system starts that component and delivers the intent object to it. If there are a number of matches, a chooser dialog is displayed, allowing the user to select the suitable component
The Gate keepers: Intent filters
You use filters to deny or allow intents to reach your app components.
Lay down the rules: Declare you intent filters
You must declare intent filters for each component that you want to receive an intent. The System will then know which intents your app can receive.
You can declare the filters in the manifest and in some cases also programmatically:
- Activity filters – must be declared in the manifest
- Broadcast Receivers – you can register these filters dynamically or in the manifest. You may want to look at Android Broadcast Receivers: a tutorial for more on broadcast receivers
Each filter specifies the type of intent it accepts, based on the intent’s action, data and category. The system then compares the intent to your filters and only delivers it to your app component if there is a match.
You should declare separate filters for each unique job that a component can do. For example, an image app can have two filters, one to view an image and another to edit an image.
Putting it together: The parts of an intent
Intents contain information which the system uses to find the correct component to handle the intent.
You can include the following information in an intent:
- Component name
- Action
- Data
- Category
- Extras
- flags
Component name
If it’s an explicit intent, then you need to include the name of the component that you want to start. Implicit intents don’t need a component name
Action
This is the action that we want the component to perform. It determines the rest of the intents structure, such as the contents of the data and extras elements.
You’d usually use actions defined by the Intent class’s action constants. Here are a few examples:
- ACTION_VIEW – use it with startActivity() if the activity has information to show, for example a photo
- ACTION_SEND – use it with startActivity() if you have data to share, for example email
- See the Intent class for more action constants
You can also specify your own actions.
Data
Data is a URI object referencing the data to be acted on. The action will be performed on this data. It could be, or include, the MIME type for the data. For example, an email address or telephone number.
Category
The category contains additional information about the component that should handle the intent. You can have a number of category descriptions but it’s not required. Here are two examples:
- CATEGORY_BROWSABLE – the target activity allows itself to be started by a web browser to display data referenced by a link, for example an image
- CATEGORY_LAUNCHER – the target activity is the initial activity of a task. And is listed in the system’s app launcher. An example is the activity that launches your app
Extras
You can include additional information in the form of key-value-pairs in the intent. Simply add the data to the intent using one of the putExtra methods.
Have a look at Passing data between activities where we show you how to exchange primitive data between activities.
Flags
Flags contain extra information for the system on how it should handle the intent.
Getting the message: Receiving an implicit intent
App components can only receive an intent if it makes it through the intent filters.
Check the credentials: Filtering the Intents
Each filter is defined by the
- specifies which intent action the component will accept - - specifies the type of data accepted. You need to include the URI and/or MIME type
- specifies the intent category accepted. You must include the category, DEFAULT, in the filter if you want a component to receive the intent (except if you’re using the startActivity() and startActivityForResult() methods)
You can include more than one instance of the action, data, and category elements.
Who can and who can’t: Intent Resolution
The system receives the implicit intent and then compares it to all the app filters of all the apps on the device. It applies three tests:
- Action test
- Category test
- Data test
Where’s the action? The Action test
A filter can have zero or more action elements. To pass, the intent’s action must match one of the filter’s actions.
If the filter does not have an action, then no intents get through.
If the intent does not have an action, it will pass but only if the filter has at least one action.
Categorise it! The Category test
A filter can declare zero or more category elements. To pass, every category in the intent must match a category in the filter.
If the intent does not have a category, it will pass regardless of whether there are any categories in the filter.
Da,da,da, data! The Data test
A filter can declare zero or more data elements.
Each data element can specify:
- MIME type – the data type of the data being matched. For example text/plain
- Uri - the URI is structured like this: < scheme>://
: (together known as the authority)/ . Here’s an example - content://za.co.101apps:200/folder/subfolder/etc where:
- scheme – content:
- host – za.co.101apps
- port – 200
- path – folder/subfolder/etc
- content://za.co.101apps:200/folder/subfolder/etc where:
As far as the Uri structure is concerned, each attribute is optional but:
- no scheme then the host is ignored
- no host then the port is ignored
- neither scheme nor host then the path is ignored
Will the Intent’s URI make it through the filter?
The intent’s URI is only compared to the URI attributes included in the filter. Here are some examples:
- scheme only – all intents with matching URI schemes will pass
- scheme and authority (host plus port) but no path - all intents with matching URI schemes and authorities will pass
- scheme, authority and path - all intents with matching URI schemes, authorities and paths will pass. Paths can include a wildcard (*)
The data test compares the URI and MIME type of the intent with those of the filter. The comparison follows the following rules:
- Intents with no URI or MIME type will pass if the filter has no URI or MIME type
- Intents with a URI but no MIME type will pass if the URI matches the filter URI and the filter has no MIME type
- Intents with a MIME type but no URI will pass if the filter has the same MIME type and no URI
- Intents with both MIME types and a URI will pass the MIME type part of the test if the filter has the same MIME type. It will pass the URI part of test if its URI matches the filter URI or:
- the intent has a content: URI and the filter has no URI
- the intent has a file: URI and the filter has no URI
So what’s in the package? Using the PackageManager
You can use the PackageManager’s methods to find out more about the components on a device. Here are some of the methods that you can use:
- Query methods – to return all components that accept a particular intent. For example:
- queryIntentActivities() – lists all activities that match the given intent
- queryIntentServices() – lists all services that match the given intent
- queryBroadcastReceivers() – lists all broadcast receivers that match the given intent
- Resolve methods – lists all the components that will respond to particular intent
- resolveActivity() – returns activities that can handle the given intent
- resolveContentProvider() – finds a content provider to handle the intent
- resolveService – gets the best service to handle the given intent. For more on Services, have a look at the article, All about Services
Pending intents
Pending intents are intents that another app can send on behalf of your app at a later time.
When triggered, pending intents execute the packaged intent as if it had been executed from within your application.
You can use pending intents for:
- notifications - the system notification manager executes the intent. Check out the series of tutorials on Notifications, You can master notifications. It’s easy!
- app widgets – the home screen app executes the intent
- intents to be executed in the future – the system’s alarm manager executes the intent. Want to know more about repeating alarms? Have a look at the tutorial, Scheduling Android’s Repeating Alarms
Have look at our tutorial on intents and intent filters. In it we’ll show you how to:
- use explicit intents to:
- start a new activity
- start an activity to get a result
- start a service
- broadcast an intent
- start a new activity from within a broadcast receiver
- use implicit intents to:
- use other app’s components to:
- send an email
- pick a contact from the contacts list
- make a phone call
- use other app’s components to:
- use a pending intent to send a notification
- use intent filters for:
- a broadcast receiver
- an activity
I hope that you have found this tutorial helpful.