如何解决“Missing PendingIntent mutability flag”在android API 30+的Lint警告?

当我将目标SDK更新为30 + (Android R或更高版本)时,当我想定义PendingIntent时,在我的PendingIntent.FLAG_UPDATE_CURRENT标志上出现了一个lint警告Missing PendingIntent mutability flag

我应该如何处理这个绒线没有对应用程序功能的影响?

127314 次浏览

您可以将您的未决意图设置为

val updatedPendingIntent = PendingIntent.getActivity(
applicationContext,
NOTIFICATION_REQUEST_CODE,
updatedIntent,
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT // setting the mutability flag
)

根据这里的文档:https://developer.android.com/about/versions/12/behavior-changes-12#pending-intent-mutability

强烈考虑使用FLAG_IMMUTABLE,如果 一些功能依赖于PendingIntent是可变的,例如if 它需要与内联应答或冒泡一起使用

相应地选择你的旗帜。

如果你想了解更多,我建议你阅读这篇很棒的文章:https://medium.com/androiddevelopers/all-about-pendingintents-748c8eb8619

如果您没有使用最新版本的WorkManager,就会看到这个问题。在2.7.0-alpha02版本中已修复:

使PendingIntent可变显式,以修复针对Android 12时的崩溃

请记住,2.7.0-alpha02只与Android 12开发者预览1 SDK兼容。所以你可能想要等到它进入beta版或RC版。

2021年4月21日更新—为任何谷歌问题的人添加这个答案,你可能遇到的错误可能是这样的:

java.lang.IllegalArgumentException: com.myapp.myapp: Targeting S+ (version 10000 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality depends on the PendingIntent being mutable, e.g. if it needs to be used with inline replies or bubbles.
at android.app.PendingIntent.checkFlags(PendingIntent.java:386)
at android.app.PendingIntent.getBroadcastAsUser(PendingIntent.java:657)
at android.app.PendingIntent.getBroadcast(PendingIntent.java:644)
at androidx.work.impl.utils.ForceStopRunnable.getPendingIntent(ForceStopRunnable.java:174)
at androidx.work.impl.utils.ForceStopRunnable.isForceStopped(ForceStopRunnable.java:108)
at androidx.work.impl.utils.ForceStopRunnable.run(ForceStopRunnable.java:86)
at androidx.work.impl.utils.SerialExecutor$Task.run(SerialExecutor.java:75)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:920)

你不需要在你的应用中直接使用WorkManager来查看这个崩溃。

解决方案,如在这里所述,是为Android 12版本在build.gradle文件中添加一个依赖项:

 implementation 'androidx.work:work-runtime-ktx:2.7.0-alpha05'

注意,无论你使用的是Java、Kotlin +协程、RxJava2、GCMNetworkManager等等,这种依赖关系都是不同的。所以一定要检查上面的还原。

显然,用最新的版本号替换上面的版本号。如前所述,它不兼容android-13之前的版本。

这是Work库的问题。 即使是最新版本也会受到2.7.0-alpha04

的影响

https://issuetracker.google.com/issues/194108978

作为临时解决方案-注释包括“工作”;gradle中的依赖项,并在项目中使用该类删除。至少这样你可以正常运行应用程序,并在其他功能和领域工作....

如果你使用Java和ADMOB,你会在SDK S或Android 12上遇到PendingIntent错误。这里有一个修复,使ADMOB使用正确的工作-运行时。

implementation 'com.google.android.gms:play-services-ads:19.5.0'
constraints {
implementation('androidx.work:work-runtime:2.7.0-alpha05') {
because 'previous versions have a bug impacting this application'
}
}

在我的例子中,它也是由第三方库使用旧的WorkManager版本,在所有依赖项上强制使用新的Android Work版本,在你的构建中使用这个。gradle文件:

allproject {
project.configurations.all {
resolutionStrategy {
force 'androidx.work:work-runtime:2.7.0'
}
}
}

如果你让你的应用在android 12上运行,有一个新的PendingIntent可变标志。如果你不希望你的PendingIntent被改变,使用

PendingIntent pendingIntent;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);


}else {
pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);


}

如果你想要你的PendingIntent被突变,使用以下命令:

PendingIntent pendingIntent;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);


}else {
pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);


}
>在谷歌文档中说,强烈考虑使用FLAG_IMMUTABLE,只有当某些功能依赖于PendingIntent是可变的时才使用FLAG_MUTABLE。这种改变应该是直截了当的。 此外,如果你在应用程序中使用AdMob 20.4.0或更低版本,请确保添加以下工作管理器依赖项
//Work Manager dependency
implementation 'androidx.work:work-runtime:2.7.1'

请注意,当前工作管理器依赖版本为2.7.1。如果您愿意,可以将版本更新到最新版本。

实现androidx.work:work-runtime:2.7.1

我将我的work-runtime-ktx版本更新为2.7.1

在上面的修改之后,我又遇到了另一个错误

java.lang.IllegalStateException: SimpleTypeImpl should not be created for error type: ErrorScope{Error scope for class <ERROR CLASS> with arguments: org.jetbrains.kotlin.types.IndexedParametersSubstitution@14ac19e7}

看看我是如何通过更新kotlin-gradle-plugin版本在这里来解决上述错误的。

当我在我的代码中有四个不同的PendingIntents时,我首先将FLAG_IMMUTABLE添加到所有它们中。然而问题仍然存在。 在花了很多时间分析我的4个意图之后,我意识到问题可能来自我的一个库

在构建。gradle,库通常在旧的时候高亮显示,但Firebase的BOM不是这样的。

我有:

implementation platform('com.google.firebase:firebase-bom:26.1.1')

事实证明这是非常古老的。更新到

implementation platform('com.google.firebase:firebase-bom:29.0.4')

一切都很好。没有更多的FLAG_IMMUTABLE错误

如果你的应用程序的目标是Android 12 (targetSdkVersion = 31),和使用旧版本的WorkManager直接或任何第三方库,那么你需要将其更新到最新来解决它。

dependencies {
val work_version = "2.7.1"


// (Java only)
implementation("androidx.work:work-runtime:$work_version")


// Kotlin + coroutines
implementation("androidx.work:work-runtime-ktx:$work_version")


// optional - RxJava2 support
implementation("androidx.work:work-rxjava2:$work_version")
}
final int flag =  Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE : PendingIntent.FLAG_UPDATE_CURRENT;
PendingIntent pendingIntent = PendingIntent.getActivity(context, PENDING_INTENT_REQUEST_CODE, notificationIntent, flag);

我有像Fatal Exception: java.lang.IllegalArgumentException. Not posted. PendingIntents attached to actions with remote inputs must be mutable这样的崩溃。

我写了这个util方法,它允许将可变性作为参数发送。有时需要获取可变标志,例如通知中的回复操作

private fun getPendingIntentFlags(isMutable: Boolean = false) =
when {
isMutable && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S ->
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE


!isMutable && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ->
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE


else -> PendingIntent.FLAG_UPDATE_CURRENT
}

使用的例子:

val quickReplyPendingIntent = PendingIntent.getBroadcast(
context, notificationId, replyIntent,
getPendingIntentFlags(true)
)

如果你让你的应用在android 12上运行,有一个新的PendingIntent可变标志。如果你不希望你的PendingIntent被静音,使用

Java

PendingIntent updatedPendingIntent = PendingIntent.getActivity(
applicationContext,
NOTIFICATION_REQUEST_CODE,
updatedIntent,
PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT // setting the mutability flag
)

芬兰湾的科特林

val updatedPendingIntent = PendingIntent.getActivity(
applicationContext,
NOTIFICATION_REQUEST_CODE,
updatedIntent,
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT // setting the mutability flag
)

如果你想要你的PendingIntent静音使用以下方法:

Java

PendingIntent updatedPendingIntent = PendingIntent.getActivity(
applicationContext,
NOTIFICATION_REQUEST_CODE,
updatedIntent,
PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT // setting the mutability flag
)

芬兰湾的科特林

val updatedPendingIntent = PendingIntent.getActivity(
applicationContext,
NOTIFICATION_REQUEST_CODE,
updatedIntent,
PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT // setting the mutability flag
)

最后实现这个依赖

//Work Manager dependency
implementation 'androidx.work:work-runtime:2.7.1'

在我的项目中,这条线是可行的

PendingIntent pendingIntent = PendingIntent.getActivity(this,0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);

当你升级你的项目和目标android版本12时,这个问题就来了。使用该解决方案,您可以更新所有待处理实习生

目标S+(版本31及以上)需要在创建PendingIntent时指定FLAG_IMMUTABLE或FLAG_MUTABLE之一 enter image description here < / p >

以下代码

 PendingIntent pendingIntent = null;
if (Build.VERSION.SDK_INT>= Build.VERSION_CODES.S){
pendingIntent = stackBuilder.getPendingIntent(1, PendingIntent.FLAG_MUTABLE);


}else {
pendingIntent = stackBuilder.getPendingIntent(1, PendingIntent.FLAG_UPDATE_CURRENT);


}

如果你在项目中使用接收器,也要实现这个依赖工作

//Work Manager dependency
implementation 'androidx.work:work-runtime:2.7.1'

下面是我在KOTLIN中从30移动到33的用例。

1. 添加媒体依赖

implementation "androidx.media:media:1.4.1"

2. 更新工作管理器

 implementation "androidx.work:work-runtime-ktx:2.7.0"

3.更新不变的

fun getImmutableFlag() = if(isAndroidAPI31())  PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT else 0


fun isAndroidAPI31() = android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S


private fun createOpenAppIntent(context: Context): PendingIntent {
val intent = Intent(context, MainActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
}
return PendingIntent.getActivity(context, 0, intent, getImmutableFlag())
}

4. 如果在所有活动、服务、提供者、接收者中未添加,则在清单中添加导出标签

android:exported="true"

希望这能起作用,祝你愉快。

你可以像这样更新挂起的意图:

val updatedPendingIntent = PendingIntent.getActivity(
context,
NOTIFICATION_REQUEST_CODE,
updatedIntent,
PendingIntent.FLAG_IMMUTABLE| PendingIntent.FLAG_UPDATE_CURRENT
)

你可以添加PendingIntent。FLAG_IMMUTABLE加上|符号,它就可以工作了。

我想分享一下我的病例。我把标志改为FLAG_IMMUTABLE,但只有当应用程序在后台时才会出现错误。我得到了它从这里解决:https://github.com/firebase/firebase-android-sdk/issues/3115

根本原因是因为我以不赞成的方式检索FCM令牌:

FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(activity,  new OnSuccessListener<InstanceIdResult>() {
@Override
public void onSuccess(InstanceIdResult instanceIdResult) {
String newToken = instanceIdResult.getToken();
       

}
});

然后更新依赖项:

FirebaseMessaging.getInstance().getToken().addOnCompleteListener(task -> {
String newToken = task.getResult();
});

来自:

https://developer.android.com/reference/android/app/PendingIntent#FLAG_MUTABLE

直到Build.VERSION_CODES。R,默认为PendingIntents被假定为可变的,除非设置了FLAG_IMMUTABLE。从Build.VERSION_CODES开始。S,它将被要求在创建时显式指定PendingIntents的可变性(@link #FLAG_IMMUTABLE}或FLAG_MUTABLE。强烈建议在创建PendingIntent时使用FLAG_IMMUTABLE。FLAG_MUTABLE只应该在某些功能依赖于修改底层意图时使用,例如任何PendingIntent需要与内联应答或气泡."一起使用;

为了保持像今天一样的行为,将任何东西改为“PendingIntent”。任何东西 "

当创建/检索一个挂起的意图/活动,服务,提供者,接收者

值得寻找的地方:

PendingIntent.getBroadcast(...


.getPendingIntent(...


PendingIntent.getService


PendingIntent.getActivity

如果你的应用程序使用androidx。工作确保至少升级到:

implementation 'androidx.work:work-runtime-ktx:2.7.0-alpha05'

他们在alpha02中修复了一个与SDK 12中所有这些更改相关的错误。