69
01-16 16:52:42.211: E/ActivityThread(2529): Activity com.Civilcourage.CivilcurageSplash has leaked IntentReceiver com.google.android.gcm.GCMBroadcastReceiver@405282e0 that was originally registered here. 

Are you missing a call to unregisterReceiver()?

What is the cause of the above error? How can it be avoided?

Nermeen
  • 15,883
  • 5
  • 59
  • 72
Raj
  • 905
  • 1
  • 8
  • 17
  • 7
    Can we accept an answer? – David Passmore Mar 06 '15 at 21:18
  • @DavidPassmore, I suppose, accepting answer in SO is a useless feature. Often you can see that newest answers are more suitable, than accepted. Also sometimes the second answer is more rated and more useful. – CoolMind Oct 15 '18 at 08:03

6 Answers6

62

Don't rely on onStop(), because:

Note that this method may never be called, in low memory situations where the system does not have enough memory to keep your activity's process running after its onPause() method is called

More on Activity life cycle here.

Unregister your receiver in onPause():

@Override
protected void onPause() {
    super.onPause();

    unregisterReceiver(yourReceiver);
}
Melquiades
  • 8,496
  • 1
  • 31
  • 46
  • Would it be okay to only unregister in onDestroy? – MobileMon Jul 08 '14 at 02:39
  • 6
    @MobileMon, use onResume() and onPause() to register/unregister receivers. onDestroy() might not always be called, same as onStop(). See a great explanation here by SnowyTracks: http://stackoverflow.com/questions/7887169/android-when-to-register-unregister-broadcast-receivers-created-in-an-activity – Melquiades Jul 08 '14 at 08:37
  • Also, onPause doesn't mean your activity will never be restarted again. Don't forget to re-register your receiver on onResume if you still need to receive broadcasts since the activity may be resumed before being destroyed. – Dzhuneyt Sep 22 '14 at 12:29
  • 1
    The answer is outdated. According to the documentation onStop will always be called on devices running Android with version > Honeycomb. onDestroy is the method that my not be called. Here is the reference: https://developer.android.com/reference/android/app/Activity.html – dephinera Jul 12 '17 at 13:58
  • This is the correct and accurate answer. Please anyone using the `onStop()` method, you should not use it really. Please read what's mentioned in the official documents about the activity lifecycle – blueware Oct 25 '17 at 13:48
49

You need to unregister your receivers on stop of your activity:

@Override
protected void onStop()
{
    unregisterReceiver(yourReceiver);
    super.onStop();
}
Nermeen
  • 15,883
  • 5
  • 59
  • 72
  • 1
    Unregistering your receiver in onStop() is the correct answer. You should not unregister just after receiving and it's not necessary to do so in onPause() either – portfoliobuilder Nov 29 '14 at 01:27
  • If it's in the case of DownloadManager Do we need to unregister it inside onStop() of the fragment – Abraham Mathew Apr 10 '19 at 14:39
7

You can unregister as soon as you receive the broadcastreceiver

 @Override
 public void onReceive(Context context, Intent intent) {
     getActivity().unregisterReceiver(this);
 }
Husnain Aslam
  • 865
  • 1
  • 11
  • 28
Omid Aminiva
  • 667
  • 5
  • 14
  • 4
    Isn't unregistering just after receiving a bad design unless we have that requirement – Nandish A Feb 19 '14 at 10:45
  • 2
    Yeah not sure why you would want to do this unless its a one time receive. Generally I set BroadcastReceivers up to continuous messages – MobileMon Jul 08 '14 at 12:12
  • 1
    In my case because I am using it in downloadmanager. So when file is finished downloading, I need to be notified. And If user starts to download another file, another broadcast receiver is being registered. This way if user starts downloading multiple files I have different broadcast receiver for each downloadmanager. – Omid Aminiva Aug 25 '14 at 14:07
4

Just to add to the answers above, if you register a receiver in on onCreate, it should be unregistered in onDestroy. if you register a receiver on onResume, you should unregister it in onPause.

Be mindful of where you register and unregister the receiver, for example, if you register a receiver in onCreate(Bundle) using the activity's context, you should unregister it in onDestroy() to prevent leaking the receiver out of the activity context. If you register a receiver in onResume(), you should unregister it in onPause() to prevent registering it multiple times (If you don't want to receive broadcasts when paused, and this can cut down on unnecessary system overhead). Do not unregister in onSaveInstanceState(Bundle), because this isn't called if the user moves back in the history stack.

Source

the_prole
  • 8,275
  • 16
  • 78
  • 163
3

Make sure receiver is registered before you unregister it. to do this, declare a boolean

private boolean isReceiverRegistered = false;

then right after calling registerReceiver() method, set the flag isReceiverRegistered to true as shown in the below code snippet

registerReceiver(broadcastReceiver, new IntentFilter("anyString"));
    isReceiverRegistered = true;

then, in onPause()

 @Override
protected void onPause() {
    super.onPause();
    if(isReceiverRegistered){
        unregisterReceiver(broadcastReceiver);
        isReceiverRegistered = false;// set it back to false.
    }
}
Soropromo
  • 1,212
  • 12
  • 17
2

Unregister your receiver on onStop() is the valid answer. Do not call it on onPause() method.

@Override
protected void onStop()
{
    unregisterReceiver(yourReceiverName);
    super.onStop();
}
Archa
  • 176
  • 1
  • 7