2015-04-28 7 views
6

Vorrei effettuare il check-in e il checkout di un utente con il server ogni volta che l'app viene aperta/chiusa, indipendentemente dal fatto che venga avviata o ripresa dal cassetto attività. C'è un modo per farlo evitando di dover chiamare una funzione in ogni attività?Rileva quando l'app viene aperta/ripresa

Grazie!

+1

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

+0

@ 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. –

+0

@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

risposta

7

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); 
} 
+0

È preferibile eseguire questa operazione in onActivityResumed e onActivityPaused, poiché è possibile interrompere le attività quando altre attività sono in primo piano. Ottimo lavoro altrimenti! –

+0

@aakashjain buona chiamata. Anche se posso vedere anche situazioni in cui onActivityStarted/onActivityStopped potrebbe rivelarsi appropriato. Ho aggiornato la risposta per riflettere il tuo feedback. Breve ricerca su google non ha prodotto una risposta che volevo, quindi potrebbe essere necessario un rapido esperimento. Credo che le chatheads e altre app che ostruiscono parzialmente la vista (anche se quasi tutte) causino la chiamata di onActivityPausa all'applicazione sottostante (la tua). Poiché l'utente spesso intende continuare l'app che è parzialmente visibile, potresti voler mantenere quella sessione andando con la combo start/stop. –

+0

Hai un esempio di ciò di cui stai parlando o l'ho fornito? –

0

È possibile utilizzare i metodi oncreate() e onpause().

+0

Questo è parzialmente corretto ! – ngoa

+0

@ngoa Ci diresti, perché è parzialmente corretto? –

+0

@ RenéHoffmann Come ho menzionato nei commenti sotto la domanda, non vuole effettuare il check-in e il checkout quando si chiude un'attività, ma piuttosto quando l'applicazione viene avviata o ripresa. Quindi questo può diventare problematico quando si chiude o si sposta tra le attività quando si ha un'app aperta, che comunque chiama le funzioni 'oncreate()' e 'onpause()'. – ngoa

6
+0

L'API di targeting 14+ (Android 4.xo successive) è accettabile, è un'idea molto interessante –

+0

Non ancora implementata, ma dopo aver visitato la documentazione e consultato il collegamento fornito da @ngoa (http: // stackoverflow .com/questions/4414171/how-to-detect-when-an-android-app-goes-to-the-background-and-come-back-to-the-fo) Credo che funzionerà bene. Grazie per l'intuizione! –

+1

@ TomMcFarlin Grazie. Lo posterò come risposta. – ngoa

1

Ok. Sto postando i miei commenti come risposta dal momento che l'utente originale che ha posto la domanda lo ha trovato molto utile.

Il problema con le risposte di cui sopra è che, L'applicazione non vuole effettuare il check-in & checkout quando un'attività si chiude, ma piuttosto quando l'applicazione viene avviata o ripresa. Quindi questo può diventare problematico quando si sta chiudendo o spostandosi tra le attività quando si dispone di un'app aperta, che continuerà a chiamare le funzioni oncreate() e onpause().

Questo problema è stato discusso anche su StackOverflow in precedenza. Di seguito è riportato il link.

How to detect when an Android app goes to the background and come back to the foreground

Ci potrebbero essere diversi modi di circa risolvere questo problema. Il link sopra fornisce maggiori informazioni su come risolverlo.

+0

Grazie per la risposta, lo implementerò entro la prossima settimana. Rivisiterò la domanda per chiarire la mia domanda e aggiungere alla discussione. –

Problemi correlati