À quoi sert «requestCode» sur PendingIntent?

110

Contexte:

J'utilise PendingIntent pour les alarmes via AlarmManager.

Le problème:

Au début, j'ai pensé que pour annuler les précédents, je devais fournir le requestCode exact que j'ai utilisé auparavant pour déclencher l'alarme.

Mais ensuite, j'ai découvert que j'avais tort, comme le dit l' API d'annulation :

Supprimez toutes les alarmes avec une intention correspondante. Toute alarme, de tout type, dont l'intention correspond à celle-ci (telle que définie par filterEquals (Intent)), sera annulée.

en regardant " filterEquals ", la documentation dit:

Déterminez si deux intentions sont identiques aux fins de la résolution d'intention (filtrage). Autrement dit, si leur action, leurs données, leur type, leur classe et leurs catégories sont identiques. Cela ne compare aucune donnée supplémentaire incluse dans les intentions.

donc je ne comprends pas à quoi sert le "requestCode" ...

La question:

À quoi sert "requestCode"?

Que faire si je crée plusieurs alarmes avec le même "requestCode"? se substituent-ils les uns aux autres?

développeur android
la source
si vous utilisez le même requestCode, vous obtiendrez le même PendingIntent
pskink
3
Pour PendingIntent.getBroadcast (), requestCode est apparemment ignoré par Android. À partir de l'API 22, cela ne rendra pas votre intention en attente unique. Fait pour getActivity () (et peut-être getService () mais je n'ai pas testé). stackoverflow.com/a/33203752/2301224
Baker
@Baker N'est-ce pas considéré comme un bug? S'il s'agit d'un bogue, vous devriez écrire à ce sujet ici: code.google.com/p/android/issues/list
développeur android
1
Eh bien, en fait, la documentation précise l'usaga du 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 Bon, alors quel est l'intérêt d'utiliser le requestCode? Où peut-il être utilisé?
développeur android le

Réponses:

77
  1. requestCode est utilisé pour récupérer ultérieurement la même instance d'intention en attente (pour l'annulation, etc.).
  2. Oui, je suppose que les alarmes se neutraliseront. Je garderais les codes de demande uniques.
Minhaj Arfin
la source
5
est-il nécessaire de définir le requestCode pour qu'il soit unique, même si les intentions des alarmes sont très différentes (une pour le service A et une pour le service B, par exemple)? Aussi, comment se fait-il que la documentation n'en dise rien? Est-il possible de supprimer toutes les alarmes d'un certain type, quel que soit le requestCode?
développeur android
1
Non, ce n'est pas nécessaire pour différentes intentions. Et je ne sais pas pourquoi la documentation ne dit rien à ce sujet, mais j'ai appris cela en définissant des alarmes répétitives et également en utilisant la même intention.
Minhaj Arfin
2
Je parlais de PendingIntent. startActivityForResult utilise une intention normale.
développeur android
2
quel est le but de "startActivityForResult avec PendingIntent en utilisant une activité proxy"? Pouvez-vous donner un exemple?
développeur android
3
Je suis d'accord; la documentation pour PendingIntent et AlarmManager est totalement sh! t - aggravée par le fait qu'il n'est pas possible de lister les alarmes par programmation.
Someone Somewhere
33

Je veux juste ajouter à la réponse @Minhaj Arfin

1- requestCode est utilisé pour obtenir la même intention en attente plus tard (pour l'annulation, etc.)

2- Oui, ils seront remplacés tant que vous spécifiez le même Receiver à votre intention que vous spécifiez sur votre PendingIntent

exemple:

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

De l'exemple ci-dessus, ils ne se remplaceront pas car le récepteur est différent (AlarmReceiverFirst et 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);

De l'exemple ci-dessus, ils se remplaceront, car le récepteur est le même (AlarmReceiverSecond)

HendraWD
la source
Intent startIntent4 = new Intent (contexte, AlarmReceiverSecond.class); PendingIntent pendingIntent4 = PendingIntent.getService (contexte, 0, startIntent4, 0); serait bien alors? Je veux dire, est-ce que cela ne remplacera pas parce qu'il appelle getService () au lieu de getBroadcast ()?
Jenix
Désolé de poser une autre question, mais parce que stackoverflow ne me permet pas d'écrire une question sans une seule ligne de code .. Le dernier argument des méthodes de PendingIntent comme getBroadcast () n'a-t-il pas quelque chose à voir avec le remplacement? J'avais l'habitude de mettre 0 là-bas, comme votre exemple de code ci-dessus, mais j'ai également vu que beaucoup de gens mettaient une valeur d'option spécifique au lieu de 0.
Jenix
1
@Jenix vous utilisez AlarmReceiverSecond.classsur l'intention, puis utilisez PendingIntent.getService(). Cela ne fonctionnera pas, car AlarmReceiverSecond.classc'est un BroadcastReceiver, pas unService
HendraWD
1
À propos des indicateurs, ce sont les propriétés que vous pouvez définir, qui feront le comportement de votre PendingIntent en fonction des indicateurs que vous avez fournis. 0 signifie que tous les drapeaux sont désactivés
HendraWD
Ah j'étais stupide haha ​​A quoi diable étais-je en train de penser… J'étais un peu confus au sujet de PendingIntent et ta réponse était vraiment utile. Et je voulais juste que ce soit plus clair, mais je me suis maintenant rendu compte que ma question n'avait aucun sens au début. Merci!
Jenix
2

dans mon cas, je veux ouvrir la même activité avec deux intentions différentes, donc si deux ou plusieurs FCMS sont là dans le bac, l'un d'eux n'ouvrira que l'autre ne le sera pas, donc j'ai changé les codes de demande d'intention en attente, puis cela a fonctionné.

 PendingIntent pendingIntent =
                            PendingIntent.getActivity(this, **Some unique id for all GCMS** /* Request code */, intent,
                                    PendingIntent.FLAG_ONE_SHOT);
JSONParser
la source
il n'était pas nécessaire de vérifier davantage le code pour mon cas, pouvez-vous dire dans quel cas l'instance d'intention en attente sera requise. En ce qui concerne le code de demande de changement de question, m'a aidé à obtenir un écran correct, je ne sais pas si c'est la bonne façon et pour moi une erreur ne se produisait que lorsque plusieurs FCM étaient là dans le bac
JSONParser
Alors pourquoi définir un code de requête différent, si vous n'en avez pas besoin?
développeur android
ok je vais expliquer en détail, j'ai eu une activité A, il est destiné à montrer des questions je vais passer l'identifiant des notifications à l'intention, puis faire une demande réseau pour cet identifiant et récupérer la question particulière, alors que se passait-il quand il y a Il y a plus de 1 notifications dans la barre de notification, puis je clique sur l'une d'entre elles.J'obtiens l'id de la question qui se trouvait dans le premier GCM, après avoir changé le code de demande d'intention en attente en une valeur unique, cela a fonctionné. J'espère avoir été clair maintenant, si plus de discussion est nécessaire, je suis là, je veux aussi en savoir plus, merci
JSONParser
Oh, vous vouliez dire que sinon cela n'aurait pas fonctionné du tout, non? Désolé pour la confusion. Cette question a été posée il y a longtemps et je ne m'en souviens pas bien du tout ...
développeur android
1

Une chose importante à ce sujet requestCodequi gênera sérieusement votre application est l'utilisation de widgets. Les widgets ne fonctionneront pas après le redémarrage du téléphone s'ils requestCodesont identiques. cela signifie que le pendingIndentparamètre que vous définissez sur le remoteViewsde votre widget doit être défini comme un requestCode unique, généralement le widgetId accompagnant un nombre.

Alireza Jamali
la source
0

En fait, la documentation indique clairement à quoi sert le code de requête:

Si vous avez vraiment besoin de plusieurs objets PendingIntent distincts actifs en même temps (par exemple pour les utiliser comme deux notifications qui sont toutes les deux affichées en même temps), vous devrez vous assurer qu'il y a quelque chose de différent à leur sujet pour les associer à des PendingIntents. Il peut s'agir de n'importe lequel des attributs Intent considérés par Intent # filterEquals (Intent), ou de différents entiers de code de requête fournis à getActivity (Context, int, Intent, int), getActivities (Context, int, Intent [], int), getBroadcast ( Context, int, Intent, int) ou getService (Context, int, Intent, int).

Puisqu'il semble que ce n'est toujours pas si clair, laissez-moi essayer d'expliquer:

Lorsque vous souhaitez utiliser un PendingIntentobjet, vous ne vous contentez pas d'en instancier un. Au contraire, vous obtenez un à partir du système en utilisant les PendingIntentméthodes statiques ( getActivity, getBroadcast, getServiceetc.). Le système conserve un tas d'instances PendingIntent et vous en donne une. Lequel il vous donne, cela dépend des paramètres d'entrée que vous passez à ces méthodes getter. Ces paramètres d'entrée sont:, Contextc'est-à-dire le récepteur cible de l'intention, le Intentà utiliser, requestCodeet flags. Lorsque vous transmettez la même Context, la même requestCodeet la même intention (c'est-à-dire une intention filterEqualsavec une autre intention), vous obtenez le même PendingIntentobjet. Le fait est que le système veut avoir le moins d' PendingIntentobjets possible, donc il a tendance à réutiliser autant que possible les objets existants.

Par exemple, vous avez deux notifications de calendrier, pour deux dates différentes. Lorsque vous cliquez sur l'un d'entre eux, vous souhaitez que votre application s'ouvre à la date correspondante de cette notification. Dans ce scénario, vous avez la même Contextcible et l' Intentobjet que vous passez ne diffère que par EXTRA_DATA (qui spécifie la date qui doit être ouverte). Si vous fournissez la même chose requestCodelors de l'obtention de l' PendingIntentobjet, vous vous retrouverez avec le même PendingIntentobjet. Ainsi, lors de la création de la deuxième notification, vous remplacerez l'ancien Intentobjet par le nouveau EXTRA_DATA, et vous vous retrouverez avec deux notifications pointant vers la même date.

Si vous souhaitez avoir deux PendingIntentobjets différents , comme vous le devriez dans ce scénario, vous devez en spécifier un différent requestCodelors de l'obtention de l' PendingIntentobjet.

Eir
la source
Mais comme je l'ai mentionné, pour annuler les alarmes, vous ne pouvez pas utiliser uniquement le requestCode. Cela ne veut rien dire. Vous devrez mettre des données supplémentaires pour les différencier. Je ne me souviens pas mais je pense que vous pouvez même utiliser le même requestCode pour plusieurs alarmes.
développeur android
@androiddeveloper ce que vous venez de dire est incorrect. Essayez-le.
Eir