Broadcast Receiver Register in Manifest vs. Activity

AndroidAndroid IntentBroadcastreceiverIntentfilter

Android Problem Overview


I need some help to understand when I can expect my broadcast receiver will work when just registered in the manifest versus having to be registered from a running activity or service.

So for example if I register a stand alone receiver with the following intent filter it works without having a service/activity reference to it:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.blk_burn.standalonereceiver"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="10" />
    <uses-permission android:name="android.permission.WAKE_LOCK"/>

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        
        <receiver android:name="TestReceiver">
            <intent-filter>
                <action android:name="android.media.AUDIO_BECOMING_NOISY"/>
            </intent-filter>
        </receiver>
        
    </application>

</manifest>

However if I replace android.media.AUDIO_BECOMING_NOISY with android.intent.action.HEADSET_PLUG the receiver is not triggered (Android Documentation)

From what I found on this site you have to register this receiver from an activity or service that is already running for it to work (Post).

  • Can anyone tell me why this does not work when just adjusting your intent filter in the manifest and why you need to have a service running in the background that references/registers the receiver?

  • Is there a work around so that I can just register my receiver in my app's manifest using an intent filter with android.intent.action.HEADSET_PLUG?

  • How can do I identify which Broadcast actions from the android documentation need to have a service or activity register them versus just having the right filter in the manifest?

Android Solutions


Solution 1 - Android

If your receiver is registered in the manifest, and your app is not running, a new process will be created to handle the broadcast. If you register it in code, it's tied to the life of the activity/service you registered it in. For some broadcasts, it doesn't really make sense to create a new app process if it doesn't exist, or there are some security, performance, etc. implications, and thus you can only register the receiver in code.

As for the HEADSET_PLUG broadcast, it seems the idea is that your already running app can get this to do app-specific adjustments to UI, volume, etc. If your app is not running, you shouldn't really care about the headphones being unplugged.

AFAIK, there is no single place this info is summarized for all broadcasts, but each Intent should have a comment in the JavaDoc about how to register and use it, but apparently it's lacking in places. You should be able to compile a list if you grep the Android source tree for Intent.FLAG_RECEIVER_REGISTERED_ONLY.

Solution 2 - Android

As usual broadcast receivers can be configured in the manifest fileAndroidManifest.xml. A BroadcastReceiver that is configured in this way is called statically registered.

You can register your receiver in the manifest file by using the element:

<receiver
   android:name=".ConnectivityChangeReceiver">
   <intent-filter>
      <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
   </intent-filter>
</receiver>

The nested element is used to specify the event the receiver should react to.

Dyanmic Broadcast Recievers

As an alternative you can register your BroadcastReceiver implementation dynamically in your code. You just need to call the registerReceiver() method on your Context object.

The registerReceiver() method takes two parameters:

The arguments of the registerReceiver() method

  • receiver : The BroadcastReceiver you want to register
  • filter : The IntentFilter object that specifies which event your receiver should listen to.

When you register your receiver in this way, it lives for as long as the component livesand Android sends events to this receiver until the creating component itself gets destroyed.

It’s your task to handle the lifecycle correctly. Thus when you add a receiver dynamically, take care to unregister the same receiver in the onPause() method of your Activity!

I suggest to register the receiver in the onResume() method of your Activity and to unregister it in your onPause() method:

@Override
protected void onPause() {
   unregisterReceiver(mReceiver);
   super.onPause();
}

@Override
protected void onResume() {
   this.mReceiver = new ConnectivityChangeReceiver();
   registerReceiver(
         this.mReceiver, 
         new IntentFilter(
               ConnectivityManager.CONNECTIVITY_ACTION));
   super.onResume();
}

When to use which method to register

Which method to use for registering your BroadcastReceiver depends on what your app does with the system event. I think there are basically two reasons why your app wants to know about system-wide events:

  • Your app offers some kind of service around these events
  • Your app wants to react graciously to state changes

Examples for the first category are apps that need to work as soon as the device is booted or that must start some kind of work whenever an app is installed. Battery Widget Pro or App2SD are good examples for these kinds of apps. For this type you must register the BroadcastReceiver in the Manifest file.

Examples for the second category are events that signal a change to circumstances your app might rely on. Say your app depends on an established Bluetooth connection. You have to react to a state change – but only when your app is active. In this case there is no need for a statically registered broadcast receiver. A dynamically registered one would be more reasonable.

There are also a few events that you are not even allowed to statically register for. An example for this is the Intent.ACTION_TIME_TICK event which is broadcast every minute. Which is a wise decision because a static receiver would unnecessarily drain the battery.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionControlAltDeleteView Question on Stackoverflow
Solution 1 - AndroidNikolay ElenkovView Answer on Stackoverflow
Solution 2 - AndroidHaythem BEN AICHAView Answer on Stackoverflow