[MUSIC] In this lesson, we're going to talk about another fundamental Android component. The broadcast receiver class. I'll begin by discussing the BroadcastReceiver class, and the basic work flow that you follow when you're using it. Next I'll discuss how broadcast receivers are registered with the Android system. After that I'll talk about the different ways that events can be broadcast to those broadcast receivers. And lastly I'll finish up with a short discussion of how broadcast receivers are notified, and how they handle the broadcasts they receive. The BroadcastReceiver is a base class for components, whose purpose is to wait for certain events to occur, to receive those events, and then to react to them. And the way this all works, is that individual broadcast receivers, register to receive the specific events in which they're interested. For example, there's a broadcast receiver in Android whose job is to listen for outgoing MMS messages. Now, somewhere else at a later time, a component does something that it wants to inform broadcast receivers about. So, it creates an intent that represents that event and then it broadcasts that intent. So, there are other components in Android that prepare MMS messages, so that they can be later sent out over the network. Once the MMS message is ready then there's a component that create an action_send_message intent, and then broadcast that intent. Android then takes the intent that was just broadcast, and delivers it to that component we've talked about, before that have registered to receive action_send_message intents. And that component finally receives the intent by getting a call to its onReceive method with that intent as one of the parameters to the method. Now, for our MMS example, the component receives the action_send_message intent. And eventually sets off a service to deliver the MMS message. So, to recap, the basic workflow is one, BroadcastReceivers registered to receive specific intents. Two, some component generates an intent, and then broadcast it to the system. Three, Android delivers that intent to the broadcast receivers that registered to receive it. And four the broadcast receivers then get a call to their onReceive method. During which they handle the incoming event. So, let's talk about each of these steps one at a time. So, in order to register a broadcast receiver, developers have two options. One, they can register the broadcast receiver statically by putting some information in the AndroidManifest.XML file of the application, to which the broadcast receiver belongs. Or two, they can register the broadcast receiver dynamically by invoking some methods at run time. So, to register a broadcast receiver statically. You add a receiver tag in your applications AndroidManifest.XML file. And then within that receiver tag, you put at least one intent filter tag. And the information there tells Android that when an intent matching this intent filter is broadcast. This broadcast receiver wants to know about it, and the format for a receiver tag looks something like this. You start with the receiver keyword and then you add some of the following attributes. And some of those attributes include android:enabled, which allows you to enable or disable a particular receiver. Another is android:exported. If set to true, then this receiver can receive broadcasts from outside its application, while if it's set to false and the receiver can only receive intents that are broadcast by other components within this application. Another attribute is android:name which gives the name of the class that implements this receiver. There is also android:permission which defines a permission string. That the sender of an intent must have in order for this receiver to receive an intent from them. And, as I said, you also have to specify at least one intent filter tag, which we covered back in our lesson on intents. Now once you've created the receiver tag. You insert and intent-filter tag as one of it's children. And just like with intent-filters that are used to start activities, these intent-filter tags can specify things like an action, data, and categories. Now, if you do register a receiver statically. That information will be read and processed, when the system boots up. Or when the application package is added, if that happens while the system is running. So, let's take a look at an application that statically registers a single broadcast receiver, to receive a custom intent that I'll call the show toast intent. And I'll start up the single broadcast static registration application. This application displays a single button labeled Broadcast Intent. Pressing this button causes an intent to be broadcast, and then routed to and received by a broadcast received which then displays a toast message. Now, I'll press the button. And there you see the toast message, indicating that the receiver got the intent. Now, here I've open up the application in the IDE. Now, open the main activity, and this code first defines an intent action string that will be used to identify this intent. Scrolling down, there's a button listener, that calls the context.send, broadcast, method. Passing in an intent, and a permission string. The intent will be matched against registered intent filters. While the permission string indicates that this intent, can only be delivered to broadcast receivers that have this particular permission. You can also register broadcast receivers programatically at run time, for instance if you want your broadcast receiver. To respond to attempts only while your activity is in the foreground. Well then you can dynamically register and unregister them in your activities, on resume, and on pause methods for example. And to do this, you'll first create an intent filter object, specifying the intents that you want to register for. Next you create the broadcast receiver. And then you register it by calling a register receiver method. And there are different implementations of this method. One is in the local broadcaster manager class. And this one is for broadcasts, that are meant only for this application. And therefore, they don't need to be broadcast systemwide. The other implementation is in the context class. And this one broadcast intents systemwide. So, these intents can potentially be received by any application on your device. Then finally as necessary you can call an unregister receiver method to unregister these broadcast receivers. Let's look at the source code for the single broadcast dynamic registration application. This application looks exactly like the previous application. There's a broadcast intent button, and when you press it an intent is broadcast. A broadcast receiver receives the intent, and then displays a toast message, internally however, its implementation is a little bit different. So, this code starts off by creating an intent action string and next it creates an intent filter, object with the just created action string. After that, it creates a broadcast receiver instance called receiver. And then down in the on create method the code gets an instance of the local broadcast manager. Which, as I said, is used to broadcast and receive intents, only within this application. Next the code uses the local broadcast manager, to register the receiver object for the show toast intent. And after that if the broadcast intent button is pressed, the listener calls local broadcast manager.send broadcast passing in the intent. When the button is pushed the local broadcast manager will send the intent to the receiver object, which operates just as it did in the last application creating and displaying a toast message. Now my example so far, simply broadcasting single intent to a single receiver. But Android supports a variety of different ways in which intents can be broadcast. For example, intents can be broadcast normally, or in order. Normal broadcast are delivered to subscribed broadcast receivers in an undefined order. So, if you have two broadcast receivers that should receive a single intent, it's possible that both broadcast receivers could be processing the intent at the same time. Ordered broadcast on the other hand, deliver the intent to multiple broadcast receivers one at a time in priority order. And broadcasts can also be sticky or non-sticky. A sticky intent sticks around after its initial broadcast. So, a broadcast receiver that is registered after the initial broadcast of an intent. May still be able to receive it, even though it wasn't around when the intent was actually broadcast. And this feature is useful for example, to record system state changes, such as changes in the battery level, or charging status. In these cases, it doesn't matter to the receiver when the state changed. Right, they just want to know what the current state is. Non-sticky broadcasts in contrast are discarded after their initial broadcast. And these broadcasts are more suited therefore, to reporting that a certain event has occurred. In these cases, if the receiver isn't registered to receive the broadcast when it happens, then there, they won't get it. And lastly, as we saw in the examples, some broadcast methods also take a permission string. Which limits the broadcast to those broadcast receivers that have the specified permission. Now, if you find yourself having trouble, getting broadcasts to the right broadcast receivers. There are a few things that you can do one is to have Android log extra information about its intent resolution process. And you can do this by setting the FLAG_DEBUG_LOG_RESOLUTION flag in the intent that you're going to broadcast. Another is to use the ADB tool to find out what broadcast receivers have been registered. And you can use the dumpsys command like this, to show broadcast receivers that are dynamically registered. And you can use it like this, to show those that are statically registered.