Я справился с этим с помощью AlarmManager, чтобы запланировать и отменить действие тайм-аута.
Затем в событии onPause () всех моих активностей я планирую тревогу. В событии onResume () всех моих действий я проверяю, сработал ли будильник. Если сработала сигнализация, я выключил свое приложение. Если тревога еще не сработала, я ее отменяю.
Я создал Timeout.java для управления своими тревогами. Когда сработала сигнализация, сработало намерение:
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) {
ctx.startService(new Intent(ctx, TimeoutService.class));
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));
ctx.startService(new Intent(ctx, TimeoutService.class));
}
}
Затем я создал сервис для захвата намерения, генерируемого сигналом тревоги. Он устанавливает некоторое глобальное состояние в моем экземпляре класса приложения, чтобы указать, что приложение должно блокироваться:
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;
}
}
Наконец, я создал подкласс Activity, из которого все подклассы действий моего приложения управляют блокировкой и разблокировкой:
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();
}
}
}
Использование onPause и onResume для запуска и остановки тайм-аута дает мне следующую семантику. Пока одно из действий моего приложения активно, часы таймаута не работают. Поскольку я использовал тип AlarmManager.RTC, каждый раз, когда телефон переходит в спящий режим, срабатывает тайм-аут. Если время ожидания истекло, когда телефон спит, моя служба определит время ожидания, как только телефон проснется. Кроме того, часы работают, когда открыты любые другие действия.
Для более подробной версии, вы можете увидеть, как я на самом деле реализовал их в своем приложении https://github.com/bpellin/keepassdroid