[MUSIC] Now, after an intent is broadcast, it will eventually be delivered to the appropriate broadcast receiver, through a call to the broadcast receiver's onReceive method. And this method has two parameters. One, the context in which the receiver is running and two, the intent that was broadcast. So there are some things to consider when you're writing the code that handles incoming broadcasts. First, to deliver a broadcast, Android may have to start a receiver's application process, because it might not actually be running, when the intent is broadcast. And while onreceive is running, that process has high priority. So broadcasting and intent, especially if it goes to multiple applications, can be a relatively expensive operation. Second, onreceive method runs in the main thread of the toasting process. And like anything that you do on the main thread, it should be fairly short-lived, and it shouldn't block the main thread. In particular, if the processing you need to do in response to the broadcast is time consuming, then you should consider starting a service to that work, rather than doing the work in onReceive. In fact, that's exactly what the MMS application does when an MMS message arrives. A broadcast receiver receives a broadcast, informing it that the MMS message has arrived. And in its onReceive method, when it gets called, it immediately passes the message, to another service that handles all the work of downloading the message, storing it in a database, and so forth. Now of course, we haven't talked about services much yet, but we'll get to them in later lessons. A last issue to consider, is that a broadcast receiver is considered valid only as long as OnReceive is running. In fact, once OnReceive returns android will sometimes terminate the underlying broadcast receiver. In particular, this, this means that broadcast receivers can't start up operations that will need to call back to the receiver asynchronously at a later time. And of course that makes sense, because there's no guarantee that the broadcast receiver will even exist when that callback occurs. Now examples of these asynchronous callbacks include things like, starting a dialogue. We're starting an activity via the start activity or result method. So, let's look at some more examples of applications that use broadcast receivers. Here, I'll start up the compound broadcast application. It has a button labeled broadcast intent. Which when pressed, will use the send broadcast method to broadcast a show toast intent. This time however, there are three broadcast receivers that will receive this intent. So, now I'll press the button. And below you see a toast message from receiver 1. A second one from receiver 2, and a third one from receiver 3. Because the compound broadcast application used send broadcast. The broadcasts were sent out normally. And that means that the arrival and processing order, were undefined. In this case, the broadcast happened to be handled in one particular order. In other cases, or on a different device, or if Android changes in the future, that order might be different. So if you really want the broadcast receivers to receive broadcasts in a particular order, or if you want each broadcast receiver to have exclusive access to the intent while it's being process, then you'll want to broadca, you'll want the broadcast to be ordered. And to, you'll do that by using a sendOrderedBroadcast method. And you can do that using some of the methods, some of the following methods from the context class. The first, sends an intent to broadcast receivers that have a specified permission in priority order. The second does the same thing, but provides additional parameters for greater control. Let's look at some applications that use these methods to sendOrderedBroadcasts. Here, I'll start up The Compound Ordered Broadcast application. This application displays a button labeled Broadcast Intent, and when you press the button, a show Toast intent is broadcast. For this application, there are three registered broadcast receivers, a type receiver one, receiver two and receiver three. And each of these, has a different priority for receiving the broadcast. Receiver two has the highest priority, Receiver one, the next highest, and Receiver three has the lowest priority. So we expect the receivers to get the broadcast in that order, receiver two, receiver one, receiver three. However, I've put in some code. I put some code in receiver one, that aborts the broadcast. So in this case, only receiver two, and then receiver one, should receive the broadcast. So let's see that in action. Now I'll press the broadcast intent button, and you can see a toast message saying that the intent was received by receiver two. And then another saying it was received by receiver one. And apparently poor receiver three gets left out in the cold. Let's look at the source code for this application. Now here, I've got the application open in the IDE. And I'll start by opening up the Android manifest.xml file. And as you can see, I've statically registered Receiver2 with a priority of 10, and Receiver3 I've registered with a priority of 1. Now back in the main activity, the code creates an instance of Receiver1, then creates an intent filter for the show toast intent, and then sets the priority to three. So any Receiver2 instance has priority 10. This Receiver1 instance as priority 3. And then your receiver three instance as priority 1. Now when the broadcast intent button is pressed, a listener calls sendOrderedBroadcast, passing in a new show toast intent. This intent is first received by a receiver 2 instance, and then by a receiver 1 instance that was created in this file. Let's open the receiver 1 code. Now here in on-receive, you see that the code checks to see whether this is an ordered broadcast. And if so, it calls abort broadcast, which consumes the broadcast, and in this case, prevents it from being sent on to receiver 3. Now let's also look at a slightly more complicated use of abort broadcast. In this application, called ordered broadcast with result receiver, we'll see that a single toast message is displayed, that shows all the broadcast receivers that receive this intent, and that indicates the order in which they received it. Now here, I'll start the application. Now I'll press its Broadcast Intent button, and there's the toast message. It shows that receiver 2 received the intent, then receiver 1, then receiver 3. Let's look at the source code. Here's the application, open in the IDE. Now I'll open the main activity. And go to the listener for the broadcast intent button. As you can see, this code uses the second form of the send broadcast method. One of the interesting parameters of this method, is a broadcast receiver. I'll call it the result receiver. That will receive the intent after all the other broadcast receivers, have gotten the chance to receive it. And this is useful if the initial broadcast receivers compute some resolve. Because that result will then be available to this last receiver. And it can get that result by calling getResultData. As we see here. Now let's take a look at one of the broadcast receiver classes to see how they compute the result, that this result receiver finally displays in the toast message. Now here's the Receiver1 class. And as you can see, its onReceive method calls getResultData. To get the current result data. And then it tacks on its own string at the end. And then saves the new string by calling setResultData. Now since all the broadcast receivers do this in turn, the final result data is a single string showing which receivers received the intent. And the order in which they received it. The last kind of broadcast I'll talk about today, are sticky broadcasts. As I said earlier, non-sticky broadcasts indicate that something has happened at a specific moment in time. They announce events. So, once the event is over, it's over. Android disposes of the event and moves on. If a broadcast receiver wasn't registered to receive an intent when it happened, say yesterday, then it shouldn't be told about it now. Because for example it might think that the event just happened, and that could lead to all kinds of timing problems and other difficulties. Other events however, indicate state changes that may persist over time. Broadcast receivers that want to know about the current device state for example, we'll still want that information even if they weren't registered to be notified when that particular state changed. For example if the battery level goes very low, Android will broadcast this fact in the system. Good application will want to be good device citizens. And not do battery consuming operations when the device is in this low state. So in this case, if a new application starts up, and registers to hear about the battery state, that application needs to know, right now, if the device is in the low battery state. And because of this, Android broadcasts the battery low intent as a sticky broadcast. So sticky intents are cached by Android, and sticky broadcasts of a given intent overwrite any cached values from previous sticky broadcasts of a matching intent. When a broadcast receiver is dynamically registered, any cached intents that match its intent filter, will be broadcast to it. In addition, one matching cached intent, will be returned to the caller of register receiver. Now, similar to what we saw with non-sticky broadcasts, sticky broadcasts can be sent normally, that is, without a defined order, or sequentially, in priority order. Normal sticky broadcasts can use this method, and order sticky broadcasts can use this method. And finally, applications that want to broadcast Sticky intents must have the BROADCAST_STICKY permission. Let's look at an example application that uses Sticky Broadcasts. Now here I'll run the sticky intent application in the emulator. I've also opened a terminal window, and started a telnet session with that emulator. Now, I'll start the application, which displays the current battery level. And displays the string, Reading may be stale, and this last string just indicates that the battery level reading, comes from a cached StickyBroadcast, not from a fresh broadcast. If I now go to the terminal window and change the battery level, a new intent will be broadcast, reflecting the updated battery level. So now I'll type power capacity 95, and hit Return. As you can see, the display has been updated. And that display text has changed to indicate that the broadcast receiver can distinguish between fresh broadcasts and a cached one. Let's look at the source code for this application. Now, here I'm in the IDE. And now we'll open the main activity for this application. It calls register receiver, and passes in a broadcast receiver as defined in line. Let's look at the onReceive method of that broadcast receiver. First it checks to see whether its receiving a battery_ changed intent. If so it determines whether the broadcast is new, or cached by calling is initial sticky broadcast. This method returns true, if this intent is a cached value. And after that the code sends the text to display.