The following is the first few sections of a chapter from The Busy Coder's Guide to Android Development, plus headings for the remaining major sections, to give you an idea about the content of the chapter.


Broadcasts and Broadcast Receivers

One channel of the Intent message bus is used to start activities. A second channel of the Intent message bus is used to send broadcasts. As the name suggests, a broadcast Intent is one that — by default – is published to any and all applications on the device that wish to tune in.

Sending a Simple Broadcast

The simplest way to send a broadcast Intent is to create the Intent you want, then call sendBroadcast().

That’s it.

At that point, Android will scan through everything set up to tune into a broadcast matching your Intent, typically filtering just on the action string. Anyone set up to receive this broadcast will, indeed, receive it, using a BroadcastReceiver.

Receiving a Broadcast: In an Activity

To receive such a broadcast in an activity (or a fragment), you will need to do four things.

First, you will need to create an instance of your own subclass of BroadcastReceiver. The only method you need to (or should) implement is onReceive(), which will be passed the Intent that was broadcast, along with a Context object that, in this case, you will typically ignore.

Second, you will need to create an instance of an IntentFilter object, describing the sorts of broadcasts you want to receive. Most of these filters are set up to watch for a single broadcast Intent action, in which case the simple constructor suffices:

new IntentFilter(Intent.ACTION_CAMERA_BUTTON)

Third, you will need to call registerReceiver(), typically from onStart() of your activity or fragment, supplying your BroadcastReceiver and your IntentFilter.

Fourth, you will need to call unregisterReceiver(), typically from onStop() of your activity or fragment, supplying the same BroadcastReceiver instance you provided to registerReceiver().

In between the calls to registerReceiver() and unregisterReceiver(), you will receive any broadcasts matching the IntentFilter.

The biggest downside to this approach is that some activity has to register the receiver. Sometimes, you want to receive broadcasts even when there is no activity around. To do that, you will need to use a different technique: registering the receiver in the manifest.

Receiving a Broadcast: Via the Manifest

You can also tell Android about broadcasts you wish to receive by adding a <receiver> element to your manifest, identifying the class that implements your BroadcastReceiver (via the android:name attribute), plus an <intent-filter> that describes the broadcast(s) you wish to receive:

<receiver android:name=".OnBootReceiver">
  <intent-filter>
    <action android:name="android.intent.action.BOOT_COMPLETED"/>
  </intent-filter>
</receiver>

The good news is that this BroadcastReceiver will be available for broadcasts occurring at any time. There is no assumption that you have an activity already running that called registerReceiver().

The bad news is that the instance of the BroadcastReceiver used by Android to process a broadcast will live for only so long as it takes to execute the onReceive() method. At that point, the BroadcastReceiver is discarded. Hence, it is not safe for a manifest-registered BroadcastReceiver to do anything that needs to run after onReceive() itself completes, such as forking a thread. After all, Android may well terminate the process within milliseconds, if there is no other running component in the process.

More bad news: onReceive() is called on the main application thread — the same main application thread that handles the UI of all of your activities. And, you are subject to the same limitations as are your activity lifecycle methods and anything else called on the main application thread:

This makes using a manifest-registered BroadcastReceiver a bit tricky. If the work to be done is very quick, just implement it in onReceive(). Otherwise, you will probably need to pair this BroadcastReceiver with a component known as an IntentService, which we will examine in the next chapter.

The Stopped State

On Android 3.1 and higher, when your app is first installed on the device, it is in a “stopped” state. This has nothing to do with onStop() of any activity. While in the stopped state, your manifest-registered BroadcastReceivers will not receive any broadcasts.

Getting Out of the Stopped State

To get out of the stopped state, something on the device, such as another app (that itself is not in the stopped state), must use an explicit Intent to invoke one of your components.

The most common way this happens is for the user to tap on a launcher icon associated with your launcher activity. Under the covers, the home screen’s launcher will create an explicit Intent, identifying your activity, and use that with startActivity(). This moves you out of the stopped state.

Getting Into the Stopped State

As noted above, you start off in the stopped state. Once you are moved out of the stopped state, via the explicit Intent, you will remain out of the stopped state until one of two things happens:

  1. The user uninstalls your app
  2. The user “force-stops” your app

The latter normally occurs when the user clicks the “Force Stop” button on your app’s screen in the Settings app (Settings > Apps). There is some evidence that some device manufacturers have tied their own device’s task manager to do a “force stop” when the user removes a task — this was not a particularly wise choice on the part of those manufacturers.

Note that a reboot does not move you back into the stopped state. You remain in the normal state through a reboot.

Example System Broadcasts

The preview of this section was lost in the sofa cushions.

The Order of Things

The preview of this section took that left turn at Albuquerque.

Keeping It Local

The preview of this section is [REDACTED].

Visit the Trails!

The preview of this section is sleeping in.