Android: supprimez toutes les activités précédentes de la pile arrière

119

Lorsque je clique sur le bouton Déconnexion dans mon activité de profil, je veux amener l'utilisateur à la page de connexion , où il doit utiliser de nouvelles informations d'identification.

Par conséquent, j'ai utilisé ce code:

Intent intent = new Intent(ProfileActivity.this,
        LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

dans le onButtonClickbouton Déconnexion.

Mais le problème est que lorsque je clique sur le bouton de retour de l'appareil sur l'activité de connexion, cela me conduit à ProfileActivity. Je m'attendais à ce que l'application se ferme lorsque j'appuie sur le bouton de retour de l'appareil sur LoginActivity.

Qu'est-ce que je fais mal?

J'ai également ajouté android:launchMode="singleTop"dans le manifeste pour mon LoginActivity

Merci

Archie.bpgc
la source
@GauravVashisth Je suivais juste cette solution stackoverflow.com/questions/5794506/…
Archie.bpgc
@ abbas.aniefa Cette solution est un peu compliquée. Est-ce la seule façon de vider toute la pile arrière. Parce que j'ai plus de 30 activités, je devrais donc écrire ce code de diffusion pour toutes
Archie.bpgc
essayez ceci alors, stackoverflow.com/questions/10961481/… . L'utilisation de la diffusion est une meilleure solution.
abbas.aniefa
une autre approche que vous pouvez utiliser pour la déconnexion, une fois que vous vous déconnectez, stockez un indicateur dans sharedpreferences et dans chaque méthode onRestart () d'une activité, vous pouvez vérifier cette valeur de variable si elle est définie sur true, vous pouvez terminer l'activité en cours. donc peu importe le nombre d'activités ouvertes en arrière-plan. cela terminerait toute votre activité.
Hiren Dabhi
Votre code d'origine fonctionne en fait pour le niveau d'API 11 ou supérieur avec un ajustement. Il vous suffit de rassembler les drapeaux en un seul appel: intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);j'ai eu la réponse à cette question: stackoverflow.com/questions/3473168
...

Réponses:

304

La solution proposée ici a fonctionné pour moi:

Java

Intent i = new Intent(OldActivity.this, NewActivity.class);
// set the new task and clear flags
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);

Kotlin

val i = Intent(this, NewActivity::class.java)
// set the new task and clear flags
i.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
startActivity(i)

Cependant, il nécessite un niveau d'API> = 11.

kgiannakakis
la source
Les gars, lisez la documentation de FLAG_ACTIVITY_CLEAR_TASK.C'est le moyen officiel d'obtenir. Pas besoin de modifier toutes les activités de l'application.
AlikElzin-kilaka
Cela ne fonctionne pas pour les notifications stackoverflow.com/questions/24873131/...
Sam
J'ai mon minAPI = 16, donc cela fonctionne parfaitement bien pour moi. Cependant, j'ai remarqué que l'exécution de la vue est un peu lente avec API> 21 et fluide avec les API <21. Quelqu'un rencontre-t-il le même problème?
Red M
1
Cela créera une nouvelle tâche pour les activités
Rohit
@kgiannakakis Il ne fait aucun doute que la solution fonctionne si nous n'avons qu'une seule tâche (pile de retour d'activité), mais lorsque nous avons plusieurs tâches (pile d'activité), cela ne fonctionne pas. ex- disons que j'ai quatre activités pour mon application A, B, C et D. Supposons que j'ai deux piles de dos d'activité A-> B-> C (arrière-plan) et D-> A-> B (premier plan) et si je appeler l'activité A de ma pile actuelle (D-> A-> B) avec un filtre d'intention ce que vous avez suggéré ce qui va se passer efface ma pile actuelle (D-> A-> B) et ouvre l'activité A et quand j'appuie dessus, fermez-la application, mais si j'appuie sur le bouton de l'application récente, je peux voir deux piles arrière de mon application.
Rahul Pareta
31

Voici une solution pour effacer toutes les activités de votre application lorsque vous utilisez le bouton de déconnexion.

Chaque fois que vous démarrez une activité, démarrez-la comme ceci:

Intent myIntent = new Intent(getBaseContext(), YourNewActivity.class);
startActivityForResult(myIntent, 0);

Lorsque vous souhaitez fermer l'ensemble de l'application, procédez comme suit:

setResult(RESULT_CLOSE_ALL);
finish();

RESULT_CLOSE_ALL est une variable globale finale avec un entier unique pour signaler que vous souhaitez fermer toutes les activités.

Définissez ensuite le onActivityResult(...)rappel de chaque activité afin que lorsqu'une activité retourne avec la valeur RESULT_CLOSE_ALL, elle appelle également finish():

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch(resultCode)
    {
    case RESULT_CLOSE_ALL:
        setResult(RESULT_CLOSE_ALL);
        finish();
    }
    super.onActivityResult(requestCode, resultCode, data);
}

Cela provoquera un effet de cascade qui fermera toutes vos activités.

Ceci est un hack cependant et utilise startActivityForResultd'une manière qu'il n'a pas été conçu pour être utilisé.

Peut-être qu'une meilleure façon de le faire serait d'utiliser des récepteurs de diffusion comme indiqué ici:

Lors de la déconnexion, effacez la pile de l'historique des activités, empêchant le bouton "Retour" d'ouvrir les activités uniquement connectées

Consultez également ces discussions pour d'autres méthodes:

Android: effacez la pile arrière

Terminez toutes les activités précédentes

Anup Cowkur
la source
4
Est-ce faisable lorsque vous avez une trentaine d'activités sur l'histoire?
Rakesh Gondaliya
4
devrait être. Mais si vous avez 30 activités dans l'histoire, vous voudrez peut-être envisager de modifier votre conception. 30 semble un peu trop et Android pourrait les tuer de lui-même.
Anup Cowkur
1
Cela semble être une mauvaise façon de procéder. La question de réponse de @RakeshGondaliya semble légitime. 30 peut-être juste un nombre représentant un nombre «élevé» d'activités. Cette réponse semble meilleure: stackoverflow.com/a/3008684/243709
Aman Alam
Cette réponse est excellente. Vous pouvez également utiliser la bibliothèque EventBus pour envoyer des événements à vos activités en backstack. github.com/greenrobot/EventBus
Stan
Mieux vaut utiliser un simple indicateur 'Intent.FLAG_ACTIVITY_CLEAR_TOP' avec intention
Naveen Rao
18

Pour effacer complètement la pile d'activités, vous souhaitez créer une nouvelle pile de tâches à l'aide de TaskStackBuilder, par exemple:

Intent loginIntent = LoginActivity.getIntent(context);
TaskStackBuilder.create(context).addNextIntentWithParentStack(loginIntent).startActivities();

Cela ne créera pas seulement une nouvelle pile de tâches propre, cela permettra également le bon fonctionnement du bouton «haut» si votre LoginActivity a une activité parent.

Matt Accola
la source
1
C'est la meilleure façon de le faire.
Paul Burke
FLAG_ACTIVITY_NEW_TASKou finishAffinity()n'a pas fonctionné pour moi. Seule cette réponse a résolu le but.
TM
Si je quitte l'application via le bouton de retour et retourne via l'icône de l'application, elle s'ouvre dans l'activité que j'ai appelée cette méthode. Donc pas de travail pour moi.
Tgo1014
17

finishAffinity()ajouté dans l'API 16. Utilisation ActivityCompat.finishAffinity()dans les versions précédentes. Quand vous lancerez une activité en utilisant l'intention et terminerez l'activité en cours. Maintenant, utilisez à la ActivityCompat.finishAffinity()place finish(). il terminera toutes les activités empilées en dessous de l'activité actuelle. Ça fonctionne bien pour moi.

Anurag Srivastava
la source
3
C'est en faitActivityCompat.finishAffinity()
The Berga
finishAffinity()termine également l'activité en cours avec toutes les activités présentes dans la pile arrière de la même affinité.
Neeraj Sewani
10

Ce qui a fonctionné pour moi

Intent intent = new Intent(getApplicationContext(), HomeActivity.class);
ComponentName cn = intent.getComponent();
Intent mainIntent = IntentCompat.makeRestartActivityTask(cn);
startActivity(mainIntent);
Mongi Zaidi
la source
5

Une solution possible que je peux vous suggérer est d'ajouter android:launchMode="singleTop"dans le manifeste pour mon ProfileActivity . et quand vous déconnecter est cliqué u peut logoff recommençant vous LoginActivity. à la déconnexion, vous pouvez appeler ça.

Intent in = new Intent(Profile.this,Login.class);
                in.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(in);
                finish();
Android
la source
Je l'ai fait, ce qui s'est passé est: lorsque je clique sur le bouton retour, cela m'amène à l'Activty d'où je suis venu à ProfileActivity
Archie.bpgc
Cela peut se produire parce que vous êtes arrivé à ProfileActivity en appelant une nouvelle intention et non en appelant finish (); Comment arrivez-vous à ProfileActivity à partir d'une autre activité en dehors de LoginActivty?
Android
Je traverse la même question. Je pense que cela ne fonctionnerait pas lorsque l'intention de connexion a été détruite par le système, par exemple en raison d'un manque de mémoire.
user1914692
5

Pour l'API 11+, vous pouvez utiliser Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASKcomme ceci:

Intent intent = new Intent(this, MyActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);

Il effacera totalement toutes les activités précédentes et commencera une nouvelle activité.

madx
la source
4

Vous pouvez essayer finishAffinity(), il ferme toutes les activités en cours et fonctionne sur et au-dessus d'Android 4.1

lapin
la source
1
finishAffinity () ajouté dans l'API 16. Utilisez ActivityCompat.finishAffinity () dans la version précédente. Je fonctionne bien pour moi.
Anurag Srivastava
2

Je suis également confronté au même problème.

dans l'activité de connexion ce que je fais est.

    Intent myIntent = new Intent(MainActivity.this, ActivityLoggedIn.class);
    finish();
    MainActivity.this.startActivity(myIntent);  

à la déconnexion

   Intent myIntent = new Intent(ActivityLoggedIn.this, MainActivity.class);
   finish();
   ActivityLoggedIn.this.startActivity(myIntent);

Cela fonctionne bien, mais lorsque je suis dans ActivityLoggedIn et que je minimise l'application et clique sur l'icône du bouton du lanceur dans le tiroir de l'application, MainActivity redémarre: - / j'utilise le drapeau

android:LaunchMode:singleTask 

pour MainActivity.

Sujal Mandal
la source
2

Utilisez ce qui suit pour activity

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

supprimer l' indicateur CLEAR_TASK pour l'utilisation de fragments.

J'espère que cela peut utiliser pour certaines personnes.

Aristo Michael
la source
1

Gardez juste

Intent intent = new Intent(ProfileActivity.this,
    LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
startActivity(intent);
Gaurav Vashisth
la source
4
Ça ne fonctionne pas. Je peux toujours accéder à ProfileActivity en utilisant le bouton de retour
Archie.bpgc
1

Aucun des indicateurs d'intention n'a fonctionné pour moi, mais voici comment je l'ai corrigé:

Lorsqu'un utilisateur se déconnecte d'une activité, je devais diffuser un message à partir de cette activité, puis le recevoir dans les activités que je voulais fermer, après quoi j'appelle finish (); et ça marche plutôt bien.

Ian Wambai
la source
1

Essayez ceci, cela fonctionnera:

Intent logout_intent = new Intent(DashboardActivity.this, LoginActivity.class);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(logout_intent);
finish();
Mohammad
la source
1

Au niveau d'API 11 ou supérieur, utilisez FLAG_ACTIVITY_CLEAR_TASKet FLAG_ACTIVITY_NEW_TASKmarquez sur Intention pour effacer toute la pile d'activités.

Intent i = new Intent(OldActivity.this, NewActivity.class);
// set the new task and clear flags
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |  Intent.FLAG_ACTIVITY_CLEAR_TASK)
startActivity(i);
S.Sathya Priya
la source
0

Utilisez ceci

Intent i1=new Intent(getApplicationContext(),StartUp_Page.class);
i1.setAction(Intent.ACTION_MAIN);
i1.addCategory(Intent.CATEGORY_HOME);
i1.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
i1.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
i1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i1);
finish();
Prashant Kumar
la source
saviez-vous que setFlags et addFlags?
GvSharma
0

ajouter au manifeste pour votre activité android:launchMode="singleTask"

Hally Trần
la source
0

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 bitwise ou |.

intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK

Si vous prévoyez de l'utiliser régulièrement, 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 de l'option pour 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