在 Android 12/API 31 中,Geofence 不适用于 IMMUTABLE pendingintent。为什么?
In Android 12/API 31, Geofence doesn't work with IMMUTABLE pendingintent. Why?
PendingIntent 中的新 PendingIntent 字段是 FLAG_IMMUTABLE。
在31中,必须指定MUTABLE或IMMUTABLE,否则无法创建PendingIntent,(当然我们不能有默认值,那是给失败者的)参考here
根据(搞笑的)Google Javadoc for Pendingintent,你应该基本上总是使用 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?).
是的,所以我总是像这样为地理围栏创建 PendingIntents:
PendingIntent proximityIntent = PendingIntent.getBroadcast(context, requestCode, intent, PendingIntent.FLAG_NO_CREATE)
一直工作得很好。但是,按照上面的文档,我添加了 IMMUTABLE 标志,如下所示:
PendingIntent proximityIntent = PendingIntent.getBroadcast(context, requestCode, intent, PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_IMMUTABLE)
现在,结果是当我仍然在我的接收器中进行地理围栏转换时,如果我调用
List<Geofence> triggeringGeofences = geofencingEvent.getTriggeringGeofences();
它returns无效!
所以,我有两个问题。
为什么 IMMUTABLE 标志导致我没有像过去那样获得触发地理围栏?
我是不是做错了什么?有没有办法用 Geofence 触发器来设置 IMMUTABLE?
其实我有3个疑问:
- 为什么 Google 的文档如此混乱、糟糕、矛盾和滞后? (反问)
不胜感激。
在这种情况下,地理围栏的挂起意图需要使用 FLAG_MUTABLE
,而通知挂起意图需要使用 FLAG_IMMUTABLE
。不幸的是,他们还没有更新目标 Android 12 的 documentation or the codelabs example。以下是我修改 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
)
}
PendingIntent 中的新 PendingIntent 字段是 FLAG_IMMUTABLE。
在31中,必须指定MUTABLE或IMMUTABLE,否则无法创建PendingIntent,(当然我们不能有默认值,那是给失败者的)参考here
根据(搞笑的)Google Javadoc for Pendingintent,你应该基本上总是使用 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?).
是的,所以我总是像这样为地理围栏创建 PendingIntents:
PendingIntent proximityIntent = PendingIntent.getBroadcast(context, requestCode, intent, PendingIntent.FLAG_NO_CREATE)
一直工作得很好。但是,按照上面的文档,我添加了 IMMUTABLE 标志,如下所示:
PendingIntent proximityIntent = PendingIntent.getBroadcast(context, requestCode, intent, PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_IMMUTABLE)
现在,结果是当我仍然在我的接收器中进行地理围栏转换时,如果我调用
List<Geofence> triggeringGeofences = geofencingEvent.getTriggeringGeofences();
它returns无效!
所以,我有两个问题。
为什么 IMMUTABLE 标志导致我没有像过去那样获得触发地理围栏?
我是不是做错了什么?有没有办法用 Geofence 触发器来设置 IMMUTABLE?
其实我有3个疑问:
- 为什么 Google 的文档如此混乱、糟糕、矛盾和滞后? (反问)
不胜感激。
在这种情况下,地理围栏的挂起意图需要使用 FLAG_MUTABLE
,而通知挂起意图需要使用 FLAG_IMMUTABLE
。不幸的是,他们还没有更新目标 Android 12 的 documentation or the codelabs example。以下是我修改 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
)
}