tags:

views:

1186

answers:

3

My android application requires a password to be entered as the first activity. I want to be able to automatically send the application back to the password entry screen after the application has been idle for a fixed amount of time.

The application has multiple activities, but I would like the timeout to be global to all activities. So, it wouldn't be sufficient to create a timer thread in the onPause() method of an activity.

I'm not sure what the best definition for the application being idle is, but no activities being active would be sufficient.

+2  A: 

Check out how OpenIntents Safe implements this functionality.

alex
A: 

I dealt with this by using the AlarmManager to schedule and cancel timeout action.

Then in the onPause() event of all of my activites, I schedule the alarm. In the onResume() event of all of my activities, I check to see if the alarm goes off. If the alarm went off, I shutdown my app. If the alarm hasn't gone off yet I cancel it.

I created Timeout.java to manage my alarms. When the alarm goes off a intent is fired:

public class Timeout {
    private static final int REQUEST_ID = 0;
    private static final long DEFAULT_TIMEOUT = 5 * 60 * 1000;  // 5 minutes

    private static PendingIntent buildIntent(Context ctx) {
     Intent intent = new Intent(Intents.TIMEOUT);
     PendingIntent sender = PendingIntent.getBroadcast(ctx, REQUEST_ID, intent, PendingIntent.FLAG_CANCEL_CURRENT);

     return sender;
    }

    public static void start(Context ctx) {
     long triggerTime = System.currentTimeMillis() + DEFAULT_TIMEOUT;

     AlarmManager am = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE);

     am.set(AlarmManager.RTC, triggerTime, buildIntent(ctx));
    }

    public static void cancel(Context ctx) {
     AlarmManager am = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE);

     am.cancel(buildIntent(ctx));
    }

}

Then, I created a service to capture the intent generated by the alarm. It sets some global state in my instance of the application class to indicate that the app should lock:

public class TimeoutService extends Service {
    private BroadcastReceiver mIntentReceiver;

    @Override
    public void onCreate() {
     super.onCreate();

     mIntentReceiver = new BroadcastReceiver() {
      @Override
      public void onReceive(Context context, Intent intent) {
       String action = intent.getAction();

       if ( action.equals(Intents.TIMEOUT) ) {
        timeout(context);
       }
      }
     };

     IntentFilter filter = new IntentFilter();
     filter.addAction(Intents.TIMEOUT);
     registerReceiver(mIntentReceiver, filter);

    }

    private void timeout(Context context) {
     App.setShutdown();

     NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
     nm.cancelAll();
    }

    @Override
    public void onDestroy() {
     super.onDestroy();

     unregisterReceiver(mIntentReceiver);
    }

    public class TimeoutBinder extends Binder {
     public TimeoutService getService() {
      return TimeoutService.this;
     }
    }

    private final IBinder mBinder = new TimeoutBinder();

    @Override
    public IBinder onBind(Intent intent) {
     return mBinder;
    }

}

Finally, I created a subclass of Activity that all of my app's activities subclass from to manage locking and unlocking:

public class LockingActivity extends Activity {

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

     Timeout.start(this);
    }

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

     Timeout.cancel(this);
     checkShutdown();
    }

    private void checkShutdown() {
     if ( App.isShutdown() ) {
      finish();
     }

    }

}

Using onPause and onResume to start and stop the timeout gives me the following semantics. As long as one of my application's activities is active, the timeout clock is not running. Since I used an Alarm type of AlarmManager.RTC, whenever the phone goes to sleep the timeout clock runs. If the timeout happens while the phone is asleep, then my service will pick up the timeout as soon as the phone wakes up. Additionally, the clock runs when any other activity is open.

Brian Pellin
A: 

Intents.TIMEOUT is not resolved.

Rashid
In this case Intents refers to com.keepassdroid.intents.Intents which defines TIMEOUT in my application. You'd need to define a similar string in your application.
Brian Pellin