Come verificare se un'attività è l'ultima nello stack di attività per un'applicazione?


Risposte:


116

AGGIORNAMENTO (luglio 2015):

Dal momento che getRunningTasks () ottenere deprecato, da API 21 è meglio seguire raukodraug risposta o Ed Burnette uno (io preferirei secondo).


C'è la possibilità di controllare le attività correnti e il loro stack utilizzando ActivityManager .

Quindi, per determinare se un'attività è l'ultima:

  • richiedi le autorizzazioni android.permission.GET_TASKS nel manifest.
  • Usa il codice seguente:

    ActivityManager mngr = (ActivityManager) getSystemService( ACTIVITY_SERVICE );
    
    List<ActivityManager.RunningTaskInfo> taskList = mngr.getRunningTasks(10);
    
    if(taskList.get(0).numActivities == 1 &&
       taskList.get(0).topActivity.getClassName().equals(this.getClass().getName())) {
        Log.i(TAG, "This is last activity in the stack");
    }
    

Tieni presente che il codice sopra sarà valido solo se hai una singola attività. Se esiste la possibilità che esista un numero di attività per la tua applicazione, dovrai controllare altri elementi taskList . Ulteriori informazioni sulle attività Tasks e Back Stack



25
H9kDroid ha dato un suggerimento corretto. La risposta selezionata è un trucco. Uno dovrebbe farlo nel modo giusto usando il isTaskRoot()metodo.
Sufian

@Sufian dov'è l'hack in particolare? Il codice è logico e utilizza API Android aperte nel modo in cui intendono essere utilizzate (ad es. GetRunningTasks dovrebbe essere utilizzato per eseguire attività in esecuzione e si potrebbe desiderare di chiamarlo solo allo scopo di analizzare queste attività). L'utilizzo di get (0) è ben documentato e logico "Restituisce un elenco delle attività attualmente in esecuzione, con le più recenti prima e quelle più vecchie dopo in ordine".
sandrstar

2
getRunningTasks () è deprecato nel livello API 21.
gilchris

Posso fare la stessa cosa per i frammenti. Se sì, allora come? Si prega di aiutare
Sagar Devanga

1
@ Mr.Drew vede la risposta più votata da @ raukodraug
David Wasser

167

Pubblicherò il commento di @ H9kDroid come la migliore risposta qui per le persone che hanno una domanda simile.

È possibile utilizzare isTaskRoot () per sapere se l'attività è la radice di un'attività.

Spero che aiuti


1
puoi fornire la singola riga di codice in modo che sia chiaro come usare isTaskRoot. Grazie.
Kaveesh Kanwal

18
@TheHunterif (isTaskRoot()) { // do something }
howettl

3
L'unico problema è che su <= 4.4 vedo che ha un comportamento diverso rispetto a> = 5.x. Sembra restituire sempre false.
chubbsondubs

Penso che dovresti considerare di incorporare il codice di esempio fornito nei commenti nella risposta, per renderlo più facile per i futuri lettori.
Isac

ottima risposta. nel mio caso dopo che l'utente fa clic su una notifica, l'attività potrebbe essere la radice se ha chiuso l'applicazione prima
dave o grady

19

Spero che questo aiuterà i nuovi principianti, Sulla base delle risposte sopra che funzionano bene per me, sto anche condividendo lo snippet di codice in modo che sia facile da implementare.

soluzione: ho usato isTaskRoot()che restituisce vero se l'attività corrente è solo attività nel tuo stack e oltre a gestire anche il caso in cui se ho qualche attività in pila vai all'ultima attività in pila invece di aprirne una nuova personalizzata.

Nella tua attività

   @Override
    public void onBackPressed() {

        if(isTaskRoot()){
            startActivity(new Intent(currentActivityName.this,ActivityNameYouWantToOpen.class));
            // using finish() is optional, use it if you do not want to keep currentActivity in stack
            finish();
        }else{
            super.onBackPressed();
        }

    }


5

Anche se potrebbe esserci un modo per raggiungere questo obiettivo (vedi altre risposte), suggerirei di non farlo. Le normali applicazioni Android non dovrebbero aver bisogno di sapere se la schermata Home sta per essere visualizzata o meno.

Se stai cercando di salvare i dati, inserisci il codice di salvataggio dei dati nel tuo metodo onPause (). Se stai cercando di dare all'utente un modo per cambiare idea sull'esistenza dell'applicazione, potresti intercettare il tasto su / giù per il tasto Indietro e il metodo onBackPressed () e presentargli un "Sei sicuro?" richiesta.


1
Che ne dici se ho bisogno di un servizio in esecuzione finché l'utente non ha abbandonato l'attività? Non posso intercettare nessuna delle funzioni come onStop perché queste potrebbero essere chiamate dopo che lo schermo è spento.
Michael,

2
Se un servizio in background avvia un'attività, forse ti piacerebbe sapere se è l'unica attività in pila o meno.
Matt W

4

Un modo per tenerne traccia è includere un marker quando inizi una nuova attività e controllare se il marker esiste.

Ogni volta che inizi una nuova attività, inserisci il marker:

newIntent=new Intent(this, NextOne.class);
newIntent.putExtra(this.getPackageName()+"myself", 0);
startActivity(newIntent);

E puoi quindi verificarlo in questo modo:

boolean islast=!getIntent().hasExtra(this.getPackageName()+"myself")

1
Non funziona se l'attività viene interrotta e lo stack di attività viene ricostruito, ogni attività su richiesta.
AlikElzin-kilaka

3

Il problema con la soluzione di sandrstar usando ActivityManagerè: hai bisogno di un'autorizzazione per ottenere le attività in questo modo. Ho trovato un modo migliore:

getIntent().hasCategory(Intent.CATEGORY_LAUNCHER)

La Activityparte inferiore dello Stack dovrebbe sempre ottenere questa categoria per impostazione predefinita, mentre le altre attività non dovrebbero ottenerla.
Ma anche se questo non riesce su alcuni dispositivi, puoi impostarlo all'avvio di Activity:

Intent intent = new Intent(startingActivity, SomeActivityClass.class);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
activity.startActivity(intent);

Cosa succede se l'attività viene aperta dalla notifica push? Non hanno la CATEGORY
LAUNCHER

Sono abbastanza sicuro che la seconda parte della mia risposta sia ancora valida. Puoi impostare la categoria come suggerimento nell'intento. In questo caso, forse nell'intento del tuo contesto di notifica. Oltre a questo potresti anche usare flag per questo. vedi questo link per una creazione di notifica con l'intento: stackoverflow.com/questions/13716723/...
A. Binzxxxxxx

Tuttavia, se la tua attività più vecchia è MainActivity e ora viene ripresa, quindi ricevi una notifica push e imposti l'apertura di pendingIntent con CATEGORY_LAUNCHER, avrai 2 attività con questa categoria. Probabilmente su compiti diversi però
nbtk

Non sono esattamente sicuro di come funzioni con le notifiche. Non li ho mai usati come fai tu qui. Sono abbastanza sicuro che ci sia un modo semplice per farlo con questo approccio, ma non ho toccato il codice Android dal primo trimestre del 2014. Forse vuoi usare una seconda categoria per questo caso? O qualche bandiera? Ma immagino che debba funzionare in questo modo. Che ne dici di avviare l'attività principale e aggiungere una sorta di meta informazioni per aprire l'attività corretta, quindi?
A. Binzxxxxxx

2

Ho creato una classe base per tutte le mie attività, estendendo l' AppCompatActivity e che ha un contatore statico:

public abstract class BasicActivity extends AppCompatActivity {
    private static int activityCounter = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ++activityCounter;
        ...
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        --activityCounter;
        if(activityCounter==0) {
            // Last instance code...
        }
    }

    public boolean isLastInstance() { return (activityCounter==1); }
}

Finora ha funzionato abbastanza bene; e indipendentemente dalla versione dell'API. Ovviamente richiede che tutte le attività estendano questa classe base, cosa che fanno, nel mio caso.

Modifica: ho notato un'istanza in cui il contatore scende a zero prima che l'app esca completamente, ovvero quando l'orientamento viene modificato e solo un'attività è aperta. Quando l'orientamento cambia, l'attività viene chiusa e ne viene creata un'altra, quindi onDestroyedviene chiamata per l'ultima attività, quindi onCreateviene richiamata quando la stessa attività viene creata con l'orientamento modificato. Questo comportamento deve essere tenuto in considerazione; È possibile utilizzare OrientationEventListener .


0

Android implementa uno stack di attività, ti consiglio di leggerlo qui . Sembra che tutto quello che vogliamo fare è però recuperare l'attività di chiamata: getCallingActivity(). Se l'attività corrente è la prima attività nell'applicazione e l'applicazione è stata avviata dalla schermata principale, dovrebbe (presumo) tornare null.


9
Ciò non funzionerà poiché getCallingActivity () restituirà null se l'attività non è stata avviata tramite startActivityForResult ().
H9kDroid

0

L'unica cosa che mancava qui è il clic sul "tasto Home", quando attivato, non puoi rilevarlo dalla tua attività, quindi sarebbe meglio controllare lo stack delle attività a livello di programmazione con la gestione della pressione del "tasto Indietro" e passare all'attività richiesta o solo facendo i passaggi necessari.

Inoltre, non puoi essere sicuro che l'avvio della tua attività dall'elenco "Attività recenti" possa essere rilevato preimpostando alcuni dati aggiuntivi nell'intento di apertura dell'attività, poiché in tal caso vengono riutilizzati.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.