Working with Pending Intents

When the user needs to interact with your application, she communicates by tapping the app widget using the Android messaging architecture (as described earlier), and you aren’t immediately notified. However, this doesn’t mean you can’t be notified about a click event on your app widget — it’s just done a little differently than regular views.

App widget click events contain instructions for what to do when a click event happens via the PendingIntent class in the Android framework. A pending intent is an implementation of the Intent class in Android, as explained in the following section.

Understanding the Android intent system

An Intent object in Android is a message telling Android to make something happen. When you turn on a light using a wall switch, the action of your intent is to turn on the light, so you flip the switch to the On position. In Android, this action correlates to creating an instance of the Intent class with an action in it specifying that the light is to be turned on:

Intent turnLightOn = new Intent(“TURN_LIGHT_ON”);

This intent is fired off into the Android messaging system (as described in Chapter 1), and the appropriate activity handles the Intent. (If multiple activities respond, Android lets the user choose one to do the work.) However, in the physical world, an electrical connection is made by positioning the switch to the On position, resulting in illuminating the light. In Android, you have to provide code, in the form of an activity, to make this happen. This activity (that can be named TurnLightOnActivity) responds to the turnLightOn intent. If you’re working with an app widget, you must handle the intent in a BroadcastReceiver rather than in an activity. An AppWidgetProvider is an instance of a BroadcastReceiver with a few extra bells and whistles that configure a lot of the app widget framework for you. The BroadcastReceiver object is responsible for receiving broadcast messages.

The AppWidgetProvider handles the intent from the Home screen and responds with the appropriate result that you determined, using your code, inside your custom AppWidgetProvider. It doesn’t work with any intent, though. If you want to receive input from your app widget, use PendingIntent.

To understand what a PendingIntent class is, you need to fully grasp the concept of the basic Intent class. A PendingIntent contains a child Intent object. At a high level, a pending intent acts like a regular intent. An intent is a message that can carry a wide variety of data describing an operation that needs to be performed. An intent can be addressed to a specific activity or broadcast to a generic category of receivers known as BroadcastReceivers (which includes AppWidgetProvider). The Intent, Activity, and BroadcastReceiver system is reminiscent of the message bus architecture, where a message is placed on a message bus and any of the endpoints on the bus respond to the message if (and only if) they know how. If no endpoint knows how to respond to the message, or if the message wasn’t addressed to the endpoint, the message is ignored.

An intent can be launched into the message bus system in a couple of ways:

check.png Start another activity: Use the startActivity() call, which accepts an Intent object as a parameter.

check.png Notify any interested BroadcastReceiver components: Use the sendBroadcast() call, which also takes an intent as a parameter.

check.png Communicate with a background service: Use the startService() or bindService() call, which both accept intents as parameters.

An activity is the glue that binds various components of the application because it provides a late-binding mechanism that allows inter-application and intra-application communication.

Understanding intent data

An intent’s data consists of these elements:

check.png Action: The general action to be performed. A few common actions include ACTION_VIEW, ACTION_EDIT, and ACTION_MAIN. You can also provide your own custom action.

check.png Data: The data to operate on, such as a record in a database or a uniform resource identifier that should be opened, such as a URL.

Table 7-1 demonstrates a few action and data parameters for Intent objects and their simple data structure.

Table 7-1 Intent Data Examples

Action

Data

Result

ACTION_VIEW

tel:123

Display the dialer with the given number (123) filled in.

ACTION_DIAL

content://contacts/people/1

Display the dialer showing the phone number from the contact with the ID of 1.

ACTION_EDIT

content://contacts/people/1

Edit the information about the person whose given identifier is 1.

ACTION_VIEW

http://www.example.org

Display the web page of the given intent.

ACTION_VIEW

content://contacts/people

Display a list of all people in the Contacts system.

Intents can also carry an array of other data that include these elements:

check.png category: Gives additional information about the action to execute. As an example, if CATEGORY_LAUNCHER is present, the application should show up in the application launcher as a top-level application. Another option, CATEGORY_ALTERNATIVE, can provide alternative actions that the user can perform on a piece of data.

check.png type: Specifies a particular type (MIME type) of intent data. For example, when you’re setting the type to audio/mpeg, the Android system recognizes that you’re working with an MP3 file. Normally, the type is inferred by the data itself. By setting the type, you override the inferred type by explicitly setting the type in the intent.

check.png component: Specifies an explicit component name of the class on which to execute the intent. Normally, the component is inferred by inspection of other information in the intent (action, data/type, and categories), and matching components can handle it. If this attribute is set, none of that evaluation takes place, and this component is used exactly as specified (likely the most common use case in your applications). You can provide another activity as the component — this addresses Android to interact with that specific class.

check.png extras: A bundle of additional, key-based information that’s used to provide extra information to the receiving component. For example, if you need to send an e-mail address, you use the extras bundle to supply the body and subject and other components of the e-mail.

Evaluating intents

Intents are evaluated in the Android system in one of two ways:

check.png Explicitly: The intent has specified an explicit component or the exact class that will execute the data in the intent. (Again, this is likely the most common way to address intents.) This type of intent often contains no other data because it’s a means to start other activities within an application. You find out later in this chapter how to use an explicit intent in an application.

check.png Implicitly: The intent hasn’t specified a component or class. Instead, the intent must provide enough information about the action that needs to be performed with the given data for the Android system to determine which available components can handle the intent — sometimes referred to as an address and a payload.

An example is setting up an e-mail intent that contains e-mail fields (To, CC, Subject, and Body) and an e-mail MIME type. Android interprets it as an e-mail and gives the user of the device the opportunity to choose which application should handle the intent. Possibilities include Gmail or Exchange or a POP e-mail account. The user determines which e-mail program to use. The Android capability to identify possible matches for the given intent is known as intent resolution.

Using pending intents

A PendingIntent is an intent at its core, but with a slight paradigm shift in regard to functionality: It’s created by your application and given to another, completely different application. By giving another application a PendingIntent, you’re granting the other application the right to perform the operation you have specified as though the application were your application. In layman’s terms, you’re giving information about how to call your application to perform work on another application’s behalf. When the other application deems that the given work needs to take place, it executes the PendingIntent, which instructs the Android messaging system to inform your application to perform the necessary work.

For the purpose of the Silent Mode Toggle application, you use the PendingIntent.getBroadcast() call to obtain a pending intent instance. This call returns a PendingIntent that’s used for broadcasts throughout the system. The call takes these four parameters:

check.png Context: The context in which this PendingIntent should perform the broadcast.

check.png RequestCode: The private request code for the sender. Not currently used; therefore, a zero is passed in.

check.png Intent: The intent to be broadcast.

check.png Flags: A set of controls used to control the intent when it’s started. Not currently used in the Silent Mode Toggle application; therefore, a zero is passed in.

Wait a second — this code uses an Intent as well as a PendingIntent. Why? The Intent object is wrapped inside a PendingIntent because a PendingIntent is used for cross-process communication. When the PendingIntent is fired off, the real work that needs to be done is wrapped up in the child Intent object.

That’s a lot of information! Now that you understand the basics of the Android intent system, it’s time to implement the guts of the application inside this app widget.

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

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