Android: effacer la pile arrière

330

Dans Android, j'ai quelques activités, disons A, B, C.

Dans A, j'utilise ce code pour ouvrir B:

Intent intent = new Intent(this, B.class);
startActivity(intent);

En B, j'utilise ce code pour ouvrir C:

Intent intent = new Intent(this, C.class);
startActivity(intent);

Lorsque l'utilisateur appuie sur un bouton en C, je veux revenir à A et effacer la pile arrière (fermer à la fois B et C). Donc, lorsque l'utilisateur utilise le bouton de retour B et C ne s'affiche pas, j'ai essayé ce qui suit:

Intent intent = new Intent(this, A.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
startActivity(intent);

Mais B et C apparaissent toujours si j'utilise le bouton de retour lorsque je suis de retour dans l'activité A. Comment puis-je éviter cela?

Martin
la source

Réponses:

438

Essayez d'ajouter FLAG_ACTIVITY_NEW_TASKcomme décrit dans les documents pour FLAG_ACTIVITY_CLEAR_TOP:

Ce mode de lancement peut également être utilisé à bon escient en conjonction avec FLAG_ACTIVITY_NEW_TASK: s'il est utilisé pour démarrer l'activité racine d'une tâche, il mettra au premier plan toute instance en cours d'exécution de cette tâche, puis l'effacera à son état racine. Cela est particulièrement utile, par exemple, lors du lancement d'une activité à partir du gestionnaire de notifications.

Donc, votre code à lancer Aserait:

Intent intent = new Intent(this, A.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); 
startActivity(intent);
CurrentActivity.this.finish(); // if the activity running has it's own context


// view.getContext().finish() for fragments etc.
Jake Basile
la source
28
Merci mais j'ai essayé ça. Toujours quand j'appuie sur le bouton de retour après qu'il montre à nouveau C. Que puis-je manquer?
Martin
4
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);
dzeikei
8
ne fonctionne pas pour moi, mais appeler finish () sur l'activité source fait ce que je devais atteindre
2cupsOfTech
10
J'ai eu le même problème que cela ne fonctionnait pas. Ce qui m'a arrangé, c'est d'appeler finish () après avoir commencé la nouvelle activité
Arno
20
J'ai également ajouté une intention claire supplémentaire = nouvelle intention (SingUpActivity.this, LoginActivity.class); intent.setFlags (Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity (intention); terminer();
Sam
147
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
diesel
la source
8
Avec tout le respect pour le CLEAR_TOPdrapeau - cette combinaison est la SEULE qui a complètement effacé la pile entière et fait de la nouvelle activité la seule dans l'application. Je vous remercie!
Aviel Gross
8
Quelle est la différence entre cela et la réponse acceptée?
Yuri Heupa
7
Merci, la différence avec la réponse acceptée est qu'avec ce drapeau, nous n'avons pas besoin d'appeler activity.finish
Pablo Cegarra
1
FLAG_ACTIVITY_CLEAR_TASK a parfaitement fonctionné avec NEW_TASK
Shamsul Arefin Sajib
1
Ce devrait être la réponse acceptée. Merci beaucoup.
MD Danish Ansari
77

Qu'en est-il de l'ajout d'un fichier de manifestes pour une activité connexe:

android:noHistory="true"

à la définition d'activité de B et C? Ils ne seront pas ajoutés au backstack. Je ne sais pas si c'est ce que vous voulez.

Dominik Helleberg
la source
3
Soyez très prudent lorsque vous utilisez ceci - Si vous utilisez la connexion avec FB ou tout autre type de fonctionnalité similaire
Skynet
2
@Skynet Pourquoi? Quels sont les problèmes associés à cette opération?
Alfie Woodland
8
Lorsque vous passez le contrôle à FB pour la connexion à partir d'une page avec aucune histoire vraie, l'application FB ne sait plus où atterrir après avoir connecté l'utilisateur, dans mon cas, elle revenait à l'écran d'accueil du téléphone et j'ai presque perdu mon travail!
Skynet
Cela ne laisse pas une activité ajoutée au backstack .... ce n'est pas la bonne solution.
Tarun
Exactement ce que je recherche
Masum
63

Cela me dérange depuis longtemps. Enfin, je l'ai résolu en faisant ceci:

En fragment, utilisez:

Intent intent = new Intent(view.getContext(), A.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); 
startActivity(intent);

Dans Activity, utilisez (ajoutez un indicateur d'intention de plus Intent.FLAG_ACTIVITY_CLEAR_TASKpar rapport au fragment):

Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Geng Jiawen
la source
1
Si vous utilisez des annotations
android
La solutioin d'activité a bien fonctionné pour moi. Bien que je pense qu'avec l'API 16, la solution de Daniel Schuler est plus facile.
PhilippS
Merci yosafatade, c'est ce qui me manquait!
Marty Miller
30
  1. Ajouter android:launchMode="singleTop"à l'élément d'activité dans votre manifeste pour l'activité A
  2. Ensuite, utilisez intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) et intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)au début de l'activité A

Cela signifie que lorsque l'activité A est lancée, toutes les tâches au-dessus d'elle sont effacées afin que A soit en haut. Une nouvelle pile arrière est créée avec A à la racine, et l'utilisation singleTopgarantit que vous ne lancez jamais A une seule fois (puisque A est maintenant en haut à cause de ..._CLEAR_TOP).

Joseph Earl
la source
3
Oui. c'est ce que j'utilise maintenant, mais cela ne le fait pas. Toujours C apparaît lorsque je clique sur le bouton de retour.
Martin
Bizarrement, je l'ai utilisé dans un projet et cela fonctionne très bien ... appuyer en arrière me ramène à l'écran d'accueil. Peut-être que quelque chose d'autre se passe. Pourriez-vous poster votre manifeste?
Joseph Earl
J'ai redémarré l'émulateur et maintenant il semble fonctionner comme vous l'avez dit. Merci beaucoup pour votre aide!
Martin
singleTop ne devrait rien avoir à voir avec l'effacement de la pile.
stdout
29

À partir de l'API 16 (Jelly Bean), vous pouvez simplement appeler finishAffinity().

Maintenant, vous pouvez également appeler ActivityCompat.finishAffinity(Activity activity)avec la bibliothèque de compatibilité.

Veillez à définir taskAffinity dans le manifeste sur un nom de package unique pour ce groupe d'activités.

Voir pour plus d'informations:
http://developer.android.com/reference/android/support/v4/app/ActivityCompat.html#finishAffinity%28android.app.Activity%29

Daniel Schuler
la source
Vraiment une solution facile à utiliser si vous êtes déjà sur l'API 16. J'ai travaillé pour moi!
PhilippS
3
rappel: cela ne fonctionnera que pour les activités qui partagent la même tâche Nom de l'affinité
Ryan
cela ne fonctionne que si vous n'avez qu'une seule activité dans l'histoire.
arsent
17

Essayez d'utiliser

intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

et pas

intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
Muhammad Aamir Ali
la source
11

Si votre application a au minimum la version 16 de sdk, vous pouvez utiliser finishAffinity ()

Terminez cette activité ainsi que toutes les activités immédiatement en dessous dans la tâche en cours qui ont la même affinité.

Cela fonctionne pour moi Dans l'écran Top Payment, supprimez toutes les activités de back-stack,

 @Override
public void onBackPressed() {
         finishAffinity();
        startActivity(new Intent(PaymentDoneActivity.this,Home.class));
    } 

http://developer.android.com/reference/android/app/Activity.html#finishAffinity%28%29

Jaydeep purohit
la source
8

Pour de futures recherches, essayez ce code.

Intent intent = new Intent(context, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
GeetT
la source
Ces drapeaux ont finalement fonctionné pour moi. Ce que j'ai fait, c'est que j'ai commencé la même activité dans laquelle j'étais avec ces drapeaux et une sortie booléenne supplémentaire = true. Dans onCreate (), j'ai vérifié les paramètres de lancement pour EXIT et appelé finish () s'il était défini sur true. C'est beaucoup de tracas juste pour fermer votre propre application.
Janne Oksanen
8

Utilisez finishAffinity (); dans la tâche C lors du démarrage de la tâche A pour effacer les activités de backstack.

baswaraj
la source
seule cette réponse fonctionne pour moi. Intent.FLAG_ACTIVITY_CLEAR_TOP et Intent.FLAG_ACTIVITY_NEW_TASK ne sont pas requis
nuttynibbles
7

Utilisez ce code pour démarrer une nouvelle activité et fermez ou détruisez toute autre pile d'activité ou pile arrière.

Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
Pankaj Talaviya
la source
5
Use finishAffinity() to clear all backstack with existing one.

Suppose, Activities A, B and C are in stack, and finishAffinity(); is called in Activity C, 

    - Activity B will be finished / removing from stack.
    - Activity A will be finished / removing from stack.
    - Activity C will finished / removing from stack.
Firzan Shaikh
la source
5

J'ai trouvé une solution intéressante qui pourrait aider. Je l'ai fait dans ma onBackPressed()méthode.

finishAffinity();
finish();

FinishAffinitysupprime la connexion de l'activité existante à sa pile. Et puis terminer vous aide à quitter cette activité. Ce qui finira par quitter l'application.

Sujith Royal
la source
4

J'ai trouvé les réponses ici un peu trompeuses car le code de la question d'origine semble bien fonctionner pour moi?

Avec A étant l'activité racine, le démarrer à partir de B ou C uniquement avec FLAG_ACTIVITY_CLEAR_TOP supprime B et C de la pile arrière.

ianjoyner
la source
4

En kotlin, c'est presque la même chose que java. Uniquement | le symbole est remplacé par ou texte. Donc, c'est écrit comme-

intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
Exigente05
la source
3

J'ai essayé toutes les solutions et aucune ne fonctionnait individuellement pour moi. Ma solution est:

Déclarez Activity Acomme SingleTopen utilisant[android:launchMode="singleTop"] dans le manifeste Android.

Ajoutez maintenant les drapeaux suivants lors du lancement Ade n'importe où. Cela effacera la pile.

Intent in = new Intent(mContext, A.class);
in.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK );
startActivity(in);
finish();
Tarun
la source
2

Intent.FLAG_ACTIVITY_CLEAR_TOPne fonctionnera pas dans ce cas. Veuillez utiliser(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)

Pour plus de détails, consultez cette documentation.

Ashish Saini
la source
2

Il me semble que vous devez commencer à Activity Cpartir à Activity Bl'aide startActivityForResult(). Lorsque vous cliquez sur un bouton Activity C, appelez setResult(RESULT_OK)et finish()ainsi Activity Cse termine. Dans Activity B, vous pourriez avoir la onActivityResult()réponse en vous invoquant également finish(), et vous seriez alors ramené à Activity A.

Maximus
la source
7
Oui, mais s'il y a 42 activités entre A et C, ce sera plutôt fastidieux. Le drapeau FLAG_ACTIVITY_CLEAR_TOP est censé faire directement ce que veut l'OP.
Guillaume Brunerie
Ce serait un moyen moins qu'optimal de réaliser ce que l'OP veut, et comme l'a dit @Guillaume, cela nécessiterait du code dans toutes les activités entre la racine et le haut de la pile.
Jake Basile
Dûment noté. Ce sont des drapeaux dont je dois me renseigner apparemment.
Maximus
1

logout.addFlags (Intent.FLAG_ACTIVITY_CLEAR_TASK); logout.addFlags (Intent.FLAG_ACTIVITY_NEW_TASK);

Abhijeet
la source
1

Vous pouvez utiliser cet exemple pour appeler votre Activity AdeActivity C

Intent loout = new Intent(context, LoginActivity.class); loout.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); context.startActivity(loout);

Vipin Yadav
la source
1

pour moi l'ajout a Intent.FLAG_ACTIVITY_CLEAR_TASKrésolu le problème

Intent i = new Intent(SettingsActivity.this, StartPage.class);
                i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP  | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(i);
finish();
Mohamed Mo'nes
la source
1

Kotlin avancé et réutilisable:

Vous pouvez définir le drapeau directement en utilisant la méthode setter. Dans Kotlin orest le remplacement de Java au niveau du bit ou |.

intent.flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK

Si vous l'utilisez plusieurs fois, créez une fonction d'extension d'intention

fun Intent.clearStack() {
    flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}

Vous pouvez ensuite appeler directement cette fonction avant de démarrer l'intention

intent.clearStack()

Si vous avez besoin d'ajouter des indicateurs supplémentaires dans d'autres situations, ajoutez un paramètre facultatif à la fonction d'extension.

fun Intent.clearStack(additionalFlags: Int = 0) {
    flags = additionalFlags or Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
Gibolt
la source
0

De plus FLAG_ACTIVITY_CLEAR_TOP, vous pouvez également essayer d'ajouter Intent.FLAG_ACTIVITY_SINGLE_TOP:

intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

James
la source
Cela n'affecterait que l'activité en haut de la pile, pas sa racine.
Jake Basile
0

Le code donné fonctionne correctement. J'ai essayé dans l'exemple de cycle de vie d'application.

Je n'ai pas eu B et C dans la pile arrière après avoir commencé l'activité A avec l'indicateur FLAG_ACTIVITY_CLEAR_TOP

Sathesh
la source
0

J'ai appelé activity_name.this.finish()après avoir commencé une nouvelle intention et cela a fonctionné pour moi.

I tried "FLAG_ACTIVITY_CLEAR_TOP" and "FLAG_ACTIVITY_NEW_TASK"

Mais cela ne fonctionnera pas pour moi ... Je ne suggère pas cette solution, mais si la définition du drapeau ne fonctionne pas pour vous, vous pouvez essayer ceci .. Mais je recommande toujours de ne pas l'utiliser

Swap-IOS-Android
la source
0

Ajoutez AUCUN indicateur d'historique dans l'intention.

Dans l'activité B, démarrez l'activité C comme ci-dessous >>>>>>

Intent intent = new Intent(this, C.class);
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NO_HISTORY); 
startActivity(intent);
finish();
Arun Sharma
la source
0

En manifeste

android:launchMode="singleTask"

et

intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
blackjack
la source
0

Soit ajoutez ceci à votre Activity BetActivity C

android:noHistory="true"

ou Override onBackPressedfonction pour éviter d'appuyer à nouveau avec a return.

@Override
public void onBackPressed() {
   return;
}
Renjith JR
la source
0

Utilisez la méthode setFlags () pour effacer l'arrière ouvert toutes les activités fermer et démarrer votre activité

Intent intent = new Intent(getApplicationContext(), yourActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
Pankaj Talaviya
la source