Grokking Android

Getting Down to the Nitty Gritty of Android Development

Android Quick Tip: Enabling and Disabling BroadcastReceivers at Runtime

By

BroadcastReceivers are good when you want to be notified about system events. But sometimes you do need to know about an event only once or for a short period of time.

A dynamically registered receiver doesn't cut it because the Activity and it's dynamically registered broadcast receiver might long be dead when the event occurs. The only way to achieve this is by enabling and disabling broadcast receivers in your code.

Enabling or Disabling BroadcastReceivers

You enable or disable receivers by using methods of the PackageManager class. With this class you can enable and disable app components at runtime:


PackageManager pm = getPackageManager();
ComponentName compName = 
      new ComponentName(getApplicationContext(), 
            YourReceiver.class);
pm.setComponentEnabledSetting(
      compName,
      PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 
      PackageManager.DONT_KILL_APP);

There are three states the PackageManager offers for this:

Supported states of setComponentEnabledSetting()
COMPONENT_ENABLED_STATE_DEFAULT Sets the state to the manifest file value
COMPONENT_ENABLED_STATE_DISABLED Sets the state to disabled
COMPONENT_ENABLED_STATE_ENABLED Sets the state to enabled

By default the PackageManager kills your app immediately, since a component state change could lead to unpredictable situations. The flag DONT_KILL_APP prevents this from happening and is safe to use for BroadcastReceivers. Of course if you do not use the DONT_KILL_APP-flag, you will spot your mistake even with the most cursory of testings 🙂

Disabling BroadcastReceivers by default

If you want to enable your receiver at runtime, you can set the state to disabled initially. You can do so in the manifest file:


<receiver
   android:name=".YourReceiver"
   android:enabled="false" >
   <!-- your intent filter -->
</receiver>

When to use this

The basic reason why you should do this, is that you want to preserve valuable resources on your user's devices. You do not want to drain the battery by running code that is not relevant to your user. Most often you can achieve this by using a dynamically registered receiver. But this does not always work.

Three examples where you should explicitly use the PackageManager-solution presented above:

1. You might need to know about the next boot, but only the next one. In this case you cannot use a dynamically registered receiver. You have to use a statically registered one. But you do not want to run it on every boot completion. Which means that you have to disable the receiver after it's first run.

2. If one or more receivers depend on the state of a specific system service you can disable all of them for as long as the necessary service is not in the desired state. This could be true for network connectivity, while waiting for a GPS fix, for missing Bluetooth availabilty and such.

3. You intend to use notifications - but only if the app is not currently active. In this case your BroadcastReceiver has to be enabled by default. But you would disable it in your Activities' onResume() method and re-enable it in the onPause() method.

See also Reto Meier's blog post about location-based apps and have a thorough look at the accompanying source code. He covered these topics initially in his talk at Google's IO 2011. I highly recommend to watch the video of this talk. It's definitely a good watch!

Wolfram Rittmeyer lives in Germany and has been developing with Java for many years.

He has been interested in Android for quite a while and has been blogging about all kind of topics around Android.

You can find him on Google+ and Twitter.