Leaked IntentReceiver in Google Cloud Messaging
Asked Answered
E

3

4

I have implemented GCM in my app and I am using GSMRegistrar as suggested here. No I am getting an error in logcat

7-02 23:35:15.830: E/ActivityThread(10442): Activity com.abc.xyz.mnp has leaked IntentReceiver com.google.android.gcm.GCMBroadcastReceiver@44f8fb68 that was originally registered here. Are you missing a call to unregisterReceiver()?

What I can understand from this and looking at the code for GSMRegistrar is I need to to call GSMRegistrar.onDestroy(this) but I could not understand where should I call this? Calling in onDestroy() of activity mnp causes it to stop retrying for GSM Registartion

Emotionalism answered 2/7, 2012 at 18:39 Comment(0)
D
12

You may use the application context, instead of the activity context. That way the backoff mechanism is not restricted by the activity life cycle.

Deuced answered 13/7, 2012 at 15:8 Comment(1)
Thanks. It helps. e.g: Have it like this: GCMIntentService.register(getApplicationContext()); instead of something like: GCMIntentService.register(RegisterActivity.this);Selfrenunciation
C
8

It should be called inside onDestory() method of the activity that you started the GCM registration.

Keep in mind an activity may not be destroyed, even though another activity is launched on top of it. So your registration could still be retried in the background. If the registration activity is destroyed, then your GCMBroadcastReceiver class won't be there to handle the response anyway.

Update: After looking at the GCM library source code more carefully, here's what I've observed:

  1. The GCM library uses the activity context to register a receiver, for the purpose of retrying registration if it fails, it will use a backoff mechanism to retry.
  2. You should call GCMRegistrar.onDestroy() on your activity's onDestroy() method, it's a good Android practice to unregister a receiver before activity is destroyed.
  3. Because of #2, it means that your app won't attempt to re-register, if the activity that calls GCMRegistrar.register is destroyed. The user has to go back to this activity for the registration process to kick off again.
  4. If you don't want behavior #3, you may have to implement your own GCM registration and retry mechanism. For example, if the retry mechanism is done in a separate background thread, then it could keep on trying even though the activity is destroyed, as long as the application is running.

I think #3 is acceptable, as it's very rare that the GCM server will reject the registration with 'SERVICE_NOT_AVAILABLE' error. And as long as your user runs your app a few times, sooner or later their device will have successful registration.

Collimore answered 2/7, 2012 at 20:46 Comment(8)
Hi, thanks for the answer. I tried to understand your point that * If the registration activity is destroyed, then your GCMBroadcastReceiver class won't be there to handle the response anyway.* Why do you say so?Emotionalism
When you call GCMRegistrar.register(this,xxxx); the GCM library is using the context of your activity to handle the responses. If your activity is destroyed by the OS (perhaps on low memory situation), then that context is no longer valid, so if a response is received from the GCM library, the app may be referencing a destroyed context, which will give unpredictable results. So it's safer to call GCMRegistrar.onDestory() when the activity is being destroyed.Collimore
+1 for your comment, let me work more on this. Why not use application context instead of activity context?Emotionalism
I believe the Google sample requires activity context, because it is displaying dialogs on registration results. Look for mHandleMessageReceiver in the sample. But the best practice for BroadcastReceiver is if you register it in an activity, you must unregister it before activity is destroyed. That's what the 'leaked' intent message is warning you about.Collimore
You are right that leaked intent' is because I did not unregistered the intent. Can you tell me where you want to look for mHandleMessageReceiver`? I tried to find where registration results are displaying dailogs, can you direct me towards those?Emotionalism
I was referring to the GCM Library sample. If you look for the demo client source, you will see this receiver is used by the demo client to display a message box showing the GCM registration status.Collimore
Showing dialog box is not compulsory.Emotionalism
GCMRegistrar does not use Activity context, it uses a context you pass on too it.Emotionalism
B
2

you have to destroy GCMRegistrar in your onDestroy method of activty class

        unregisterReceiver(receiver);
        GCMRegistrar.onDestroy(this);
Borax answered 3/7, 2012 at 10:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.