5. Broadcasting and Receiving Intents

The Android operating system enables applications to communicate with one another in a variety of ways. One way that information can be communicated across process or application boundaries is by using the broadcast event system built into the platform through the use of Intent objects. When an application has something it wants to communicate, it can broadcast that information to the system at large. Applications that are interested in that sort of event can listen for and react to that broadcast by becoming broadcast receivers. Although we develop numerous examples of broadcasts in the other chapters of this book, we felt it was worthwhile to cover some of the basics of broadcasting on the Android platform in their own chapter, free of other lessons.

Sending Broadcasts

The Android operating system uses broadcasts to communicate information to applications. The system generates numerous broadcasts about the state of the device, such as when the device is docked, an SD card is ejected, or a call is about to be placed. Applications can also generate and send broadcasts. Some system broadcasts can be initiated by applications (with the appropriate permissions), or applications can create their own events and broadcast them.

The Android framework supports two kinds of broadcasts. Normal broadcasts are delivered to all receivers and completed asynchronously in an undefined order. Ordered broadcasts are delivered to each receiver in priority order; the receiver can pass the event on to the next appropriate receiver in the queue or abort the broadcast before all receivers get it.

Broadcasts can also be sticky. This means that the Intent associated with the broadcast stays around after the broadcast has been completed, so that the broadcast receivers can retrieve valid Intent data from the registerReceiver() method return value. Both normal and ordered broadcasts can be sticky.

When dispatching a broadcast of any type, you have the option of specifying any permissions that the broadcast receiver must hold in order to receive your broadcast. These permissions are enforced by the Android operating system at runtime when matching occurs.


Image Tip

Many of the code examples provided in this chapter are taken from the SimpleBroadcasts application. The source code for this application is provided for download on the book’s website.


Sending Basic Broadcasts

Sending basic broadcasts is as simple as configuring the appropriate Intent object and dispatching it to the system using the sendBroadcast() method of the Context class. For example, the following code creates a simple Intent with a custom action type:

Intent i = new Intent("ACTION_DO_A_LITTLE_DANCE");
sendBroadcast(i);

Intents may be much more specific, with data stored in the type, category, and extra data attributes. The Android operating system uses the action, data, and category information to match up the broadcast with the appropriate applications using intent filters. The Intent extra and flag information is not used as part of intent resolution but may be used by the broadcast receivers when handling a broadcast.


Image Tip

The Intent action namespace is globally shared. When you broadcast “custom” intents, make sure you define unique action types. (It’s common to tack them onto your application package namespace.) If you want other developers to listen for and react to your broadcasts, be sure to clearly document the broadcasts your application generates and the Intent data stored in each type of broadcast.


To send a normal sticky broadcast, simply use the sendStickyBroadcast() method of the Context class instead of the sendBroadcast() method.

Sending Ordered Broadcasts

To send an ordered broadcast, simply create the appropriate Intent object as normal and then dispatch it to the system using the sendOrderedBroadcast() method of the Context class.


Image Tip

If multiple broadcast receivers that match a broadcast have the same priority, they will receive the broadcast in an arbitrary order.


To send an ordered sticky broadcast, simply use the sendStickyOrderedBroadcast() method of the Context class instead of the sendOrderedBroadcast() method.

Receiving Broadcasts

The Android operating system handles the transmission of broadcasts. Certain broadcasts can be initiated by any application, whereas others are protected or require certain permissions. The Android operating system matches up a broadcast with suitable application(s) using intent filters. Intent filters are criteria that the system uses as matching rules when determining what should handle an Intent. A simple intent filter might catch all intents of a given action type (like our sample application). A more specific intent filter might specify the Intent action, data (URI and data type), and category details.

In order to become a broadcast receiver, your application must

Image Register to receive broadcasts, specifying a specific intent filter, which the Android operating system uses to match broadcasts to your receiver

Image Implement a broadcast receiver class

After your application has received a broadcast, it is handled by your broadcast receiver class—specifically by its onReceive() callback. The lifecycle of a BroadcastReceiver is short; it is valid only for the duration of the onReceive() method. This means that you should not perform lengthy synchronous operations within this callback method. It also means that any asynchronous processing might be killed off before it finishes. To perform an operation that goes beyond these limitations, create and launch a Service instance instead. Android services are discussed in Chapter 2, “Working with Services.” For more information on the lifecycle of a broadcast receiver, see the Android SDK documentation at: http://d.android.com/reference/android/content/BroadcastReceiver.html#ReceiverLifecycle

Let’s look at a simple example of a broadcast receiver that can react to the dancing broadcast we sent earlier in this chapter. First, you must extend the BroadcastReceiver class and implement your own event handling in the onReceive() callback method. The following is an example implementation of a BroadcastReceiver called MyDancingBroadcastReceiver:

class MyDancingBroadcastReceiver extends BroadcastReceiver
{
    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "Get Down and Boogie!",
            Toast.LENGTH_LONG).show();
    }
}

If this is an inner class, say of your Activity class, it must be declared as public static so it can be instantiated on its own. This is particularly important if the registration is done in the manifest file; see “Registering to Receive Broadcasts Statically” in the next section.

Registering to Receive Broadcasts

To listen for and react to broadcast events, your application must register with the Android operating system as a broadcast receiver at runtime or in its Android manifest file. The type of events your application registers to listen for is dictated by what are called intent filters. You can filter on a variety of rules. For example, your application might want to listen only for broadcasts for specific Intent action types or some other Intent criteria.

Registering to Receive Broadcasts Dynamically

To register for specific broadcasts at runtime, use the registerReceiver() and unregisterReceiver() methods of the Context class. Registering dynamically enables your application to turn off receiving broadcasts of certain types when it can’t handle them or doesn’t need to. This can help improve performance compared to just ignoring broadcasts. It is fairly typical to register for broadcasts in the onResume() callback method of the Activity class, and unregister (stop listening for them) in the onPause() callback method. Here we have an example of how an Activity might manage its broadcast registration with a very simple intent filter that watches for a special Intent action type:

public class SimpleBroadcastsActivity extends Activity {
    public static String ACTION_DANCE =
        "com.advancedandroidbook.simplebroadcasts.ACTION_DANCE";

    MyDancingBroadcastReceiver mReceiver;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mReceiver = new MyDancingBroadcastReceiver();
    }

    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(mReceiver);
    }

    @Override
    protected void onResume() {
        super.onResume();
        IntentFilter danceFilter =
            new IntentFilter(ACTION_DANCE);
        registerReceiver(mReceiver, danceFilter);
    }
}

Registering to Receive Broadcasts Statically

You can also register to receive broadcasts in your application’s Android manifest file. Registering to receive broadcasts is useful when your application can always handle a particular broadcast. To re-create the same receiver configuration shown previously, where your broadcast receiver handles a specific Intent action type, you use the following XML in your application’s Android manifest file inside the <application> tag:

<receiver android:name=

        "com.advancedandroidbook.simplebroadcasts

        .SimpleBroadcastsActivity$MyDancingBroadcastReceiver" >
    <intent-filter>
        <action
            android:name=
                "com.advancedandroidbook.simplebroadcasts.ACTION_DANCE" />
    </intent-filter>
</receiver>

You can also set numerous tag attributes, such as priority, on the intent filter.

Handling Incoming Broadcasts from the System

After you have registered your broadcast receiver and implemented its onReceive() callback method, you are ready to start processing broadcast events. In some cases, your application will send the broadcasts, but in many cases, you simply want to respond to broadcasts made by other applications or the Android operating system at large (the device). Some common broadcasts your application might want to listen for and react to are listed in Table 5.1.

Image
Image
Image

Table 5.1 Important System Broadcasts

Securing Application Broadcasts

Some broadcasts are meant to be “heard” by any application that is interested. Others are intended for specific recipients. For example, you might want to define a set of broadcasts that your suite of Android applications uses but that cannot be used by other applications. Here are some tips for securing the broadcasting and receiving ends of the broadcast system:

Image Create unique Intent data for broadcast. If your application broadcasts only to specific target applications, create and enforce the permissions required for that broadcast when you send it.

Image Send the most specific broadcasts you can and create the most specific intent filters possible. This helps avoid broadcasts accidentally making it to unintended receivers.

Image As of API Level 14, you can specify the package limitations using the setPackage() method of the Intent class, and these limitations will be enforced. This is good for cross-application broadcasts that need to target just one application, for whatever reason.

Image You can set the target Class of the broadcast through either the appropriate constructor or the setClass() method. Use this for sending a broadcast directly to a particular receiver in your app. This avoids needing to set up and configure intent filters if you know exactly which receiver must handle each broadcast and you have full control over them within your app.

Image You can use the android:exported attribute of the <intent-filter> tag in your application’s Android manifest file to prevent other applications from sending broadcasts to your receiver.


Image Tip

Want to broadcast within the boundaries of your application but are worried about privacy? Check out the Android Support Package class called LocalBroadcastManager (android.support.v4.content.LocalBroadcastManager). It is basically an application-scoped broadcast that is more efficient than a system broadcast, and it guarantees that your Intent data never leaves your app—great for sending private data.


Summary

Broadcasts are a simple yet powerful way to communicate data across process boundaries. Broadcasts are sometimes used to communicate between services and their application user interfaces and between applications at large. Many broadcasts are initiated by the operating system to notify applications of events such as changes in device state. When an application sends a broadcast out, the Android operating system matches it up with all applications that have intent filters that match that request. For security purposes, there are some ways to lock down a broadcast such that it is handled by a specific application, and no other.

Quiz Questions

1. What are the two types of broadcasts that Android supports?

2. True or false: The method dispatchBroadcast() is used for sending out broadcasts to the system.

3. What must your application do in order to become a broadcast receiver?

4. What broadcast receiver Intent action notifies the new version of an application when the old version is replaced?

5. True or false: The android:exported attribute is used to prevent other applications from sending broadcasts to your receiver.

Exercises

1. Use the Android documentation to determine why you would not want to unregister a receiver in Activity.onSaveInstanceState().

2. Use the Android documentation to create a list of the broadcast receiver methods that work only when sent through Context.sendOrderedBroadcast().

3. Create an application that is able to receive a CALL_BUTTON intent action and, upon doing so, broadcast a custom Intent that displays a success Toast message.

References and More Information

Android API Guides: “Application Fundamentals”:

http://d.android.com/guide/components/fundamentals.html

Android SDK Reference documentation regarding the BroadcastReceiver class:

http://d.android.com/reference/android/content/BroadcastReceiver.html

Android API Guides: “Intent Resolution”:

http://d.android.com/guide/components/intents-filters.html#Resolution

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.143.222.225