Categories
discuss

In Android 12/API 31, Geofence doesn’t work with IMMUTABLE pendingintent. Why?

A new PendingIntent field in PendingIntent is FLAG_IMMUTABLE.

In 31, you must specify MUTABLE or IMMUTABLE, or you can’t create the PendingIntent, (Of course we can’t have defaults, that’s for losers) as referenced here

According to the (hilarious) Google Javadoc for Pendingintent, you should basically always use IMMUTABLE (empasis mine):

It is strongly recommended to use FLAG_IMMUTABLE when creating a PendingIntent. FLAG_MUTABLE should only be used when some functionality relies on modifying the underlying intent, e.g. any PendingIntent that needs to be used with inline reply or bubbles (editor’s comment: WHAT?).

Right, so i’ve always created PendingIntents for a Geofence like this:

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

Always worked fine. However, following the docs above, i added the IMMUTABLE flag like this:

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

Now, what that results in is that while i still the geofence transitions in my Receiver, if i call

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

It returns null!

So, i have two questions.

  1. Why does the IMMUTABLE flag result in that i don’t get the triggering geofence as i have in the past?

  2. Am i doing something wrong? Is there a way to do set IMMUTABLE with Geofence triggers?

Actually, i have three questions:

  1. Why is Google’s documentation so confusing, bad, contradictory and lagging behind? (it’s a rhetorical question)

Pointers much appreciated.

Answer

In this case, the pending intent for the geofence needs to use FLAG_MUTABLE while the notification pending intent needs to use FLAG_IMMUTABLE. Unfortunately, they have not updated the documentation or the codelabs example for targeting Android 12 yet. Here’s how I modified the codelabs geofence example to work.

First, update gradle to target SDK31.

In HuntMainActivity, change the geofencePendingIntent to:

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

In NotificationUtils.kt, update the notifications pending intent as follows:

  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
    )
  }
Source: stackoverflow
Text is available under the Creative Commons Attribution-ShareAlike License; additional terms may apply. By using this site, you agree to the Privacy Policy, and Copyright Policy. Content is available under CC BY-SA 3.0 unless otherwise noted. The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 © No Copyrights, All Questions are retrived from public domain..