Do czego służy „requestCode” w PendingIntent?

110

Tło:

Używam PendingIntent do alarmów za pośrednictwem AlarmManager.

Problem:

Na początku pomyślałem, że aby anulować poprzednie, muszę podać dokładny requestCode, którego użyłem wcześniej do uruchomienia alarmu.

Ale potem dowiedziałem się, że się myliłem, ponieważ API anulowania mówi:

Usuń wszystkie alarmy z dopasowaną intencją. Każdy alarm dowolnego typu, którego intencja pasuje do tego (zgodnie z definicją filterEquals (Intent)), zostanie anulowany.

patrząc na „ filterEquals ”, dokumentacja mówi:

Określ, czy dwie intencje są takie same, na potrzeby rozwiązania intencji (filtrowania). Oznacza to, że ich działanie, dane, typ, klasa i kategorie są takie same. Nie porównuje to żadnych dodatkowych danych zawartych w intencjach.

więc nie rozumiem, do czego służy „requestCode” ...

Pytanie:

Do czego służy „requestCode”?

Co się stanie, jeśli utworzę wiele alarmów z tym samym „requestCode”? czy mają pierwszeństwo?

programista Androida
źródło
jeśli użyjesz tego samego requestCode, otrzymasz ten sam PendingIntent
pskink
3
W przypadku PendingIntent.getBroadcast () requestCode jest najwyraźniej ignorowany przez system Android. Od API 22 nie sprawi, że Twój oczekujący zamiar będzie wyjątkowy. Działa dla getActivity () (i być może getService (), ale nie testowałem). stackoverflow.com/a/33203752/2301224
Baker
@Baker Czy to nie jest uważane za błąd? Jeśli to błąd, napisz o tym tutaj: code.google.com/p/android/issues/list
programista Androida
1
Cóż, w rzeczywistości dokumentacja określa usaga requestiCode: If you truly need multiple distinct PendingIntent objects active at the same time (such as to use as two notifications that are both shown at the same time), then you will need to ensure there is something that is different about them to associate them with different PendingIntents. This may be any of the Intent attributes considered by Intent#filterEquals(Intent), or different request code integers supplied.
Eir
@ Eir Dobrze, więc jaki jest sens w używaniu requestCode? Gdzie można go użyć?
programista Androida

Odpowiedzi:

77
  1. requestCode służy do późniejszego pobrania tej samej oczekującej instancji intencji (do anulowania itp.).
  2. Tak, przypuszczam, że alarmy będą się wzajemnie unieważniać. Chciałbym zachować unikalne kody żądań.
Minhaj Arfin
źródło
5
czy ustawienie requestCode jako unikatowego jest potrzebne nawet w przypadku, gdy intencje alarmów są bardzo różne (na przykład jeden dla usługi A, a drugi dla usługi B)? Poza tym, dlaczego dokumentacja nic o tym nie mówi? Czy można usunąć wszystkie alarmy określonego typu, bez względu na to, jaki jest requestCode?
programista Androida
1
Nie, nie jest to konieczne z innych powodów. I nie wiem, dlaczego dokumentacja nic o tym nie mówi, ale nauczyłem się tego przy ustawianiu alarmów powtarzających się, a także przy tej samej intencji.
Minhaj Arfin
2
Mówiłem o PendingIntent. startActivityForResult używa normalnej intencji.
programista Androida
2
jaki jest cel „startActivityForResult with PendingIntent przy użyciu działania proxy”? czy możesz podać przykład?
programista Androida
3
Zgadzam się; dokumentacja dla PendingIntent i AlarmManager jest kompletna - pogarszana faktem, że nie jest możliwe programowe wyświetlanie alarmów.
Someone Somewhere
33

Chcę tylko dodać do odpowiedzi @Minhaj Arfin

1- requestCode służy do późniejszego uzyskania tego samego oczekującego zamiaru (do anulowania itp.)

2 - Tak, zostaną one zastąpione, o ile określisz tego samego odbiorcę w swoim zamiarze, który określisz w swoim PendingIntent

przykład:

Intent startIntent1 = new Intent(context, AlarmReceiverFirst.class);
PendingIntent pendingIntent1 = PendingIntent.getBroadcast(context, 0, startIntent1, 0);

Intent startIntent2 = new Intent(context, AlarmReceiverSecond.class);
PendingIntent pendingIntent2 = PendingIntent.getBroadcast(context, 0, startIntent2, 0);

Z powyższego przykładu nie będą się nadpisywać, ponieważ odbiornik jest inny (AlarmReceiverFirst i AlarmReceiverSecond)

Intent startIntent2 = new Intent(context, AlarmReceiverSecond.class);
PendingIntent pendingIntent2 = PendingIntent.getBroadcast(context, 0, startIntent2, 0);

Intent startIntent3 = new Intent(context, AlarmReceiverSecond.class);
PendingIntent pendingIntent3 = PendingIntent.getBroadcast(context, 0, startIntent3, 0);

Z powyższego przykładu będą się nadpisywać, ponieważ odbiornik jest taki sam (AlarmReceiverSecond)

HendraWD
źródło
Intent startIntent4 = new Intent (context, AlarmReceiverSecond.class); PendingIntent pendingIntent4 = PendingIntent.getService (context, 0, startIntent4, 0); byłoby dobrze wtedy? Chodzi mi o to, czy nie zastąpi to, ponieważ wywołuje metodę getService () zamiast getBroadcast ()?
Jenix
Przepraszam, że zadaję inne pytanie, ale ponieważ stackoverflow nie pozwala mi napisać pytania bez jednej linii kodu. Czy ostatni argument metod PendingIntent, takich jak getBroadcast (), nie ma nic wspólnego z przesłanianiem? Kiedyś
wstawiałem
1
@Jenix używasz AlarmReceiverSecond.classw zamiarze, a następnie używasz PendingIntent.getService(). To nie zadziała, ponieważ AlarmReceiverSecond.classjest to BroadcastReceiver, a nieService
HendraWD
1
Jeśli chodzi o flagi, to właściwości, które możesz ustawić, sprawią, że zachowanie twojego PendingIntent będzie zgodne z podanymi flagami. 0 oznacza wyłączenie wszystkich flag
HendraWD
Ach, byłem głupi haha ​​Co ja do cholery myślałem… Byłem trochę zdezorientowany co do PendingIntent i twoja odpowiedź była naprawdę pomocna. Chciałem tylko to wyjaśnić, ale teraz zdałem sobie sprawę, że moje pytanie na początku nie miało żadnego sensu. Dzięki!
Jenix
2

w moim przypadku chcę otworzyć tę samą czynność z dwoma różnymi intencjami, więc jeśli w zasobniku są dwa lub więcej FCMS, jeden z nich otworzy tylko inne nie, więc zmieniłem kody żądań oczekujących zamiarów, a następnie zadziałało.

 PendingIntent pendingIntent =
                            PendingIntent.getActivity(this, **Some unique id for all GCMS** /* Request code */, intent,
                                    PendingIntent.FLAG_ONE_SHOT);
JSONParser
źródło
nie było potrzeby dalszego sprawdzania kodu w moim przypadku, czy możesz powiedzieć, w którym przypadku będzie wymagana oczekująca instancja intencji. Jeśli chodzi o zmianę pytania, kod żądania pomógł mi przejść do prawidłowego ekranu, nie wiem, czy to jest właściwy sposób i dla mnie błąd występował tylko wtedy, gdy w zasobniku znajdowało się wiele FCM
JSONParser
Po co więc ustawiać inny kod żądania, jeśli go nie potrzebujesz?
programista Androida
ok, wyjaśnię szczegółowo, miałem AKTYWNOŚĆ A, ma to na celu pokazanie pytań, przekażę identyfikator z powiadomień przez intencję, a następnie wyślę żądanie sieciowe dla tego identyfikatora i pobiorę konkretne pytanie, więc co się działo, gdy tam jest więcej niż 1 powiadomienie w zasobniku powiadomień, a następnie klikam dowolne z nich i otrzymuję identyfikator pytania, które było w pierwszym GCM, po zmianie oczekującego kodu żądania zamiaru na jakąś unikalną wartość zadziałało. Mam nadzieję, że wyjaśniłem to teraz, jeśli potrzebna jest
jakakolwiek dalsza
Och, miałeś na myśli, że inaczej by to w ogóle nie zadziałało, prawda? Przepraszam za zamieszanie. To pytanie zostało zadane dawno temu i wcale go nie pamiętam ...
programista android
1

Jedną z ważnych rzeczy, requestCodektóre będą poważnym problemem w Twojej aplikacji, są widżety. widżety nie będą działać po ponownym uruchomieniu telefonu, jeśli requestCodesą takie same. Oznacza to, że element pendingIndentustawiony w remoteViewswidgecie musi mieć ustawiony unikalny kod żądania, zwykle widgetId towarzyszący liczbie.

Alireza Jamali
źródło
0

W rzeczywistości dokumentacja jasno określa, do czego służy kod żądania:

Jeśli naprawdę potrzebujesz wielu różnych obiektów PendingIntent aktywnych w tym samym czasie (na przykład jako dwóch powiadomień, które są wyświetlane w tym samym czasie), musisz upewnić się, że jest w nich coś innego, aby powiązać je z różnymi PendingIntents. Może to być dowolny z atrybutów Intent uwzględnianych przez Intent # filterEquals (Intent) lub różne liczby całkowite kodu żądania dostarczone do getActivity (Context, int, Intent, int), getActivities (Context, int, Intent [], int), getBroadcast ( Context, int, Intent, int) lub getService (Context, int, Intent, int).

Ponieważ wydaje się, że nadal nie jest to takie jasne, spróbuję wyjaśnić:

Kiedy chcesz użyć PendingIntentobiektu, nie tworzysz go po prostu. Przeciwnie, można uzyskać jedną z systemu przy użyciu PendingIntentmetody statyczne ( getActivity, getBroadcast, getServiceetc). System przechowuje kilka instancji PendingIntent i daje Ci jedną. To, który z nich daje, zależy od parametrów wejściowych przekazanych do tych metod pobierających. Te parametry wejściowe to: Contexttj. Docelowy odbiorca zamiaru, Intentużycie requestCodei flags. Kiedy przekazujesz ten sam Context, ten sam requestCodei ten sam zamiar (co oznacza zamiar filterEqualsz inną intencją), otrzymujesz ten sam PendingIntentobiekt. Chodzi o to, że system chce mieć jak najmniej PendingIntentobiektów, więc ma tendencję do ponownego wykorzystywania istniejących, w jak największym stopniu.

Na przykład masz dwa powiadomienia kalendarza dla dwóch różnych dat. Po kliknięciu jednego z nich chcesz, aby Twoja aplikacja otworzyła się zgodnie z datą tego powiadomienia. W tym scenariuszu masz ten sam Contextcel, a Intentobiekt, który przekazujesz różni się tylko DANE_DODATKOWE (które określają datę, która powinna być otwarta). Jeśli podasz to samo requestCodeprzy zdobywaniu PendingIntentprzedmiotu, otrzymasz ten sam PendingIntentprzedmiot. Tak więc, tworząc drugie powiadomienie, Intentzastąpisz stary obiekt nowym EXTRA_DATA i otrzymasz dwa powiadomienia wskazujące tę samą datę.

Jeśli chcesz mieć dwa różne PendingIntentobiekty, tak jak powinieneś w tym scenariuszu, requestCodepodczas uzyskiwania PendingIntentobiektu należy określić inny .

Eir
źródło
Ale jak już wspomniałem, aby anulować alarmy, nie możesz użyć samego requestCode. To nic dla niego nie znaczy. Będziesz musiał wprowadzić dodatkowe dane, aby je rozróżnić. Nie pamiętam, ale myślę, że możesz nawet użyć tego samego requestCode dla wielu alarmów.
programista android
@androiddeveloper to, co właśnie powiedziałeś, jest nieprawidłowe. Spróbuj.
Eir