В Android 12/API 31 Geofence не работает с НЕИЗМЕНЯЕМЫМ pendingintent. Почему?

#android #android-pendingintent #android-geofence #android-12

Вопрос:

Новое поле PendingIntent в PendingIntent имеет значение FLAG_IMMUTABLE.

В 31 вы должны указать ИЗМЕНЯЕМЫЙ или НЕИЗМЕНЯЕМЫЙ, иначе вы не сможете создать PendingIntent (конечно, у нас не может быть значений по умолчанию, это для неудачников), как указано здесь

Согласно (веселому) Google Javadoc для Pendingintent, вы должны в основном всегда использовать НЕИЗМЕНЯЕМЫЙ (empasis мой):

Настоятельно рекомендуется использовать FLAG_IMMUTABLE при создании PendingIntent. FLAG_MUTABLE следует использовать только в тех случаях, когда какая-либо функциональность зависит от изменения базового намерения, например, любого PendingIntent, который необходимо использовать со встроенным ответом или пузырьками (комментарий редактора: ЧТО?).

Правильно, поэтому я всегда создавал подвесные элементы для такой геозоны, как эта:

 PendingIntent proximityIntent = PendingIntent.getBroadcast(context, requestCode, intent, PendingIntent.FLAG_NO_CREATE)
 

Всегда хорошо работало. Однако, следуя приведенным выше документам, я добавил НЕИЗМЕНЯЕМЫЙ флаг следующим образом:

 PendingIntent proximityIntent = PendingIntent.getBroadcast(context, requestCode, intent, PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_IMMUTABLE)
 

Теперь, к чему это приводит, так это к тому, что, пока я все еще сохраняю переходы геозоны в своем приемнике, если я позвоню

 List<Geofence> triggeringGeofences = geofencingEvent.getTriggeringGeofences();
 

Он возвращает значение null!

Итак, у меня есть два вопроса.

  1. Почему НЕИЗМЕНЯЕМЫЙ флаг приводит к тому, что я не получаю запускающую геозону, как это было в прошлом?
  2. Я делаю что-то не так? Есть ли способ сделать набор НЕИЗМЕНЯЕМЫМ с помощью триггеров геозоны?

На самом деле, у меня есть три вопроса:

  1. Почему документация Google такая запутанная, плохая, противоречивая и отстающая? (это риторический вопрос)

Указатели очень ценятся.

Комментарии:

1. Там нет Android 31. Название должно быть в API 31.

2. Вот почему люди больше не задают вопросов о переполнении стека.

Ответ №1:

В этом случае необходимо использовать ожидающее намерение для геозоны, FLAG_MUTABLE в то время как необходимо использовать ожидающее уведомление FLAG_IMMUTABLE намерение . К сожалению, они еще не обновили документацию или пример codelabs для таргетинга на Android 12. Вот как я изменил пример геозоны codelabs для работы.

Во-первых, обновите gradle до целевого SDK31.

В HuntMainActivity , измените geofencePendingIntent на:

   private val geofencePendingIntent: PendingIntent by lazy {
    val intent = Intent(this, GeofenceBroadcastReceiver::class.java)
    intent.action = ACTION_GEOFENCE_EVENT
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
      PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE)
    } else {
      PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
    }
  }
 

В NotificationUtils.kt , обновите уведомления, ожидающие намерения, следующим образом:

   val contentIntent = Intent(context, HuntMainActivity::class.java)
  contentIntent.putExtra(GeofencingConstants.EXTRA_GEOFENCE_INDEX, foundIndex)
  val contentPendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    PendingIntent.getActivity(
      context,
      NOTIFICATION_ID,
      contentIntent,
      PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
    )
  } else {
    PendingIntent.getActivity(
      context,
      NOTIFICATION_ID,
      contentIntent,
      PendingIntent.FLAG_UPDATE_CURRENT
    )
  }
 

Комментарии:

1. Спасибо. Не уверен, почему это так, хотя… (не помогает никакая документация)