Question

J'ai une application presque finie avec une structure d'activité non triviale. Il existe des notifications push associées à cette application, et la sélection de l'entrée de notification est censée afficher une activité spécifique, que l'application soit en avant / arrière-plan / non active.

Si l'application n'est pas active, j'ai réussi à démarrer avec succès l'application et la navigation automatique vers la partie appropriée. Cependant, lorsque l'application est active, j'ai un problème. Je présenterai une version simplifiée du problème, pour communiquer la nature du problème, et je publierai les détails de la structure d'activité de mon application et du code pertinent au besoin (en fait, en travaillant là-dessus maintenant).

Ainsi, la pile d'activités de mon application (très simplifiée) ressemble à ceci:

A -> b -> x

Où A, l'activité racine, est une page de connexion; B est quelque chose d'une "page d'accueil" et X est l'une des nombreuses activités qui peuvent être démarrées à partir de la page d'accueil (mais une seule instance active à la fois; car celles-ci ne peuvent être démarrées que de B).

Lorsque la notification est sélectionnée, j'ai besoin de l'application pour accéder automatiquement à B, quel que soit l'état dans lequel il se trouvait au préalable - que ce soit [a], [a -> b], [a -> b -> x] ou [] (] application non active).

Ma notification transmet une intention d'activité A. J'ai essayé d'utiliser les drapeaux clear_top et new_task, et aucun. A actuellement LaunchMode = singletask. En faisant cela, je pense que j'aborde toutes les configurations de pile existantes possibles et les réduisant à [A]. L'intention porte également un supplément qui l'identifie comme provenant d'une notification, par opposition à un lancement habituel.

L'activité A, lors de l'identification de l'intention comme étant envoyée à partir de la notification (elle peut le faire dans OnCreate () et OnNewIntent ()), envoie une intention à l'activité B. Cette intention contient clear_top et single_top. B a LaunchMode = singletop.

95% du temps, cela fonctionne comme souhaité, et après avoir appuyé sur la notification, la pile de l'application est [a -> b]. Environ 5% du temps, l'application se termine en quelque sorte avec une pile de [a -> b -> b].

Des idées sur ce qui se passe ici, ou tout ce que je fais de mal?

Je publierai plus de détails si cela s'avère être un problème non trivial. En fait, publier plus de détails maintenant ...

~~~~~~~~~~~~~~~~~~~~~~~~ Plus de détails ~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~

En passant par le débogueur montre que, chaque fois que A envoie son intention à B, l'instance existante de B est onDestroy () 'D avant d'être onCreate ()' D, puis avoir également son innewintent () appelé. Cela me semble étrange et suggère que je comprenne mal les drapeaux que j'utilise (clear_top et single_top), soit quelque chose d'autre qui interfère avec eux.

Je n'ai pas réussi à reproduire la structure de pile erronée dans le débogage. Je ne sais pas si c'est parce que cela ne se produit pas dans le débogage, ou je n'ai tout simplement pas essayé assez de fois.

Code pour les intentions réalisées:

Dans le service récepteur C2DM:

protected void onMessage(Context context, Intent intent) {
    int icon = R.drawable.some_drawable;
    CharSequence tickerText = "blah";
    long when = System.currentTimeMillis();
    Notification notification = new Notification(icon, tickerText, when);

    //Context context = getApplicationContext(); //Don't need this; using the context passed by the message.
    CharSequence contentTitle = intent.getStringExtra("payload");
    CharSequence contentText = "Lorem ipsum dolor si amet,";
    Intent notificationIntent = new Intent(this, LoginPage.class);
    //notificationIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); //Tried with and without
    notificationIntent.putExtra(PushManager.PUSH_INTENT, PushManager.PUSH_INTENT); //Indicator that this was send from notification

    PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
    notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);

    notificationManager.notify(PushManager.ALARM_NOTIFICATION_ID, notification);
}

Dans LoginPage (activité A), après une connexion réussie:

Intent i = new Intent(LoginPage.this, TabHomePage.class);
// (If we're automatically going to tab 2, inform next activity)
if(fromNotification) {
    i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
    i.putExtra(TabHomePage.TAB_NUMBER, TabHomePage.TAB_2);
}
startActivity(i);

Pour plus de détails sur la structure de la pile d'activités, voici l'image:

http://i89.photobucket.com/albums/k207/cephron/activitystack.png

Et voici les mille mots:

L'activité A est une page de connexion; Lors de la connexion réussie, il démarre B. B est une tabactivité, qui contient trois activités en elle (représentées par C, D, E). Chacun de C, D et E est en fait un groupe d'activités dont les activités des enfants imitent le comportement de pile habituel des activités.

Ainsi, chaque onglet contient sa propre pile d'activités, et la commutation entre les modifications des onglets, laquelle de ces piles est actuellement poussée vers / surgissée par la navigation de l'utilisateur (chaque onglet contient une pile de listactivités naviguant via une structure hiérarchique d'entités). Ceux-ci peuvent également commencer de nouvelles activités au-delà de la tabactivité géante «B» (représentée par X).

Ainsi, lors de la connexion de l'activité A, au moins trois activités sont créées avant que davantage l'entrée des utilisateurs ne soit acceptée: -B est créé (et est vu, en raison du TabWidget maintenant en haut de l'écran) -Un des groupes d'activité est créé : Celle-ci appartient à l'onglet par défaut. Ce groupe d'activité reste non représenté à l'écran, cependant ... il ne montre que la principale activité de sa pile d'activités enfants. -So, enfin, l'activité "racine" de la pile de ce groupe d'activité est créée (dans l'image, F est un exemple d'une telle activité). Cette activité se montre sous le TabWidget.

Une fois que chaque onglet a été visité une fois, aucune activité n'est créée / détruite en basculant entre les onglets (sans compter les tués de mémoire). En appuyant sur n'importe quelle finition d'onglet () Es l'activité en haut de cette pile, montrant celle en dessous. Appuyez sur Retour de l'activité racine (comme F) dans n'importe quel onglet termine l'intégralité de TabActivity, renvoyant l'utilisateur à A.

L'intention transmise à B lui demande également de naviguer automatiquement vers un onglet différent de la valeur par défaut. Dans le cas où nous nous retrouvons avec une pile de [a -> b -> b], le premier B est navigué vers l'onglet correct, et le second est par défaut.

Était-ce utile?

La solution

Tl; dr; N'utilisez pas clear_top avec single_top en même temps

S'il ne produit qu'une erreur de 5% du temps, il s'agit probablement d'un problème de concurrence. Vous avez dit que vous avez single_top | Clear_top pour l'appel de l'activité B. Clear_top détruit l'instance actuelle de l'activité B et l'intention est délivrée à onCreate (). Single_top ne détruise pas l'instance actuelle de l'activité B et offre l'intention de OnNewIntent ().

Lorsque l'indicateur Single_Top est en premier, l'intention est livrée à l'instance actuelle de l'activité B appelant onNewIntent (). Ensuite, Clear_Top est lu et l'activité B est détruite et une nouvelle instance est créée avec OnCreate () et tout fonctionne bien.

Lorsque clear_top est lu en premier, l'instance existante de l'activité B est détruite et une nouvelle est créée avec onCreate (). Ensuite, Single_Top est lu et l'intention est également livrée à onNewIntent (). Encore une fois, ça marche.

Lorsque clear_top et single_top sont lus en même temps, l'instance actuelle d'activité est détruite et clear_top appelle onCreate () et single_top appelle également onCreate (), car aucune instance d'activité B n'existe pour le moment. Ainsi, vous vous retrouvez avec a-> b-> b.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top