Для чего «requestCode» используется в PendingIntent?

111

Задний план:

Я использую PendingIntent для сигналов тревоги через AlarmManager.

Эта проблема:

Сначала я подумал, что для того, чтобы отменить предыдущие, я должен предоставить точный requestCode, который я использовал раньше, чтобы запустить будильник.

Но потом я обнаружил, что ошибался, поскольку API отмены говорит:

Удалите все тревоги с соответствующим намерением. Любой сигнал тревоги любого типа, намерение которого соответствует этому (как определено filterEquals (Intent)), будет отменено.

глядя на filterEquals , в документации говорится:

Определите, совпадают ли два намерения для целей разрешения намерений (фильтрации). То есть, если их действие, данные, тип, класс и категории совпадают. При этом не сравниваются никакие дополнительные данные, включенные в намерения.

поэтому я не понимаю, для чего нужен "requestCode" ...

Вопрос:

Для чего используется requestCode?

Что, если я создам несколько алармов с одним и тем же «requestCode»? они перекрывают друг друга?

разработчик Android
источник
если вы используете тот же requestCode, вы получите тот же PendingIntent
pskink
3
Для PendingIntent.getBroadcast () requestCode явно игнорируется Android. Начиная с API 22, это не сделает ваше ожидающее намерение уникальным. Работает для getActivity () (и, возможно, getService (), но я не тестировал). stackoverflow.com/a/33203752/2301224
Бейкер
@Baker Разве это не ошибка? Если это ошибка, напишите об этом здесь: code.google.com/p/android/issues/list
разработчик Android,
1
На самом деле, в документации действительно указано использование кода запроса: 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 Верно, в чем смысл использования requestCode? Где это можно использовать?
разработчик Android

Ответы:

77
  1. requestCode используется для получения того же ожидающего экземпляра намерения позже (для отмены и т. д.).
  2. Да, я предполагаю, что сигналы тревоги будут перекрывать друг друга. Я бы сохранил коды запросов уникальными.
Минхадж Арфин
источник
5
устанавливает ли requestCode, чтобы он был уникальным, даже если намерения сигналов тревоги сильно различаются (например, для службы A и для службы B)? Кроме того, почему в документации об этом ничего не говорится? Можно ли удалить все алармы определенного типа, независимо от того, какой код запроса?
разработчик Android
1
Нет, для разных целей это не нужно. И я не знаю, почему в документации ничего об этом не говорится, но я узнал об этом при настройке повторяющихся сигналов тревоги, а также при использовании того же намерения.
Минхадж Арфин
2
Я говорил о PendingIntent. startActivityForResult использует обычное намерение.
разработчик Android
2
какова цель «startActivityForResult с PendingIntent с использованием прокси-активности»? можешь привести пример?
разработчик Android
3
Я согласен; документация для PendingIntent и AlarmManager - полная чушь - еще хуже из-за того, что невозможно перечислить алармы программно.
Someone Somewhere
34

Я просто хочу добавить к ответу @Minhaj Arfin

1- requestCode используется для получения того же ожидающего намерения позже (для отмены и т. Д.)

2- Да, они будут переопределены, если вы укажете того же получателя для своего намерения, которое вы указываете в своем PendingIntent.

пример:

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

В приведенном выше примере они не будут перекрывать друг друга, потому что получатель отличается (AlarmReceiverFirst и 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);

В приведенном выше примере они будут перекрывать друг друга, потому что получатель один и тот же (AlarmReceiverSecond)

HendraWD
источник
Intent startIntent4 = новое намерение (контекст, AlarmReceiverSecond.class); PendingIntent pendingIntent4 = PendingIntent.getService (контекст, 0, startIntent4, 0); тогда было бы хорошо? Я имею в виду, не будет ли это отменено, потому что он вызывает getService () вместо getBroadcast ()?
Jenix
Извините за другой вопрос, но поскольку stackoverflow не позволяет мне писать вопрос без единой строки кода ... Разве последний аргумент таких методов PendingIntent, как getBroadcast (), не имеет отношения к переопределению? Раньше я ставил 0, как и в приведенном выше примере кода, но я также видел, как многие люди ставили какое-то конкретное значение параметра вместо 0.
Jenix
1
@Jenix uou используйте AlarmReceiverSecond.classпо назначению, а затем используйте PendingIntent.getService(). Это не сработает, так AlarmReceiverSecond.classкак это BroadcastReceiver, а неService
HendraWD
1
Что касается флагов, это свойства, которые вы можете установить, которые будут определять поведение вашего PendingIntent в соответствии с указанными вами флагами. 0 означает, что все флаги выключены
HendraWD
Ах, я был глуп, ха-ха, о чем я думал ... Я был немного сбит с толку насчет PendingIntent, и ваш ответ был действительно полезен. Я просто хотел прояснить это, но теперь понял, что мой вопрос сначала не имел никакого смысла. Спасибо!
Jenix
2

в моем случае я хочу открыть одно и то же действие с двумя разными намерениями, поэтому, если в лотке есть два или более FCMS, любой из них будет только открывать, другой - нет, поэтому я изменил коды запросов ожидающих намерений, тогда это сработало.

 PendingIntent pendingIntent =
                            PendingIntent.getActivity(this, **Some unique id for all GCMS** /* Request code */, intent,
                                    PendingIntent.FLAG_ONE_SHOT);
JSONParser
источник
в моем случае не было необходимости дополнительно проверять код, можете ли вы сказать, в каком случае потребуется ожидающий экземпляр намерения. Что касается кода запроса на изменение вопроса, который помог мне перейти к правильному экрану, я не знаю, правильный ли это способ, и для меня ошибка возникала только тогда, когда в лотке было несколько FCM
JSONParser
Так зачем устанавливать другой код запроса, если он вам не нужен?
разработчик Android
хорошо, я подробно объясню, у меня была некоторая ДЕЯТЕЛЬНОСТЬ A, она предназначена для отображения вопросов, я передам идентификатор из уведомлений через намерение, а затем сделаю сетевой запрос для этого идентификатора и получу конкретный вопрос, так что же происходило, когда там есть более одного уведомления в панели уведомлений, а затем я нажимаю на любое из них, и я получаю идентификатор вопроса, который был в первом GCM, после изменения кода ожидающего запроса намерения на какое-то уникальное значение, которое он сработал. Надеюсь, теперь я прояснил, что если требуется еще какое-то обсуждение, я там, я также хочу узнать больше, спасибо
JSONParser
О, вы имели в виду, что иначе это вообще не сработало бы, верно? Извините за путаницу. Этот вопрос был задан давно, и я его совсем не помню ...
разработчик Android
1

Одна важная вещь, requestCodeкоторая может серьезно повредить вашему приложению, - это использование виджетов. виджеты не будут работать после перезагрузки телефона, если они requestCodeсовпадают. это означает pendingIndent, что remoteViewsдля вашего виджета должен быть установлен уникальный requestCode, обычно это widgetId, сопровождающий число.

Алиреза Джамали
источник
1

Собственно, в документации четко указано, для чего используется код запроса:

Если вам действительно нужно несколько различных объектов PendingIntent, активных одновременно (например, для использования в качестве двух одновременно отображаемых уведомлений), тогда вам нужно будет убедиться, что в них есть что-то отличное, чтобы связать их с разными PendingIntents. Это может быть любой из атрибутов Intent, рассматриваемых Intent # filterEquals (Intent), или различные целые числа кода запроса, предоставленные getActivity (Context, int, Intent, int), getActivities (Context, int, Intent [], int), getBroadcast ( Context, int, Intent, int) или getService (Context, int, Intent, int).

Поскольку кажется, что все еще не так ясно, позвольте мне попытаться объяснить:

Когда вы хотите использовать PendingIntentобъект, вы не просто создаете его экземпляр. Скорее, вы получаете его из системы, используя PendingIntentстатические методы ( getActivity, getBroadcastи getServiceт. Д.). Система хранит несколько экземпляров PendingIntent и предоставляет вам один. Какой из них он вам дает, зависит от входных параметров, которые вы передаете этим методам получения. Этими входными параметрами являются:, Contextт.е. целевой получатель намерения, Intentиспользуемый requestCodeи flags. Когда вы передаете то же самое Context, то же requestCodeсамое намерение (то есть намерение filterEqualsс другим намерением), вы получаете тот же PendingIntentобъект. Дело в том, что система хочет иметь как можно меньше PendingIntentобъектов, поэтому она стремится повторно использовать существующие в максимально возможной степени.

Например, у вас есть два календарных уведомления для двух разных дат. Когда вы нажимаете на один из них, вы хотите, чтобы ваше приложение открывалось до соответствующей даты этого уведомления. В этом сценарии у вас одна Contextи та же цель, а Intentобъект, который вы передаете, отличается только EXTRA_DATA (который указывает дату, которая должна быть открыта). Если вы предоставите то же самое requestCodeпри получении PendingIntentобъекта, вы получите тот же PendingIntentобъект. Итак, при создании второго уведомления вы замените старый Intentобъект новым EXTRA_DATA и получите два уведомления, указывающих на одну и ту же дату.

Если вы хотите иметь два разных PendingIntentобъекта, как и должно быть в этом сценарии, вы должны указать другой requestCodeпри получении PendingIntentобъекта.

Эйр
источник
Но, как я уже упоминал, для отмены будильников нельзя использовать только requestCode. Для этого это ничего не значит. Вам нужно будет ввести дополнительные данные, чтобы различать их. Я не помню, но думаю, что вы даже можете использовать один и тот же requestCode для нескольких сигналов тревоги.
разработчик Android
@androiddeveloper то, что вы только что сказали, неверно. Попытайся.
Эйр