Problème de classement de la stack d’activités lors du lancement de l’application à partir du programme d’installation de l’application Android et de l’écran d’accueil

À des fins de test uniquement, j’autorise le téléchargement et l’installation de mon application APK via une URL. Une fois téléchargé sur le téléphone, il peut être lancé avec l’installateur de l’application Android, ce qui permet à l’utilisateur de l’installer sur son appareil, puis de l’exécuter.

Considérez si nous avons téléchargé et exécuté l’application de la manière décrite ci-dessus. L’activité principale / lanceur de mon application est une page de connexion ( Activity A ). Une fois que l’utilisateur est authentifié, il est dirigé vers la zone principale de l’application, par exemple l’ Activity B Donc, la stack d’activité actuelle de cette tâche est A > B

J’ai ensuite appuyé sur le bouton d’accueil du téléphone et suis amené à l’écran d’accueil Android. Je relance mon application via l’icône dans le menu et je suis amené à l’ Activity A , au lieu de l’ Activity B Soit la stack d’activités est maintenant A > B > A , soit il y a maintenant deux tâches distinctes avec les stacks d’activité A > B et A respectivement. Ce que je veux, c’est revenir à l’ Activity B lorsque je relance l’application. Presser en arrière dans cet état me ramènera à l’ Activity B

Ce comportement indésirable ne se produit que si j’ouvre d’abord l’application via l’installateur et non si j’ouvre l’application via l’écran d’accueil / menu.

J’ai examiné comment les activités sont lancées par chaque mécanisme. Lorsque nous utilisons le programme d’installation de l’application, nous voyons les journaux suivants:

 INFO/ActivityManager(XXXX): Starting activity: Intent { dat=file:///mnt/sdcard/download/[my app].apk cmp=com.android.packageinstaller/.InstallAppProgress (has extras) } INFO/ActivityManager(XXXX): Starting activity: Intent { act=android.intent.action.MAIN flg=0x10000000 cmp=[my package]/[Activity A] } 

via le lanceur / écran d’accueil:

 INFO/ActivityManager(XXXX): Starting activity: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=[my package]/[Activity A] } 

Lorsqu’il est démarré avec l’installateur, nous voyons qu’il utilise l’indicateur 0x10000000 , mais lorsqu’il est démarré avec le lanceur, nous voyons qu’il utilise 0x10200000 . Il utilise également une catégorie d’intention.

À partir des documents, nous voyons les drapeaux:

 public static final int FLAG_ACTIVITY_NEW_TASK Constant Value: 268435456 (0x10000000) public static final int FLAG_ACTIVITY_RESET_TASK_IF_NEEDED Constant Value: 2097152 (0x00200000) 

L’indicateur FLAG_ACTIVITY_RESET_TASK_IF_NEEDED (utilisé lors du lancement de l’application depuis le lanceur) semble généralement empêcher la création d’une nouvelle tâche s’il existe déjà et restaure la dernière activité utilisée. C’est le comportement souhaité. Pourquoi ne travaille-t-il pas dans cette situation? Est-ce que je peux faire quelque chose pour m’assurer que mon application me renverra toujours à la dernière activité, qu’elle ait été lancée via le programme d’installation ou de lancement de l’application?

Si j’utilise singleTask cela me ramènera toujours à l’activité principale ( Activity A ) chaque fois que je lance l’application (ce qui n’est pas non plus souhaitable).

Voici une question que j’ai trouvée où quelqu’un rencontre un problème similaire (qui n’a pas de réponse acceptée): App perd sa capacité à se souvenir de sa stack lorsqu’il est lancé depuis une autre application

EDIT: Vérifier l’indicateur FLAG_ACTIVITY_BROUGHT_TO_FRONT dans onCreate() de notre activité de lanceur (puis terminer s’il est défini) semble corriger le symptôme principal, mais le problème sous-jacent est toujours là. Y a-t-il un correctif plus complet?

EDIT2: Le même résultat se produit lorsque vous téléchargez / exécutez l’application depuis Android Market. Par conséquent, certains des détails ci-dessus peuvent ne pas être pertinents.

Ajout de la réponse fournie par antonyt:

 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) { // Activity was brought to front and not created, // Thus finishing this will get us to the last viewed activity finish(); return; } // Regular activity creation code... } 

Je crois que le problème sous-jacent est que les Intent utilisées diffèrent entre le lanceur et l’installateur. Dans la mesure où vous obtenez différents drapeaux d’intention, vous allez avoir un comportement de lancement différent. Vous pouvez combiner les modes de lancement et obtenir un résultat cohérent, mais fondamentalement, ces différentes intentions produiront des résultats différents.

Votre correction (ou quelque chose comme ça ) est probablement votre meilleur pari.

Votre problème provient probablement du fait que l’installateur de l’application n’utilise pas la catégorie LAUNCHER, tout comme le lanceur.

Ce bug a été documenté ailleurs:

App commence toujours à partir de l’activité root au lieu de reprendre l’état d’arrière-plan (bogue connu)