Background Intents (non-visual)
Intents have multiple uses on the android platform and this fact makes them inherently confusing. In the single mechanism a variety of uses are implemented and this is only too apparent when you look at the Intent class constructor. When delving into the intents with Craig, he wondered why a nice Intent class hierarchy had not been implement to cleanly segment their uses.
This article addresses the use of Intents for sending and receiving messages in the background, for those circumstances, where you do not wish any impact on the users experience and will usually respond the notification asynchronously.
Receiving Intents Notifications.
It is the OS’s responsibility to notify Applications of events. It does this through the intent mechanism. You as the application developer need to tell the OS what messages you are interested in. “tell me when an sms comes in”, “tell me when the date changes”. These messages are going to be acted up on by your application in some way, but the action must be asynchronous and it should not change the flow of the user interface, unless displaying notifications in the status bar for example. (For example, this mechanism should not be really used for launching activities, the activity based intent-filters should be used for this) Having said that, it is possible to launch activities in this manner, but should be avoided.
You have two options available to notify the OS of the messages you wish to receive.
In the application section of the AndroidManifest.xml add a receiver section
<intent-filter>
<action android:name="Your.Domain.YourApplication.CustomNotificationUniqueName">
<category android:name="android.intent.category.DEFAULT" />
</action>
</intent-filter>
</receiver>
The IntenthandlerClassName should be the name of a class that we will discuss soon that will process the intents received.
The action name is a unique identifier for the intent notification to be received. If in this case you are going to receive a custom notification for you application then qualify it with your application package name and a unique string describing the messages intent.
If you want to receive a system notification then put the unique name of the notification instead.
e.g.
- android.intent.action.DATE_CHANGED - get notification when the date changes
- android.intent.action.WALLPAPER_CHANGED - find out when the wallpaper has changed
For a list of intent actions you can receive notification for see the constants section at http://code.google.com/android/reference/android/content/Intent.html
We will have a look a the second method of receiving these notifications is a while…
When you add the receiver element to your application’s manifest you are informing the OS that your application wants to receive the stated messages. You will receive these irrespective of whether your application’s activities or services are running or even loaded into memory.
When a messages needs broadcasting the OS inspects the list of applications that wish to receive the message. It then, creates an instance of the IntentReceiver descendant class (in our example the IntentHandlersClassName specified in the name attribute of the receiver)
It then calls the onReceiveIntent method passing in a content and the instance of the intent being broadcast.
So to receive these messages we add a new class (in the example “IntentHandlersClassName”) to our application that extends IntentReceiver and override the onReceiveIntent method.
// override the onReceiveIntent method
@Override
public void onReceiveIntent(Context ctx, Intent intent) {
Log.i("Intent Received", intent.getAction());
if (intent.getAction() == "Your.Domain.YourApplication.CustomNotificationUniqueName")
{
// act on intent
}
}
}
The intent object passed in is short lived, and references should not be held to the intent object by sub processes or activities. When this method goes out of scope the intent instance is assumed to be out of scope as well. If you have looked at intents at all before, you will know that they can have data associated with them using putExtra and getExtra. So if you need this data in the activity / service you are calling you need to take a copy and ensure you do not pass the intent object through.
The onReceiveIntent method needs to be processed quickly and should not block for a significant time. The OS will time it out after 10 seconds.
For more information see http://code.google.com/android/reference/android/content/IntentReceiver.html
So now you can inform the OS you want system notification or even your own custom notification messages. However, you can get notified at any time, even if you have no activities running.
The alternative method, like so much of the android functionality is either do it in xml or do it in code.
The advantage of implementing in code is you can add and remove the listening for intents at points chosen by you. For example you may wish to stop receiving intents when the application is paused by the os, for performance reasons and only start receiving them when the application is resumed.
To do this we use the context’s registerReceiver and unRegisterReceiver methods.
e.g.
Broadcasting Intent Notifications
So how do we broadcast an intent that can be received as above. It’s really nice and simple. Create a new instance of Intent, set the Action and category as necessary and call the Activity’s braodcastIntent
i.setAction("uk.co.droidapps.FileBrowser.CustomNotificationUniqueName");
broadcastIntent(i);
This is my understanding so far, from examples and tests I have put together. It may be incorrect, inconsistent or I may have misunderstood something, but the intent mechanism seems a mess of functionality and intertwined documentation. If you spot mistakes please comment.
