La risposta fornita da d60402 here e il suggerimento di Hanno Binder di registrare i callback delle attività utilizzando Application.registerActivityLifecycleCallbacks() mi hanno portato a questa soluzione.
Ho esteso l'applicazione e le richiamate registrate ai metodi di attività onPause e onStart come mostrato di seguito. In questi metodi viene avviato/fermato un timer (si esce da un'attività in cui viene chiamato onPause, ne viene inserito uno nuovo in cui viene chiamato onStart). Il flag "wasInBackground" è attivato quando l'app ha determinato di essere in background/in primo piano (true/false). Se l'app era in background quando viene eseguito il callback onStart, viene chiamato "appEntered". Se il tempo passato tra onPause e onStart callbacks è maggiore di un tempo specificato (dando tempo sufficiente per le transizioni di attività) viene chiamato "appExited" dove si considera che la sessione dell'app sia terminata.
public class MyApplication extends Application {
public static final String LOG_TAG = "MyApp";
public boolean wasInBackground = true;
private AppSession appSession;
private Timer mActivityTransitionTimer;
private TimerTask mActivityTransitionTimerTask;
private final long MAX_ACTIVITY_TRANSITION_TIME_MS = 2000; // Time allowed for transitions
Application.ActivityLifecycleCallbacks activityCallbacks = new Application.ActivityLifecycleCallbacks() {
@Override
public void onActivityResumed(Activity activity) {
if (wasInBackground) {
//Do app-wide came-here-from-background code
appEntered();
}
stopActivityTransitionTimer();
}
@Override
public void onActivityPaused(Activity activity) {
startActivityTransitionTimer();
}
...
};
@Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(activityCallbacks);
}
public void startActivityTransitionTimer() {
this.mActivityTransitionTimer = new Timer();
this.mActivityTransitionTimerTask = new TimerTask() {
public void run() {
// Task is run when app is exited
wasInBackground = true;
appExited();
}
};
this.mActivityTransitionTimer.schedule(mActivityTransitionTimerTask,
MAX_ACTIVITY_TRANSITION_TIME_MS);
}
public void stopActivityTransitionTimer() {
if (this.mActivityTransitionTimerTask != null) {
this.mActivityTransitionTimerTask.cancel();
}
if (this.mActivityTransitionTimer != null) {
this.mActivityTransitionTimer.cancel();
}
this.wasInBackground = false;
}
private void appEntered() {
Log.i(LOG_TAG, "APP ENTERED");
appSession = new AppSession();
}
private void appExited() {
Log.i(LOG_TAG, "APP EXITED");
appSession.finishAppSession();
// Submit AppSession to server
submitAppSession(appSession);
long sessionLength = (appSession.getT_close() - appSession.getT_open())/1000L;
Log.i(LOG_TAG, "Session Length: " + sessionLength);
}
fonte
2015-05-16 19:16:56
Creare una singola attività che imposta un tag per voi ed estendere tale classe invece di estendere Attività alle attività correnti. In questo modo dovresti scrivere il codice una sola volta. – zgc7009
@ zgc7009 presenta un'idea che spesso funziona bene. Il problema è che se alcune delle tue attività hanno bisogno di estendere alcune varianti di attività già specializzate provenienti da un'altra libreria, allora devi anche creare una versione speciale di questa. –
@ChrisStratton Inoltre non vuole effettuare il checkin e il checkout quando si chiude un'attività, ma piuttosto quando l'applicazione viene avviata o ripresa. Quindi questo può diventare problematico quando stai chiudendo o spostando tra le attività quando hai un'app aperta. – ngoa