Lorsque j’ai ajouté à SRDice la fonctionnalité pour gérer les Tests Étendus de Shadowrun 4ème édition, je me suis retrouvé confronté à un problème. J’avais créé une seconde Activity pour cette fonctionnalité, mais quand je demandais à fermer l’application depuis cette seconde Activity avec System.exit(0), je me retrouvais sur ma première Actitity des Tests Simples. Ce qui, d’une certaine façon, est normal, vu que les Activity se lancent les une après les autres en « s’empilant ». En fermant celle du dessus, Android me propose l’Activity disponible juste en dessous.
J’ai du chercher un moment une solution élégante avant de tomber sur un superbe tutoriel accompagné du code d’une micro application exemple : http://www.hrupin.com/2011/10/how-to-finish-all-activities-in-your-android-application-through-simple-call
Avec l’autorisation de l’auteur Igor Khrupin (thanks again) je vous le traduits :
La problématique est de pouvoir fermer toutes les Activity de votre application Android par un simple appel.
Il y a plusieurs façons de résoudre ce problème. Je vais vous montrer l’une d’elles. Ci-dessous vous pouvez télécharger l’exemple de projet. Ce projet contient 3 (trois) Activity et une Activity abstract. Toutes les Activity de ce projet étendent cette abstract. C’est elle qui étend Activity de l’API Android.
NDT : Allez sur le billet de Igor Khrupin pour récupérer les sources.
Voici la source de l’Abstract :
package com.hrupin; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; public abstract class AppBaseActivity extends Activity { public static final String FINISH_ALL_ACTIVITIES_ACTIVITY_ACTION = "com.hrupin.FINISH_ALL_ACTIVITIES_ACTIVITY_ACTION"; private BaseActivityReceiver baseActivityReceiver = new BaseActivityReceiver(); public static final IntentFilter INTENT_FILTER = createIntentFilter(); private static IntentFilter createIntentFilter() { IntentFilter filter = new IntentFilter(); filter.addAction(FINISH_ALL_ACTIVITIES_ACTIVITY_ACTION); return filter; } protected void registerBaseActivityReceiver() { registerReceiver(baseActivityReceiver, INTENT_FILTER); } protected void unRegisterBaseActivityReceiver() { unregisterReceiver(baseActivityReceiver); } public class BaseActivityReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(FINISH_ALL_ACTIVITIES_ACTIVITY_ACTION)) { finish(); } } } protected void closeAllActivities() { sendBroadcast(new Intent(FINISH_ALL_ACTIVITIES_ACTIVITY_ACTION)); } }
Vous pouvez voir que cette class contient BrodcastReceiver –> BaseActivityReceiver
Ce broadcastReceiver appelle le finish() pour l’Activity. Cette class contient aussi les méthodes pour créer intentFilter, déclarer et annuler le broadcastReceiver ainsi que la méthode closeAllActivities() qui va fermer uniquement les Activity de VOTRE application.
Le code est assez simple. 🙂
Je vous engage à aller télécharger le code source sur le billet de Igor Khrupin et à l’étudier. Il est vraiment très simple et compréhensible.
Si je devais résumer : On crée une Activity qui est celle déclarée dans l’AndroidManifest. Cette Activity est un Abstract et toutes les autres activity ne sont que ses filles. On a donc toujours qu’une seule activity d’active à la fois. Et vu qu’on ferme la mère (et seule activity), affaire réglée !
De plus, cette architecture est aussi très pratique pour mutualiser entre toutes vos activity les méthodes qui seraient communes (gestion du menu, fonctions génériques, …)
Plop !
C’est ce post qui m’a aidé :
http://cyol.fr/blog/post/dev-android-fermer-une-activity-depuis-une-autre/
Merci de prendre le temps de rédiger ce genre d’articles, ça aide pas mal ceux qui apprennent ! 🙂
De rien,
ça m’a beaucoup aidé moi aussi 😉
Pour finir j’ai utilisé un autre de tes posts.
J’ai fermé mon activité de demarrage depuis ma CorpsApp, et j’ai fermé CorpsApp avec un finish.
Merci d’avoir pris le temps de m’avoir répondu, et aussi rapidement ! 🙂
Simon
Cool !
Quel autre post t’as aidé au final ?
J’ai mis un bouton dans le menu pour fermer toutes les activités filles (deux pour moi) dérivant de ton activity AppBaseActivity mais rien ne se ferme x’)
A ce stade, sans avoir de code source, ça va être rude d’aider plus.
As tu chargés le projet de Igor Khrupin (cf lien dans l’article) pour voir le fonctionnement ?
Hum. Ok !
J’ai essayé ta technique, cad de faire hériter mes classes d’une classe mère (la tienne en fait), mais je ne sais pas comment fermer mes deux classes filles depuis mon CorpsApp.
Il faut utiliser quelle methode ?
Il faut que dans ton CorpsApp tu ais quelque chose qui appelle la fonction closeAllActivities();
Bonjour, j’ai essayé d’utiliser ta methode dans mon programme, mais je ne sais pas trop comment l’utiliser.
J’ai une application qui est composée (en gros) d’une activité d’accueil, c’est ma MainActivity, elle ne fait qu’afficher un message de bienvenue et puis redirige mon application vers une deuxième activité, ma CorpsApp.
J’ai essayé de fermer ma première activité avec un finish(); pour ne pas y retourner lors ce que je fais un retour dans CorpsApp, mais en faisant ça ma MainActivity ne s’affiche même pas..
J’ai essayé plusieurs choses mais je n’arrive pas à utiliser ce que tu as fait dans mon code.
Si tu pouvais m’aiguiller un peu ce serait cool !
Simon !
Sans voir le code ça va être dur d’aider.
De ce que j’ai compris :
MainActivity appelle CorpsApp
Le problème : Si on fait Retour, on retombe sur MainActivity
Sur ce point je ne peux pas aider.
Dans mon application j’ai la même chose (un Main, passage à une autre Activity; si j’appuis sur « retour » je reviens sur le Main ».
Mon problème initial n’était pas avec le « Retour » mais avec un bouton (ou un menu) Fermer qui devait fermer toutes les Activity (et donc l’appli) et pas seulement l’Activity « active ».
En effet, une Activity lancée reste en arrière plan, en mémoire, quand on ouvre une nouvelle Activity. L’effet du « Retour » est de fermer l’Activity courante, relaissant la place à l’Activity en arrière plan.