Как андроид сравнивает ожидающие намерения

Документация для PendingIntent.FLAG_NO_CREATE читает:

Флаг, указывающий, что если описанный PendingIntent еще не существует, просто возвращайте null вместо его создания.

Мой вопрос: Какие критерии используются для сравнения PendingIntents?

Я предполагаю, что под капотом этот флаг использует PendingIntent.equals, но я не совсем уверен, какие критерии используют функция, Используется ли действие action, requestCode, категории, дополнения (я догадываюсь нет) и т.д.?

Context:

Я хочу запустить будильник с ожидающим намерением, если мой будильник еще не настроен. В частности, я следую этому answer.

Intent i = new Intent(applicationContext, MyService.class);
i.setAction("myAction");
PendingIntent pi = PendingIntent.getService(applicationContext, /*requestCode*/0, i, PendingIntent.FLAG_NO_CREATE);
if (pi != null) {
  AlarmManager alarmMgr = (AlarmManager)applicationContext.getSystemService(Context.AlarmService);
  alarmMgr.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, AlarmManager.INTERVAL_HOUR, AlarmManager.INTERVAL_HOUR, pi);
}

Ответы

Ответ 1

Чтобы определить, соответствует ли 2 PendingIntent, следующее должно быть равным:

  • Параметр requestCode, используемый при создании PendingIntent
  • Intent ACTION
  • КАТЕГОРИИ Intent
  • Intent DATA
  • Intent MIMETYPE
  • Пакет Intent
  • Intent КОМПОНЕНТ

Экстра не принимаются во внимание.

Вы можете прочитать больше в итоговой документации PendingIntent и Intent.filterEquals().

Ответ 2

Я предполагаю, что под капотом этот флаг использует PendingIntent.equals, но Я не совсем уверен, какие критерии использует функция. Использует ли он действие, requestCode, категории, дополнения (я догадываюсь нет) и т.д.?

На самом деле подсказка в описании класса:

Описание действия Intent и target для выполнения с ним. Экземпляры этого класса создаются с помощью

getActivity (android.content.Context, INT, android.content.Intent, целое), getActivities (android.content.Context, Int, android.content.Intent [], Int), getBroadcast (android.content.Context, INT, android.content.Intent, целое), GetService (android.content.Context, Int, android.content.Intent, целое);

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

Предоставляя PendingIntent другому приложению, вы предоставляете его право выполнять указанную операцию, как если бы другая приложение было собой (с теми же правами и идентификацией). В виде например, вы должны быть осторожны в том, как вы создаете PendingIntent: почти всегда, например, базовое намерение, которое вы поставляете, должно иметь имя компонента, явно установленное на один из ваших собственных компонентов, для обеспечения он в конечном итоге отправляется туда и больше нигде.

Сам PendingIntent это просто ссылка на токен, поддерживаемый системой, описывающей исходные данные, используемые для извлечения. Это означает, что даже если его владелец процесса приложения убит, сам PendingIntent будет остаются пригодными для других процессов, которые ему были предоставлены. Если создавая приложение, повторно восстанавливает тот же вид PendingIntent (такая же операция, одно и то же действие, данные, категории и компоненты, и те же флаги), он получит PendingIntent, представляющий тот же если это все еще действует, и поэтому может вызвать функцию cancel(), чтобы удалить его.

Из-за этого поведения важно знать, когда два намерения считается одинаковым с целью получения ожидающего ответа. Обычная ошибка, которую люди делают, - создать несколько PendingIntent объекты с намерениями, которые изменяются только в их "лишнем" содержимом, ожидая получить различный PendingIntent каждый раз. Это не бывает. Элементами намерения, которые используются для сопоставления, являются те же, что определены Intent.filterEquals. Если вы используете два намерения объекты, эквивалентные по Intent.filterEquals, тогда вы будете получить тот же PendingIntent для обоих из них.

Существует два типичных способа решения этой проблемы.

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

Если вам нужен только один активный PendingIntent за один раз для любого из Намерения, которые вы будете использовать, затем вы можете использовать флаги FLAG_CANCEL_CURRENT или FLAG_UPDATE_CURRENT для отмены или изменения независимо от того, какой текущий PendingIntent связан с намерением, которым вы являетесь поставки.

от: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.0.0_r1/android/app/PendingIntent.java#PendingIntent