如何解决 android api 30+ 中的 "Missing PendingIntent mutability flag" lint 警告?

How to resolve "Missing PendingIntent mutability flag" lint warning in android api 30+?

一旦我将目标 SDK 更新为 30+(Android R 或更高版本),一个 lint 警告当我想定义 PendingIntent.

时,Missing PendingIntent mutability flag 出现在我的 PendingIntent.FLAG_UPDATE_CURRENT 标志上

我应该如何处理这个 lint 而不影响应用程序的功能?

您可以将待定意向设置为

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

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.

相应地选择你的标志。

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

如果您使用的不是最新版本的 WorkManager,就会遇到此问题。它已在版本 2.7.0-alpha02:

中修复

Make PendingIntent mutability explicit, to fix a crash when targeting Android 12

请记住,2.7.0-alpha02 仅与 Android 12 Developer Preview 1 SDK 兼容。所以你可能想等到它进入测试版或 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 就会看到此崩溃。

here 所述,解决方案是为 Android 12 个构建向 build.gradle 文件添加依赖项:

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

请注意,无论您仅使用 Java、Kotlin + coroutines、RxJava2、GCMNetworkManager 等,此依赖项都是不同的。因此请务必检查 dox以上.

很明显把上面的版本号换成最新的。如前所述,它与 android-13 之前的版本不兼容。

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

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

作为临时解决方法 - 在 gradle 中注释掉包括“工作”依赖项,并删除在项目中使用该 class。至少通过这种方式,您可以 运行 正常应用并处理其他功能和领域....

如果您使用 Java 和 ADMOB,您会遇到 SDK S 或 Android12 的 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 工作版本在所有依赖项中使用它在你的 root build.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);

    }

在 Google 文档中说,强烈考虑使用 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 个意图之后,我突然意识到问题可能来自我的一个库。

在 build.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 个错误

如果您的应用面向 Android12(targetSdkVersion = 31),并且使用旧版本的WorkManager 直接或 通过任何 third-party 库 然后你需要 将它更新到最新的 来解决它。

dependencies {
    def work_version = "2.7.1"

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

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

对于 Java 开发者

PendingIntent pendingIntent = PendingIntent.getActivity(context, PENDING_INTENT_REQUEST_CODE,
            notificationIntent,
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ?
                    PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE : PendingIntent.FLAG_UPDATE_CURRENT);

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

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

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,Android 运行 应用程序在 Android 12 上时会出现此问题。使用该解决方案,您可以更新您的所有待定实习生

针对 S+(版本 31 及更高版本)要求在创建 PendingIntent 时指定 FLAG_IMMUTABLE 或 FLAG_MUTABLE 之一

在代码下方使用

 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'