La notification dépasse les anciens extras d'intention

134

Je crée une notification dans un BroadcastReceiver via ce code:

String ns = Context.NOTIFICATION_SERVICE;
        NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(ns);
        int icon = R.drawable.ic_stat_notification;
        CharSequence tickerText = "New Notification";
        long when = System.currentTimeMillis();

        Notification notification = new Notification(icon, tickerText, when);
        notification.defaults |= Notification.DEFAULT_VIBRATE;
        long[] vibrate = {0,100,200,200,200,200};
        notification.vibrate = vibrate;
        notification.flags |= Notification.FLAG_AUTO_CANCEL;

        CharSequence contentTitle = "Title";
        CharSequence contentText = "Text";
        Intent notificationIntent = new Intent(context, NotificationActivity.class);
        notificationIntent.putExtra(Global.INTENT_EXTRA_FOO_ID, foo_id);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);

        notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);

        int mynotification_id = 1;

        mNotificationManager.notify(mynotification_id, notification);

Lorsque je clique sur la notification, cela ouvre la NotificationActivity et à l'intérieur de l'activité, je peux récupérer le foo_id du Intent-Bundle (par exemple 1)

Cependant, si une autre notification est déclenchée et que je clique dessus à nouveau, l'activité reçoit toujours la «vieille» valeur (1) de l'Intention-Bundle. J'ai essayé d'effacer le paquet avec clear (), mais je reçois le même effet. Je pense que qc est faux avec mon code ..

BrianM
la source
s'il vous plaît pouvez-vous me dire comment obtenir les données de l'intention en attente
user49557
se rendre compte qu'il envoyait de vieux extras, a rendu mon tri plus facile.
Utsav Gupta

Réponses:

268

Vous envoyez le même code de demande pour votre intens en attente. Change ça:

PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);

À:

PendingIntent contentIntent = PendingIntent.getActivity(context, UNIQUE_INT_PER_CALL, notificationIntent, 0);

les intentions ne sont pas créées si vous envoyez les mêmes paramètres. Ils sont réutilisés.

IncrediApp
la source
1
donc UNIQUE_INT_PER_CALL est un entier que je dois fournir? ou est-ce une variable statique déclarée quelque part?
BrianM
23
android gotcha # 147 - donc un Intentqui a des extras différents (via putExtra) est considéré comme le même et réutilisé parce que je n'ai pas fourni un identifiant unique à un appel d'intention en attente - terrible api
wal
vous savez quoi, j'étais si insouciant. Je pensais juste comment cela pourrait-il rester 0 dans un bloc (dans mon cas) :(
Exigente05
3
Cela a été incroyablement utile pour moi, juste un conseil pour les autres, il est probable que vous construisiez votre notification de la même manière, et vous pouvez donc simplement définir l'identifiant de la nouvelle intention en attente sur le même que celui que vous allez utiliser pour l'identifiant unique des notifications!
James McNee
1
@IncrediApp, en est-il de même avec PendingIntent.getBroadcast (); ?
Shruti
139

Vous pouvez également utiliser le code suivant pour générer votre PendingIntent:

PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);

De la doc pour PendingIntent.FLAG_UPDATE_CURRENT:

Si le PendingIntent décrit existe déjà, conservez-le, mais remplacez ses données supplémentaires par ce qui se trouve dans cette nouvelle intention. Cela peut être utilisé si vous créez des intentions dans lesquelles seuls les extras changent, et que vous ne vous souciez pas du fait que toutes les entités qui ont reçu votre précédente PendingIntent pourront la lancer avec vos nouveaux extras même si elles ne lui sont pas explicitement données.

ChristophK
la source
Merci ... fonctionne parfaitement pour ce drapeau qui est ajouté "PendingIntent.FLAG_UPDATE_CURRENT" :)
Najib Ahmed Puthawala
1
A travaillé pour moi, en utilisant l'intention en attente pour transférer l'état du réglage d'une alarme au récepteur de diffusion.
William T.Mallard
Je souhaite juste savoir ce que ces indicateurs ont vraiment fait avant d'envoyer des notifications à mes utilisateurs (!) Heureux que cela résout mes problèmes ...
James Andrew
42

Vous transmettez le même identifiant. Dans ce genre de situation, créez un identifiant unique comme ceci:

int iUniqueId = (int) (System.currentTimeMillis() & 0xfffffff);

Et dites-le comme ceci:

PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(),iUniqueId, intentForNotification, 0);
hderanga
la source
3
pourquoi ne pas utiliser le nouveau Random (). nextInt ()
exloong
@hderanga que fait l'ajout de "& 0xfffffff" à l'int ci-dessus?
AJW
3
@AJW System.currentTimeMillis()renvoie un long, tandis que le requestIdparamètre de PendingIntent.getActivity()prend un int. 0xffffffffest un masque binaire. Bien qu'il y ait un peu plus à cela, l'explication simple est que faire `long & 0xffffffff 'donne les 32 bits les plus bas du long et rejette les 32 bits les plus élevés, vous laissant essentiellement un int 32 bits. C'est mieux que de simplement lancer un int, car cela ne gâchera pas le bit de signe (si vous lancez un long qui est plus grand qu'un int en un int, le bit de signe débordera et vous vous retrouverez potentiellement avec une valeur négative )
Jordan Bondo
8

Pour tous ceux qui recherchent la meilleure approche après une longue période, vous devez transmettre PendingIntent.FLAG_UPDATE_CURRENT comme dernier argument, comme indiqué ci-dessous

PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);

vous n'avez même pas besoin de fournir un nouvel identifiant unique.

Vous devez le faire pour la prochaine fois, pas pour la première fois

Doux
la source
1
Cela ne fonctionne pas, je suis arrivé ici parce que c'est ce que je faisais.
Brill Pappin
Vous devez le faire pour les prochaines fois, pas pour la première fois, cela fonctionnera.
Gentle
0

Votre code de demande est 0 pour toutes les notifications. Changer la ligne suivante:

PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);

Avec:

PendingIntent contentIntent = PendingIntent.getActivity(context, new Random().nextInt(), notificationIntent, 0);
Faisal Shaikh
la source
1
Y a-t-il un avantage à utiliser "new Random (). NextInt ()" plutôt que "System.currentTimeMillis ()"?
AJW
l'utilisation de random peut facilement régénérer à nouveau la même valeur entière en cas d'accident, provoquant ainsi un bug très difficile à trouver des anciennes intentions passées.
Sam
@AJW il y en avait dans mon cas. J'ai créé 2 notifications différentes en exactement la même milliseconde, donc l'une d'elles a eu de mauvais extras.
artman
0

Je voulais juste ajouter une autre option

 PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE);
pellucide
la source