Rimozione di un'attività dallo stack della cronologia


382

La mia app mostra un'attività di registrazione la prima volta che l'utente esegue l'app, assomiglia a:

  1. ActivitySplashScreen (benvenuto nel gioco, registrarsi per un account?)
  2. ActivitySplashScreenSignUp (ottimo, inserisci queste informazioni)
  3. ActivityGameMain (schermata di gioco principale)

quindi le attività si avviano esattamente in quell'ordine, quando l'utente fa clic su un pulsante su ciascuna schermata.

Quando l'utente passa dall'attività n. 2 alla n. 3, è possibile cancellare completamente lo stack della cronologia n. 1 e n. 2? Mi piacerebbe che se l'utente si trova al n. 3, e preme il pulsante Indietro, vada semplicemente nella schermata iniziale, invece di tornare alla schermata iniziale.

Penso di poterlo fare con delle attività (ad es. Iniziare una nuova attività al n. 3) ma volevo vedere se esisteva un metodo più semplice,

Grazie


Dopo essere stato nella schermata principale, quando l'utente riprende la tua app, lo porta su ActivitySplashScreen o ActivityGameMain?
Tamil,

Risposte:


632

È possibile ottenere ciò impostando l' android:noHistory attributo su "true"nelle <activity>voci pertinenti nel AndroidManifest.xmlfile. Per esempio:

<activity
    android:name=".AnyActivity"
    android:noHistory="true" />

12
Questo è il modo migliore per farlo.
shkschneider,

22
Equivalentemente puoi usare FLAG_ACTIVITY_NO_HISTORY.
Timmmm,

34
Come posso ottenere questo dal codice? Perché non voglio farlo tutto il tempo. Vorrei rimuovere una determinata attività dalla storia solo in determinate condizioni.
Namratha,

8
Basta essere consapevoli del fatto che l'uso dell'attributo noHistory farà terminare l'attività, ad esempio potrebbe causare comportamenti imprevisti con l'accesso G +. Vedi: stackoverflow.com/questions/20383878/… Mi ci è voluto un po 'per trovare questo bug poiché la mia app continuava a bloccarsi senza alcuna traccia.
Acapulco,

13
È difficile copiare il flag necessario in quanto è un collegamento, quindi qui uno che può essere facilmente copiato. android:noHistory="true"
MirroredFate

137

È possibile utilizzare l'inoltro per rimuovere l'attività precedente dallo stack di attività durante l'avvio di quella successiva. C'è un esempio di questo in APIDemos , ma fondamentalmente tutto ciò che stai facendo è chiamare finish()subito dopo aver chiamato startActivity().


1
Ciao Daniel, ho letto l'esempio, ma questo cancellerà lo stack della cronologia solo per 1 attività, no? Se il mio stack sembra A, B e sto lanciando C, voglio che C sia la nuova radice e cancelli completamente A e B. Nell'esempio di sdk, chiamare finish () da B mi lascerebbe con uno stack di A , C, no? Grazie.
Segna il

1
È possibile cancellare A all'avvio di B e cancellare B all'avvio di C; tuttavia, suppongo che non saresti in grado di uscire da B ad A se è quello che desideri. Dovrò pensarci di più se questo è un problema.
Dan Lew,

3
Segna, per ottenere quello che vuoi, devi usare il flag: FLAG_ACTIVITY_CLEAR_TOP. Spero possa essere d'aiuto.
Francisco Junior,

3
FLAG_ACTIVITY_CLEAR_TOPnon funzionerà perché C non è già nello stack posteriore.
Timmmm,

1
@DanielLew Ci sono così tanti esempi in APIDemos. Avresti suggerito il nome dell'esempio?
Stephane,

52

Sì, dai un'occhiata a Intent.FLAG_ACTIVITY_NO_HISTORY .


46
Nota che questo non imposta alcuna cronologia per l'attività a cui stai avviando. Per non avere cronologia dell'attività da cui stai avviando, l'ho appena impostata android:noHistory="true"nel manifest.
georgiecasey,

1
Questo funziona bene. Utilizzare il intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)per impostare questo flag.
vovahost il

1
@georgiecasey questo è utile quando a volte vuoi tenerlo nella storia ea volte non lo vuoi nella storia.
Vihaan Verma,

24

Questo probabilmente non è il modo ideale per farlo. Se qualcuno ha un modo migliore, non vedo l'ora di implementarlo. Ecco come ho completato questo compito specifico con pre-versione-11 sdk.

in ogni classe che vuoi andare via quando è il momento giusto, devi farlo:

    ... interesting code stuff ...
    Intent i = new Intent(MyActivityThatNeedsToGo.this, NextActivity.class);
    startActivityForResult(i, 0);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == R.string.unwind_stack_result_id) {
        this.setResult(R.string.unwind_stack_result_id);
        this.finish();
    }
}

quindi quello che deve scatenare la catena di pop dallo stack deve semplicemente chiamarlo quando vuoi avviarlo:

NextActivity.this.setResult(R.string.unwind_stack_result_id);
NextActivity.this.finish();

Quindi le attività non sono in pila!
Ricorda gente, che puoi iniziare un'attività e poi iniziare a ripulire dietro di essa, l'esecuzione non segue un singolo thread (l'interfaccia utente).


Nel caso in cui qualcuno si imbattesse in questo in seguito, ho pensato che potrebbe rivelarsi importante sapere, se hai ruotato lo schermo, Android riavvierà utile l'applicazione per te quando toglierai l'ultima attività dallo stack. Basta essere consapevoli di questo!
Travis,

Questa è una buona risposta se desideri rimuovere un'attività dallo stack solo in base a ciò che l'utente fa nella prossima attività +1
theMothaShip

23

Un modo che funziona prima dell'API 11 è quello di iniziare ActivityGameMainprima, quindi in onCreatequella attività avviare l' ActivitySplashScreenattività. Il ActivityGameMainnon apparirà come si chiama startActivity troppo presto per Splash.

Quindi puoi cancellare lo stack quando inizi ActivityGameMainimpostando questi flag sull'Intento:

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);

È inoltre necessario aggiungere questo a ActivitySplashScreen:

@Override
public void onBackPressed() {
    moveTaskToBack(true);
}

In modo che la restituzione di quell'attività non torni alla tua ActivityGameMain.

Presumo che tu non voglia che la schermata iniziale venga ripristinata su entrambi, per raggiungere questo obiettivo ti suggerisco di impostarla noHistorynel tuo AndroidManifest.xml. Quindi inserisci il goBackPressedcodice nella tua ActivitySplashScreenSignUpclasse.

Tuttavia ho trovato alcuni modi per romperlo. Avvia un'altra app da una notifica mentre ActivitySplashScreenSignUpè visualizzata e la cronologia non viene ripristinata.

L'unico vero modo per aggirare questo è in API 11:

intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);

20

Uso così.

Intent i = new Intent(MyOldActivity.this, MyNewActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)
startActivity(i);

Grazie. L'ho trovato utile nel caso in cui fosse presente un pulsante Home nel mio menu e non volevo che le attività in pila comparissero dopo che l'utente ha fatto clic su Home da lì.
ghitesh,

8

So di essere in ritardo (sono passati due anni da quando è stata posta la domanda) ma l'ho realizzato intercettando il pulsante Indietro. Invece di verificare attività specifiche, guardo solo il conteggio e se è inferiore a 3, invia semplicemente l'app sul retro (mettendo in pausa l'app e riportando l'utente a tutto ciò che era in esecuzione prima del lancio). Controllo meno di tre perché ho solo una schermata introduttiva. Inoltre, controllo il conteggio perché la mia app consente all'utente di tornare alla schermata principale attraverso il menu, quindi ciò consente loro di eseguire il backup attraverso altre schermate come normali se ci sono attività diverse dalla schermata introduttiva nello stack.

//We want the home screen to behave like the bottom of the activity stack so we do not return to the initial screen
//unless the application has been killed. Users can toggle the session mode with a menu item at all other times.
@Override
public void onBackPressed() {
    //Check the activity stack and see if it's more than two deep (initial screen and home screen)
    //If it's more than two deep, then let the app proccess the press
    ActivityManager am = (ActivityManager)this.getSystemService(Activity.ACTIVITY_SERVICE);
    List<RunningTaskInfo> tasks = am.getRunningTasks(3); //3 because we have to give it something. This is an arbitrary number
    int activityCount = tasks.get(0).numActivities;

    if (activityCount < 3)
    {
        moveTaskToBack(true);
    }
    else
    {
        super.onBackPressed();
    }
}

7

Nel manifest è possibile aggiungere:

android:noHistory="true"

<activity
android:name=".ActivityName"
android:noHistory="true" />

Puoi anche chiamare

finish()

subito dopo aver chiamato startActivity (..)


2
Meglio usare i flag di attività piuttosto che mettere le cose nel manifest.
Trevor Hart,


4

È assurdo che nessuno abbia menzionato questa soluzione elegante. Questa dovrebbe essere la risposta accettata.

SplashActivity -> AuthActivity -> DashActivity

if (!sessionManager.isLoggedIn()) {
    Intent intent = new Intent(context, AuthActivity.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
    context.startActivity(intent);
    finish();
} else {
   Intent intent = new Intent(context, DashActivity.class);
   context.startActivity(intent);
    finish();
}

La chiave qui è da usare intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); per l'intermediario Activity. Una volta interrotto quel collegamento centrale, la DashActivityvolontà sarà la prima e l'ultima nella pila.

android:noHistory="true" è una cattiva soluzione, in quanto causa problemi quando si fa affidamento su Activity come callback es onActivityResult. Questa è la soluzione raccomandata e dovrebbe essere accettata.


1
Quella bandiera suonava troppo bella per essere vera. FLAG_ACTIVITY_NO_HISTORY funziona bene e come ci si aspetterebbe fino a quando non si mette l'app in background e poi di nuovo in primo piano con l'attività con il flag in cima allo stack. Quando si va in background, l'attività viene distrutta. Quando ritorni all'app, vedrai l'attività precedente dallo stack. Non volevo assolutamente un simile comportamento.
NeverwinterMoon,

4

È troppo tardi, ma spero che sia d'aiuto. La maggior parte delle risposte non punta nella giusta direzione. Ci sono due semplici bandiere per tale cosa.

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

Dai documenti Android:

public stat final int FLAG_ACTIVITY_CLEAR_TASK Aggiunto nel livello API 11

If set in an Intent passed to Context.startActivity(), this flag will cause any existing task that would be associated with the

attività da cancellare prima dell'avvio dell'attività. Cioè, l'attività diventa la nuova radice di un'attività altrimenti vuota e tutte le vecchie attività sono terminate. Questo può essere utilizzato solo insieme a FLAG_ACTIVITY_NEW_TASK.


1

Basta chiamare this.finish () prima di startActivity (intento) come questo-

       Intent intent = new Intent(ActivityOne.this, ActivityTwo.class);
        this.finish();
        startActivity(intent);

gli utenti che hanno errori su "this", dovrebbero cambiarlo in "ActivityOne.this"
ninbit

1

La rimozione di un'attività da una cronologia viene eseguita Impostando il flag prima dell'attività Non si desidera

A-> B-> C-> D

Supponiamo che A, B, C e D siano 4 attività se si desidera cancellare B e C, quindi impostare il flag

intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);

Nell'attività A e B

Ecco il bit del codice

Intent intent = new Intent(this,Activity_B.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(intent);

0
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            super.finishAndRemoveTask();
        }
        else {
            super.finish();
        }

-7

Prova questo:

intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY)

è livello API 1, controlla il link .


2
Cosa dovrebbe fare questo? Sicuramente non risolve il problema in questione.
rodrigo-silveira,

Sei sicuro di non voler dire Intent.FLAG_ACTIVITY_NO_HISTORY?
Riot Goof Woof,
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.