views:

161

answers:

1

Hey,

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: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

+1  A: 

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

smith324
I would agree, except that `ACTION_SCREEN_OFF`, and probably `ACTION_SCREEN_ON`, cannot be used by manifest-registered `BroadcastReceivers`: http://code.google.com/p/android/issues/detail?id=10735
CommonsWare
Exactly, so what do I do and how do I implement my code?
Sameer Segal