Ответ 1
Хорошо, так как это оказалось особенно сложным вопросом, я подумал, что отправлю свое решение здесь, если кто-нибудь когда-нибудь ударит что-нибудь подобное.
Существует несколько способов приблизиться к этому, но самый простой, который я использовал, - это иметь "запущенный" сервис, который решает, когда нужно закрыться. Мои действия привязываются/отключаются к сервису, и после установленной задержки (я использовал 1 минуту) служба отключится, если дальнейшие действия не будут связаны - это охватывает, если пользователь перестает использовать приложение плюс, если есть любые ошибки со смертельным исходом.
Таймер отключения запланирован в пределах onUnbind()
и отменяется в onStartCommand()
, onBind()
, onRebind()
. Если он срабатывает, он отключает службу вниз, что, в свою очередь, вызывает очистку управляемого состояния в сервисе onDestroy()
.
Мой Service
код выглядит следующим образом:
public class LocalStateService extends Service {
/** The binder to give to clients. */
private final IBinder binder = new LocalStateBinder();
/** Used for time-delayed shutdown. */
private final Handler handler = new Handler();
/**
* Called before starting or the first binding.
*/
@Override
public void onCreate() {
// initialise state...
}
/**
* Called when this service is explicitly started.
* @param intent The intent passed on starting, unused
* @param flags Startup flags, unused
* @param startId Identifies each start request
* @return Desired restart behaviour
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
cancelShutdown();
// if killed, we would like Android to restart this service, but don't bother re-delivering
// the original intent used to start the service
return START_STICKY;
}
/**
* Called when the first client binds.
* @param intent The intent passed on binding
* @return The binding to use
*/
@Override
public IBinder onBind(Intent intent) {
cancelShutdown();
return binder;
}
/**
* Called when the first of previous clients re-binds.
* @param intent The intent passed on binding
*/
@Override
public void onRebind(Intent intent) {
cancelShutdown();
}
/**
* Called when all clients have unbound.
* @param intent The first intent originally passed on binding
* @return Whether this service should be notified of rebinding
*/
@Override
public boolean onUnbind(Intent intent) {
// post a callback to be run in 1 minute
handler.postDelayed(delayedShutdown, 1000L * 60);
// we do want onRebind called when clients return
return true;
}
@Override
public void onDestroy() {
// state cleanup...
}
private Runnable delayedShutdown = new Runnable() {
@Override
public void run() {
LocalStateService.this.stopSelf();
}
};
/**
* Cancel any shutdown timer that may have been set.
*/
private void cancelShutdown() {
// remove any shutdown callbacks registered
handler.removeCallbacks(delayedShutdown);
}
}
Вместо этого из моего Application
моя основная деятельность вызывает startService(..)
в onCreate()
, так как это будет работать как для первоначального запуска, так и когда пользователь вернется к использованию приостановленного приложения (где служба может или может не решили закрыть себя).
Каждое действие затем связывает и отвязывает в соответствии с нормальным.
Я обнаружил, что:
-
При перемещении между действиями никакой обратный вызов службы не запускается. Поскольку жизненный цикл активности перекрывается, это вторичные bind/unbinds
-
Когда действие перезапускается (например, поворот экрана), служба получает
onUnbind()
, а затем вызовonRebind()
-
При приостановке приложения (например, нажмите "домой" из основного действия) или при завершении (например, нажмите "назад" из основного действия) служба получает
onUnbind()
, тогда срабатывает таймер.