O que é “requestCode” usado em PendingIntent?

110

Fundo:

Estou usando PendingIntent para alarmes via AlarmManager.

O problema:

A princípio pensei que, para cancelar os anteriores, devo fornecer o requestCode exato que usei antes para iniciar o alarme.

Mas então descobri que estava errado, como diz a API de cancelamento :

Remova todos os alarmes com um Intent correspondente. Qualquer alarme, de qualquer tipo, cujo Intent corresponda a este (conforme definido por filterEquals (Intent)), será cancelado.

olhando para " filterEquals ", a documentação diz:

Determine se duas intents são iguais para fins de resolução de intent (filtragem). Isto é, se sua ação, dados, tipo, classe e categorias são os mesmos. Isso não compara nenhum dado extra incluído nas intents.

então não entendi para que serve o "requestCode" ...

A questão:

Para que é usado "requestCode"?

E se eu criar vários alarmes com o mesmo "requestCode"? eles se sobrepõem?

desenvolvedor android
fonte
se você usar o mesmo requestCode, obterá o mesmo PendingIntent
pskink
3
Para PendingIntent.getBroadcast (), requestCode é aparentemente ignorado pelo Android. A partir da API 22, isso não tornará sua intenção pendente exclusiva. Faz para getActivity () (e talvez getService (), mas não testei). stackoverflow.com/a/33203752/2301224
Baker,
@Baker Isso não é considerado um bug? Se for um bug, você deve escrever sobre ele aqui: code.google.com/p/android/issues/list
android developer
1
Bem, na verdade, a documentação especifica o uso do 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 Certo, então qual é o ponto em usar o requestCode? Onde isso pode ser usado?
desenvolvedor Android

Respostas:

77
  1. requestCode é usado para recuperar a mesma instância de intent pendente posteriormente (para cancelamento, etc.).
  2. Sim, meu palpite é que os alarmes irão se sobrepor um ao outro. Eu manteria os códigos de solicitação exclusivos.
Minhaj Arfin
fonte
5
é necessário definir o requestCode como único, mesmo no caso de as intenções dos alarmes serem muito diferentes (um para o serviço A e outro para o serviço B, por exemplo)? Além disso, como é que a documentação não diz nada sobre isso? É possível remover todos os alarmes de um determinado tipo, não importa qual seja o requestCode?
desenvolvedor Android de
1
Não, não é necessário para diferentes intenções. E não sei por que a documentação não diz nada sobre isso, mas aprendi isso ao configurar alarmes repetidos e também ao usar a mesma intenção.
Minhaj Arfin
2
Eu estava falando sobre PendingIntent. startActivityForResult usa uma intenção normal.
desenvolvedor Android de
2
qual é o propósito de "startActivityForResult com PendingIntent usando uma atividade de proxy"? Você pode dar um exemplo?
desenvolvedor Android de
3
Concordo; a documentação para PendingIntent e AlarmManager é total - piorada pelo fato de que não é possível listar alarmes programaticamente.
Alguém em algum lugar
32

Eu só quero adicionar a resposta de @Minhaj Arfin

1- requestCode é usado para obter a mesma intenção pendente posteriormente (para cancelamento, etc.)

2- Sim, eles serão substituídos, desde que você especifique o mesmo Receptor para seu Intent que você especificou em seu PendingIntent

exemplo:

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

Do exemplo acima, eles não se substituirão porque o receptor é diferente (AlarmReceiverFirst e 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);

Do exemplo acima, eles se substituirão, porque o receptor é o mesmo (AlarmReceiverSecond)

HendraWD
fonte
Intent startIntent4 = novo Intent (contexto, AlarmReceiverSecond.class); PendingIntent pendingIntent4 = PendingIntent.getService (contexto, 0, startIntent4, 0); ficaria bem então? Quero dizer, isso não substituirá porque está chamando getService () em vez de getBroadcast ()?
Jenix de
Desculpe fazer outra pergunta, mas porque stackoverflow não me permite escrever uma pergunta sem uma única linha de código .. O último argumento dos métodos de PendingIntent como getBroadcast () não tem algo a ver com substituição? Eu costumava colocar 0 lá, assim como seu código de exemplo acima, mas também vi muitas pessoas colocando algum valor de opção específico em vez de 0.
Jenix
1
@Jenix você usa AlarmReceiverSecond.classna intenção e depois usa PendingIntent.getService(). Não funcionará, pois AlarmReceiverSecond.classé um BroadcastReceiver, não umService
HendraWD
1
Sobre os sinalizadores, são as propriedades que você pode definir que farão o comportamento do seu PendingIntent de acordo com os sinalizadores fornecidos. 0 significa todas as bandeiras desligadas
HendraWD
Ah, eu fui estúpido haha ​​O que diabos eu estava pensando .. Eu estava um pouco confuso sobre PendingIntent e sua resposta foi realmente útil. E eu só queria deixar isso mais claro, mas agora percebi que minha pergunta não fazia nenhum sentido no início. Obrigado!
Jenix de
2

no meu caso, quero abrir a mesma atividade com duas intents diferentes, portanto, se houver dois ou mais FCMS na bandeja, qualquer uma delas abrirá apenas a outra não, então mudei os códigos de solicitações de intents pendentes e funcionou.

 PendingIntent pendingIntent =
                            PendingIntent.getActivity(this, **Some unique id for all GCMS** /* Request code */, intent,
                                    PendingIntent.FLAG_ONE_SHOT);
JSONParser
fonte
não houve necessidade de verificar mais o código para o meu caso, você pode dizer em qual caso a instância de intent pendente será necessária. Com relação ao código de solicitação de alteração de pergunta me ajudou a ir para a tela correta, não sei se é a maneira correta e para mim o erro estava acontecendo apenas quando vários FCMs estavam lá na bandeja
JSONParser
Então, por que definir um código de solicitação diferente, se você não precisa dele?
desenvolvedor Android de
ok vou explicar em detalhes, tive alguma ATIVIDADE A, destina-se a mostrar perguntas que irei passar o id de notificações por intent e depois fazer uma solicitação de rede para esse id e buscar a questão em particular, então o que estava acontecendo quando lá há mais de 1 notificação na bandeja de notificação e então clico em qualquer uma delas e obtenho o id da questão que estava no primeiro GCM, após alterar o código de solicitação de intent pendente para algum valor exclusivo que funcionou. Espero ter deixado claro agora, se houver necessidade de mais discussão, estou lá, também quero saber mais, obrigado
JSONParser
Oh, você quis dizer que, do contrário, não teria funcionado, certo? Desculpe pela confusão. Esta pergunta foi feita há muito tempo e eu não me lembro bem dela ...
desenvolvedor Android
1

uma coisa importante sobre requestCodeisso que vai causar problemas sérios ao seu aplicativo é quando usar widgets. widgets não funcionarão após a reinicialização do telefone se requestCodeforem iguais. isso significa que o que pendingIndentvocê definiu no remoteViewsde seu widget deve ser definido como requestCode exclusivo, geralmente o widgetId que acompanha um número.

Alireza Jamali
fonte
0

Na verdade, a documentação afirma claramente para que o código de solicitação é usado:

Se você realmente precisa de vários objetos PendingIntent distintos ativos ao mesmo tempo (como para usar como duas notificações que são mostradas ao mesmo tempo), você precisará garantir que haja algo diferente sobre eles para associá-los a diferentes PendingIntents. Pode ser qualquer um dos atributos Intent considerados por Intent # filterEquals (Intent) ou diferentes números inteiros de código de solicitação fornecidos para getActivity (Context, int, Intent, int), getActivities (Context, int, Intent [], int), getBroadcast ( Context, int, Intent, int) ou getService (Context, int, Intent, int).

Como parece que ainda não está claro, deixe-me tentar explicar:

Quando você deseja usar um PendingIntentobjeto, não basta instanciar um. Em vez disso, você obter uma a partir do sistema usando os PendingIntentmétodos estáticos ( getActivity, getBroadcast, getServiceetc.). O sistema mantém várias instâncias PendingIntent e fornece uma. Qual ele fornece, depende dos parâmetros de entrada que você passa para esses métodos getter. Esses parâmetros de entrada são:, Contextou seja, o receptor alvo da intenção, a Intentusar requestCodee flags. Quando você passa o mesmo Context, o mesmo requestCodee mesmo Intent (ou seja, um intent filterEqualscom outro intent), você obtém o mesmo PendingIntentobjeto. A questão é que o sistema quer ter o mínimo de PendingIntentobjetos possível, então tende a reutilizar os existentes, tanto quanto possível.

Por exemplo, você tem duas notificações de calendário, para duas datas diferentes. Ao clicar em um deles, você deseja que seu aplicativo seja aberto na data correspondente dessa notificação. Nesse cenário, você tem o mesmo Contextdestino, e o Intentobjeto que você está passando difere apenas em EXTRA_DATA (que especifica a data que deve ser aberta). Se você fornecer o mesmo requestCodeao obter o PendingIntentobjeto, acabará com o mesmo PendingIntentobjeto. Assim, ao criar a segunda notificação, você irá substituir o Intentobjeto antigo pelo novo EXTRA_DATA, e ficará com duas notificações apontando para a mesma data.

Se você deseja ter dois PendingIntentobjetos diferentes , como deveria neste cenário, você deve especificar um diferente requestCodeao obter o PendingIntentobjeto.

Eir
fonte
Mas, como mencionei, para cancelar alarmes, você não pode usar apenas o requestCode. Não significa nada para isso. Você terá que colocar dados extras para diferenciá-los. Não me lembro, mas acho que você pode até usar o mesmo requestCode para vários alarmes.
desenvolvedor Android
@androiddeveloper o que você acabou de dizer está incorreto. Tente.
Eir