37

When should I use unregisterReceiver? In onPause(), onDestroy(), or onStop()?

Note: I need the service to run in the background.

Update:

  1. I get an exception releasing receivers null.

  2. Activity has leaked intent receivers are you missing call to unregisterReceiver();

Please tell me if there's something wrong, here's my code:

private boolean processedObstacleReceiverStarted;
private boolean mainNotificationReceiverStarted;

protected void onResume() {

    super.onResume();
    try {
        registerReceivers();

    } catch (Exception e) {

        Log.e(MatabbatManager.TAG,
                "MAINActivity: could not register receiver for Matanbbat Action "
                        + e.getMessage());
    }
}

private void registerReceivers() {

    if (!mainNotificationReceiverStarted) {
        mainNotificationReceiver = new MainNotificationReceiver();

        IntentFilter notificationIntent = new IntentFilter();

        notificationIntent
                .addAction(MatabbatManager.MATABAT_LOCATION_ACTION);
        notificationIntent
                .addAction(MatabbatManager.MATABAT_New_DATA_RECEIVED);
        notificationIntent
                .addAction(MatabbatManager.STATUS_NOTIFCATION_ACTION);
        registerReceiver(mainNotificationReceiver, notificationIntent);

        mainNotificationReceiverStarted = true;

    }

    if (!processedObstacleReceiverStarted) {
        processedObstacleReceiver = new ProcessedObstacleReceiver();
        registerReceiver(processedObstacleReceiver, new IntentFilter(
                MatabbatManager.MATABAT_ALARM_LOCATION_ACTION));
        processedObstacleReceiverStarted = true;

    }

}

private void unRegisterReceivers() {

    if (mainNotificationReceiverStarted) {
        unregisterReceiver(mainNotificationReceiver);
        mainNotificationReceiverStarted = false;
    }
    if (processedObstacleReceiverStarted) {
        unregisterReceiver(processedObstacleReceiver);
        processedObstacleReceiverStarted = false;
    }

}


@Override
protected void onDestroy() {
    // TODO Auto-generated method stub
    super.onDestroy();

    try {

        unRegisterReceivers();
        mWakeLock.release();//keep screen on
    } catch (Exception e) {
        Log.e(MatabbatManager.TAG, getClass() + " Releasing receivers-" + e.getMessage());
    }

}
Kevin Coppock
  • 133,643
  • 45
  • 263
  • 274
Muhammad
  • 555
  • 1
  • 5
  • 20
  • Firstly, you never have to call life-cycle methods like onPause(), onDestroy() or onStop(). – lithos35 Jan 15 '14 at 11:43
  • What is the expected behavior of your app? All of the above mentioned cases are valid, it all depends on your use case – gunar Jan 15 '14 at 11:43
  • Here is a clear answer: [Register and unregister broadcast receiever](https://stackoverflow.com/a/57452511/3842263) – Yosidroid Aug 11 '19 at 18:31
  • Helpful answer [register and unregister broadcast receiver](https://stackoverflow.com/a/57452511/3842263) – Yosidroid Aug 11 '19 at 18:33

4 Answers4

92

it depends on where you have register the receiver. The complementary method pairs are

onCreate - onDestroy
onResume - onPause
onStart  - onStop

if you register the receiver in the first one then unregister it in it's ending method.

stinepike
  • 54,068
  • 14
  • 92
  • 112
  • 2
    @nAkhmedov, can you please explain – stinepike Jun 08 '15 at 08:52
  • 6
    The last lifecycle event handler that is guaranteed to be called before an app is terminated (if you’re supporting pre-HoneyComb devices) is onPause. If you're only supporting Post-HoneyComb devices, then onStop is the last guaranteed handler. You should never assume onDestroy will be called and thus, you should unregister the receiver before this lifecycle event. Source: [Android Developer docs](http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle) – w3bshark Nov 04 '15 at 19:25
  • 3
    @w3bshark: If your process is being killed to reclaim memory, then it doesn't matter if you unregister the receiver, as your application will be evicted from memory (including your receiver). You only need to worry about killable states if you have something that's persistent and you must guarantee the method will be called. – Kevin Coppock Feb 18 '16 at 05:33
10

From the Android documentation:

You should implement onStop() to release activity resources such as a network connection or to unregister broadcast receivers.

Then, I would follow these pairs (using @StinePike's analogy):

onResume - onPause
onStart  - onStop

Because of the Android Lifecycle, and as @w3bshark mentioned:

In post-HoneyComb (3.0+) devices, onStop() is the last guaranteed handler.

Evin1_
  • 12,292
  • 9
  • 45
  • 47
  • Thus, you have to register and unregister receivers in onResume and onPause, because they will be call for sure before the fragment or the activity is destroyed. – Pedro Varela Apr 21 '16 at 20:13
2

It is just as simple as that, if you want to listen for events even when your activity is not visible then call unregister in onStop() (E.g From Activity A you open Activity B but if you want A to still listening for the events).

But when you only want to listen only for events when your activity is visible then in onPause call unregister() (E.g From Activity A you opened Activity B but now you do not want to listen for events in activity A).

Hope this helps your problem.

Sudhanshu Gaur
  • 7,486
  • 9
  • 47
  • 94
  • when we call activity A to activity B, activity A goes in onStop state and the receiver will get unregistered and won't listen to broadcasts. – Bawa Oct 23 '19 at 05:40
1

An broadcast receiver is an invisible component. All it does it respond to some kind of an change via onReceive() callback.

So it makes sense to activate them , only when your activity is in a state to respond or when it is becoming Enabled /active - which is when onResume() is called.

So it is a better practice to register in onResume() - When activity is visible & Enabled and unregister in onStop() when activity is no longer Active.

WonderBoy
  • 279
  • 1
  • 3
  • 7
  • This often won't work, since onStart/onResume of activity B happens before onStop of activity A (when moving from A -> B). The wrong activity may catch your broadcast, causing difficult to debug issues. – Brian Nov 02 '15 at 05:17