Another way to use an Intent involves sending a broadcast to any interested receiver.
There are many reasons an application may want to broadcast an event; for example, when an incoming phone call or text message is received. In this section we will take a look at how events are broadcast and how they are captured using a BroadcastReceiver.
Here we will continue working through the WeatherReporter sample application we began in the previous section. One of the most important parts of the Weather- Reporter application will be its ability to display alerts to the user when severe weather is in the forecast for a location where the user has indicated interest. We will need a background process that checks the weather and sends any needed alerts. This is where the Android Service concept will come into play. We won’t be creating the actual Service class until section 4.3, but we need a way to get the platform running the Service as soon as it boots up, and this is where we will use an Intent broadcast.
4.2.1 Overloading the Intent concept
As you have seen, Intent objects are used to go from Activity to Activity in an Android application. While this is the main use of intents in Android, it is not the only one. Intents are also used to broadcast events to any configured receiver using one of several methods available from the Context class, as shown in table 4.3.
Table 4.3 Methods for broadcasting intents
Method Description
sendBroadcast(Intentintent) Simple form for broadcasting an Intent. sendBroadcast(Intentintent,String
receiverPermission)
Broadcasts an Intent with a permission String that receivers must declare to receive the broadcast.
When broadcasting intents you are basically reusing the Intent concept to send an event in the background. Though the Intent class is used, it is used differently than when invoking foreground Activity paths. A broadcast Intent does not invoke an Activity (though a BroadcastReceiver can do so after the event is received, if necessary).
Another important aspect with Intent broadcasts is how permissions are handled.
When you broadcast an Intent, you can optionally specify a permission. Permissions are something we addressed in chapter 1. They basically are String declarations that can be used when making a broadcast that require receivers to declare the same permission.
Broadcasting an Intent itself is fairly straightforward; you use the Context object to throw it on the wire, and interested receivers will catch it. Android provides a set of platform-related Intent broadcasts that use this approach. When the time zone on the platform changes, when the device completes booting, or when a package is added or removed, for example, the system broadcasts an event using an Intent. Some of the specific Intent broadcasts the platform provides are shown in table 4.4.
sendStickyBroadcast(Intentintent) Broadcasts an Intent that hangs around a short time after it is sent so that receivers can retrieve data. Applications using this must declare the BROADCAST_STICKY permission.
sendOrderedBroadcast(Intent intent,StringreceiverPermission)
Broadcasts an Intent call to the receivers one- by-one serially.
sendOrderedBroadcast(Intent intent,StringreceiverPermission, BroadcastReceiverresultReceiver, Handlerscheduler,intinitialCode, String initialData,Bundle
initialExtras)
Broadcasts an Intent and gets a response back by implementing your own BroadcastReceiver for the broadcast (and passing it in). All receivers can append data that will be returned in the BroadcastReceiver. When using this method, the receivers are called serially.
Table 4.4 Provided Android platform broadcast actions
Action Description
ACTION_TIME_TICK Sent every minute to indicate that time is ticking ACTION_TIME_CHANGED Sent when the user changes the time on the device ACTION_TIMEZONE_CHANGED Sent when the user changes the time zone on the device ACTION_BOOT_COMPLETED Sent when the platform completes booting
ACTION_PACKAGE_ADDED Sent when a package is added to the platform ACTION_PACKAGE_REMOVED Sent when a package is removed from the platform
ACTION_BATTERY_CHANGED Sent when the battery charge level or charging state changes Table 4.3 Methods for broadcasting intents (continued)
Method Description
The other half of broadcasting events is the receiving end. To register to receive an Intent broadcast, you implement a BroadcastReceiver. This is where we are going to implement a receiver that will catch the platform-provided BOOT_COMPLETED Intent in order to start the weather alert service we will create for the Weather- Reporter application.
4.2.2 Creating a receiver
Because the weather alert Service we want to create needs to be running in the back- ground whenever the platform itself is running, we need a way to start it when the platform boots. To do this, we will create a BroadcastReceiver that listens for the BOOT_COMPLETEDIntent broadcast.
The BroadcastReceiver base class provides a series of methods that allow for get- ting and setting a result code, result data (in the form of a String), and an extras Bun- dle. In addition, there are a series of lifecycle-related methods that correspond to the lifecycle events of a receiver; you will learn more about these as we progress through this section.
Associating a BroadcastReceiver with an IntentFilter can be done in code or in the manifest XML file. Once again the XML usage is often easier and thus more com- mon. This is the way we did it for WeatherReporter in listing 4.3, where we associated the BOOT_COMPLETED broadcast with the WeatherAlertServiceReceiver class. This class is shown in listing 4.5.
public class WeatherAlertServiceReceiver extends BroadcastReceiver { @Override
public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) { context.startService(new Intent(context,
WeatherAlertService.class));
} } }
When creating your own Intent broadcast receiver you extend the BroadcastRe- ceiver class Android provides B and implement the abstract onReceive(Context c, Intent i) method C. Within this method we are starting the WeatherAlertService. This Service class, which we will create next, is started using the Context.start- Service(Intent i, Bundle b) method D.
Keep in mind that receiver class instances have a very short, specific lifecycle. When the onReceive(Context c, Intent i) method is complete, the instance and process that invoked the receiver are no longer needed and may be killed by the system. Because of this, you can’t perform any asynchronous operations in a BroadcastReceiver, such as binding to a Service or showing a dialog. Alternatively, you can start a Service, as we have done here, and leave it running in the background. (Binding to a Service is different than starting one; we will cover this distinction in the next section.)
Listing 4.5 The WeatherAlertServiceReceiverBroadcastReceiver class
Start WeatherAlertService D
Override C
onReceive Extend BroadcastReceiver B
Now that our receiver is starting the WeatherAlertService, which will run in the background and warn users of severe weather in the forecast with a Notification- based alert, we need to delve into the realm of the Android Service concept itself.