Leaked Intent & AlarmManager
I am trying to create authentication system which pops up the login window if the device has been off (SCREEN_OFF) for more than INTERVAL.
I have registered a BroadcastReceiver to listen to SCREEN_ON/OFF events in the onCreate() of the launchable activity:
/* Listen to Screen On & Off events */
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
BroadcastReceiver screenOnOff = new ScreenOnOff();
registerReceiver(screenOnOff, filter);
ScreenOnOff -- is a BroadcastReceiver which among other things does:
@Override
public void onReceive(Context context, Intent intent) {
mAuthenticationIntent = PendingIntent.getActivity(context, 0,
new Intent(context, AuthenticationActivity.class), 0);
String action = intent.getAction();
if (action.equals(Intent.ACTION_SCREEN_OFF)) {
AlarmManager mAlarmManager = (AlarmManager) context
.getSystemService(context.ALARM_SERVICE);
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, System
.currentTimeMillis()
+ interval, mAuthenticationIntent);
Log.d(LOG_TAG, "Alarm Set!");
}
When the alarm goes off, the program crashes:
08-27 19:18:02.207: ERROR/ActivityThread(3165): Activity com.artoo.ArtooSlateActivity has leaked IntentReceiver com.artoo.authentication.ScreenOnOff@4495bca0 that was originally registered here. Are you missing a call to unregisterReceiver()?
08-27 19:18:02.207: ERROR/ActivityThread(3165): android.app.IntentReceiverLeaked: Activity com.artoo.ArtooSlateActivity has leaked IntentReceiver com.artoo.authentication.ScreenOnOff@4495bca0 that was originally registered here. Are you missing a call to unregisterReceiver()?
08-27 19:18:02.207: ERROR/ActivityThread(3165): at android.app.ActivityThread$PackageInfo$ReceiverDispatcher.<init>(ActivityThread.java:939)
08-27 19:18:02.207: ERROR/ActivityThread(3165): at android.app.ActivityThread$PackageInfo.getReceiverDispatcher(ActivityThread.java:734)
08-27 19:18:02.207: ERROR/ActivityThread(3165): at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:791)
08-27 19:18:02.207: ERROR/ActivityThread(3165): at android.app.ContextImpl.registerReceiver(ContextImpl.java:778)
08-27 19:18:02.207: ERROR/ActivityThread(3165): at android.app.ContextImpl.registerReceiver(ContextImpl.java:772)
08-27 19:18:02.207: ERROR/ActivityThread(3165): at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:318)
08-27 19:18:02.207: ERROR/ActivityThread(3165): at com.artoo.ArtooSlateActivity.onCreate(ArtooSlateActivity.java:50)
08-27 19:18:02.207: ERROR/ActivityThread(3165): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
08-27 19:18:02.207: ERROR/ActivityThread(3165): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
08-27 19:18:02.207: ERROR/ActivityThread(3165): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
08-27 19:18:02.207: ERROR/ActivityThread(3165): at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3815)
08-27 19:18:02.207: ERROR/ActivityThread(3165): at android.app.ActivityThread.access$2400(ActivityThread.java:125)
08-27 19:18:02.207: ERROR/ActivityThread(3165): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2037)
08-27 19:18:02.207: ERROR/ActivityThread(3165): at android.os.Handler.dispatchMessage(Handler.java:99)
08-27 19:18:02.207: ERROR/ActivityThread(3165): at android.os.Looper.loop(Looper.java:123)
08-27 19开发者_StackOverflow:18:02.207: ERROR/ActivityThread(3165): at android.app.ActivityThread.main(ActivityThread.java:4627)
08-27 19:18:02.207: ERROR/ActivityThread(3165): at java.lang.reflect.Method.invokeNative(Native Method)
08-27 19:18:02.207: ERROR/ActivityThread(3165): at java.lang.reflect.Method.invoke(Method.java:521)
08-27 19:18:02.207: ERROR/ActivityThread(3165): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
08-27 19:18:02.207: ERROR/ActivityThread(3165): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
08-27 19:18:02.207: ERROR/ActivityThread(3165): at dalvik.system.NativeStart.main(Native Method)
Any help will be most appreciated.
Thanks, Sameer
Since you are registering the receiver dynamically the system knows you are leaking memory because you never call unregister
on it. Obviously you don't want to unregister because you need to listen for SCREEN_ON/OFF events.
The Solution is to register the receiver in your Manifest.xml
Base class for code that will receive intents sent by sendBroadcast(). You can either dynamically register an instance of this class with Context.registerReceiver() or statically publish an implementation through the tag in your AndroidManifest.xml. Note: If registering a receiver in your Activity.onResume() implementation, you should unregister it in Activity.onPause(). (You won't receive intents when paused, and this will cut down on unnecessary system overhead). Do not unregister in Activity.onSaveInstanceState(), because this won't be called if the user moves back in the history stack
精彩评论