Powiadomienie przechodzi stare Intent Extras

134

Tworzę powiadomienie wewnątrz BroadcastReceiver za pomocą tego kodu:

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);

Kiedy klikam powiadomienie, otwiera się NotificationActivity, a wewnątrz działania mogę pobrać foo_id z Intent-Bundle (np. 1)

Jeśli jednak zostanie uruchomione inne powiadomienie i kliknę je ponownie, aktywność nadal otrzyma „starą” wartość (1) z paczki intencji. Próbowałem wyczyścić pakiet za pomocą clear (), ale otrzymuję ten sam efekt. Myślę, że coś jest nie tak z moim kodem.

BrianM
źródło
czy możesz mi powiedzieć, w jaki sposób otrzymujesz dane z oczekujących intencji
user49557
uświadomienie sobie, że wysyła stare dodatki, ułatwiło mi selekcję.
Utsav Gupta

Odpowiedzi:

268

Wysyłasz ten sam kod żądania dla oczekującego intensywności. Zmień to:

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

Do:

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

intencje nie są tworzone, jeśli wysyłasz te same parametry. Są ponownie wykorzystywane.

IncrediApp
źródło
1
więc UNIQUE_INT_PER_CALL jest liczbą całkowitą, którą muszę podać? czy jest to gdzieś zadeklarowana zmienna statyczna?
BrianM,
23
Android gotcha # 147 - więc ten, Intentktóry ma różne dodatki (przez putExtra), jest uważany za taki sam i ponownie używany, ponieważ nie podałem unikalnego identyfikatora dla jakiegoś oczekującego połączenia - straszny api
wal
wiesz co, byłem taki nieostrożny.
Zastanawiam się,
3
Było to dla mnie niesamowicie przydatne, tylko wskazówka dla innych, prawdopodobnie budujesz swoje powiadomienie tą samą metodą, więc możesz po prostu ustawić identyfikator nowego oczekującego zamiaru na taki sam, jak ten, który zamierzasz użyj unikalnego identyfikatora powiadomień!
James McNee
1
@IncrediApp, czy to samo z PendingIntent.getBroadcast (); ?
Shruti
139

Alternatywnie możesz użyć następującego kodu, aby wygenerować swój PendingIntent:

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

Z dokumentu dla PendingIntent.FLAG_UPDATE_CURRENT:

Jeśli opisany PendingIntent już istnieje, zachowaj go, ale zastąp jego dodatkowe dane tym, co znajduje się w nowej intencji. Można tego użyć, jeśli tworzysz intencje, w których zmieniają się tylko dodatki, i nie obchodzi Cię, że jakiekolwiek podmioty, które otrzymały Twój poprzedni PendingIntent, będą w stanie uruchomić go z nowymi dodatkami, nawet jeśli nie zostały im wyraźnie nadane.

ChristophK
źródło
Dzięki ... doskonale działa z tą flagą, która jest dodana „PendingIntent.FLAG_UPDATE_CURRENT” :)
Najib Ahmed Puthawala
1
Zadziałało dla mnie, wykorzystując oczekujący zamiar do przeniesienia stanu z ustawienia alarmu do odbiornika transmisji.
William T. Mallard
Chciałbym tylko wiedzieć, co naprawdę robią te flagi, zanim wysłałem powiadomienia do moich użytkowników (!) Cieszę się, że to rozwiązuje moje problemy ...
James Andrew
42

Przekazujesz ten sam identyfikator. W takiej sytuacji stwórz unikalny identyfikator od czasu do czasu:

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

I ująć to tak:

PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(),iUniqueId, intentForNotification, 0);
hderanga
źródło
3
dlaczego nie użyć nowego Random (). nextInt ()
exloong
@hderanga co robi dodanie „& 0xfffffff” do int powyżej?
AJW
3
@AJW System.currentTimeMillis()zwraca long, podczas gdy requestIdparametr of PendingIntent.getActivity()przyjmuje int. 0xffffffffjest maską bitową. Chociaż jest w tym trochę więcej, proste wyjaśnienie jest takie, że wykonanie `long & 0xffffffff 'daje najniższe 32-bity z długich i odrzuca najwyższe 32-bity, pozostawiając zasadniczo 32-bitową wartość int. Jest to lepsze niż zwykłe rzutowanie na int, ponieważ nie zepsuje bitu znaku (jeśli rzucisz long, który jest większy niż int do int, bit znaku przepełni się i potencjalnie skończysz z wartością ujemną )
Jordan Bondo,
8

Dla każdego, kto szuka najlepszego podejścia po długim czasie, musisz przekazać PendingIntent.FLAG_UPDATE_CURRENT jako ostatni argument, jak pokazano poniżej

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

nie musisz nawet podawać nowego unikalnego identyfikatora.

Musisz to zrobić następnym razem, a nie pierwszy raz

Delikatny
źródło
1
To nie działa, dotarłem tutaj, ponieważ to właśnie robiłem.
Brill Pappin
Musisz to zrobić następnym razem, a nie po raz pierwszy, to zadziała.
Delikatny
0

Twój kod żądania to 0 dla wszystkich powiadomień. Zmień następujący wiersz:

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

Z:

PendingIntent contentIntent = PendingIntent.getActivity(context, new Random().nextInt(), notificationIntent, 0);
Faisal Shaikh
źródło
1
Czy jest jakaś korzyść z używania „new Random (). NextInt ()” zamiast „System.currentTimeMillis ()”?
AJW
użycie random może łatwo ponownie wygenerować tę samą wartość całkowitą w razie wypadku, powodując w ten sposób bardzo trudny do znalezienia błąd przekazywania starych intencji.
Sam
@AJW było w moim przypadku. Utworzyłem 2 różne powiadomienia w dokładnie tej samej milisekundzie, więc jedno z nich dostało złe dodatki.
artman
0

Chciałem tylko dodać inną opcję

 PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE);
przezroczysty
źródło