如何解决android api 30+中的“缺少PendingIntent可变性标志”lint警告?

Ami*_*emi 26 android lint android-pendingintent

只要我的目标更新SDK30(安卓R),棉绒警告Missing PendingIntent mutability flag出现在我的PendingIntent.FLAG_UPDATE_CURRENT标志时,我想定义PendingIntent

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

Jos*_*osi 96

如果您让您的应用程序在 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);

    }
Run Code Online (Sandbox Code Playgroud)

如果您希望 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);

    }
Run Code Online (Sandbox Code Playgroud)

在 Google 文档中,强烈考虑使用 FLAG_IMMUTABLE,仅当某些功能依赖于 PendingIntent 可变时才使用 FLAG_MUTABLE。改变应该是简单的。另外,如果您在应用中使用 AdMob 20.4.0 或更低版本,请确保添加以下工作管理器依赖项:

//Work Manager dependency
implementation 'androidx.work:work-runtime:2.7.1'
Run Code Online (Sandbox Code Playgroud)

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

  • 对于`FLAG_MUTABLE`是的,它应该是`S`,因为它是在SDK 31中添加的,`FLAG_INMUTABLE`是在SDK 23中添加的,所以M是可以的 (11认同)
  • 除非我疯了,否则这会导致“else”块中出现“Missing PendingIntent mutability flag”linter 警告。我们可以 `@SuppressLint("UnspecifiedImmutableFlag")` 但看起来 linter 应该知道代码分支,不是吗?有没有更好的解决方案来解决这个警告? (3认同)

beg*_*ner 29

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);
Run Code Online (Sandbox Code Playgroud)


Nik*_*unj 26

如果您的应用程序面向Android 12 (targetSdkVersion = 31),并直接使用旧版本的WorkManager或通过任何第三方库使用旧版本的 WorkManager ,则您需要将其更新到最新版本才能解决该问题。

dependencies {
    val work_version = "2.8.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")        
}
Run Code Online (Sandbox Code Playgroud)

  • 这对我不起作用。我使用的是 2.8 alpha,但仍然收到错误。 (4认同)

Noe*_*oel 25

如果您使用的不是最新版本的 WorkManager,您将看到此问题。它已在2.7.0-alpha02版本中修复

明确 PendingIntent 可变性,以修复面向 Android 12 时的崩溃

请记住,2.7.0-alpha02 仅与 Android 12 Developer Preview 1 SDK 兼容。因此,您可能要等到它达到测试版或 RC。

20214 月 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)
Run Code Online (Sandbox Code Playgroud)

您不必实际直接在您的应用程序中使用 WorkManager 来查看此崩溃。

该解决方案所概述这里,是一个依赖添加到您的build.gradle文件为Android构建12:

 implementation 'androidx.work:work-runtime-ktx:2.7.0-alpha05'
Run Code Online (Sandbox Code Playgroud)

请注意,无论您是使用 Java only、Kotlin + coroutines、RxJava2、GCMNetworkManager 等,此依赖项都是不同的。 所以一定要检查上面的 dox。

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

  • 我尝试了```实现“androidx.work:work-runtime:2.7.0-alpha05”```。它与java一起工作正常。 (2认同)
  • 这不是错误的答案,只是可能不是完整的答案。如果您遇到此崩溃,但您在“PendingIntent”中使用了正确的标志,那么这就是您需要的解决方案。 (2认同)

May*_*jra 20

您可以将挂起的意图设置为

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

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

强烈考虑使用 FLAG_IMMUTABLE,仅当某些功能依赖于 PendingIntent 是可变的时才使用 FLAG_MUTABLE,例如,如果它需要与内联回复或气泡一起使用。

相应地选择您的标志。

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

  • 同样,这是谷歌的另一个糟糕的设计决定。它不是设置默认行为并记录警告,而是使应用程序崩溃...... (155认同)
  • 对于 Android 21+:`if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { PendingIntent.FLAG_IMMUTABLE 或 PendingIntent.FLAG_UPDATE_CURRENT } else { PendingIntent.FLAG_UPDATE_CURRENT }` (84认同)
  • 是的,直到几天前这里才出现问题——崩溃开始发生,我同意这是谷歌的一个糟糕的决定。 (2认同)

小智 14

您可以更新待处理的意图,例如:

val updatedPendingIntent = PendingIntent.getActivity(
   context,
   NOTIFICATION_REQUEST_CODE,
   updatedIntent,
   PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT 
)
Run Code Online (Sandbox Code Playgroud)

您可以添加 PendingIntent.FLAG_IMMUTABLE 和 | 签名,它就会起作用。

  • | 的 | 不是 kotlin 语法,你需要使用 `or` (2认同)

RRi*_*VEN 13

如果您使用 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'
        }
    }
Run Code Online (Sandbox Code Playgroud)


Nik*_*las 13

就我而言,它也是由使用旧 WorkManager 版本的第三方库实现的,为了在所有依赖项上强制使用新的 Android Work 版本,请在build.gradle 文件中使用此命令:

allproject {
  project.configurations.all {
    resolutionStrategy {
      force 'androidx.work:work-runtime:2.7.0'
    }
  }
}
Run Code Online (Sandbox Code Playgroud)


小智 9

此崩溃通过以下方法解决:实现 'androidx.work:work-runtime:2.7.1'


j3A*_*App 8

由于我的代码中有四个不同的 PendingIntents,因此我首先向所有这些 PendingIntents 添加 FLAG_IMMUTABLE。然而问题依然存在。在花了很多时间分析我的 4 个意图之后,我意识到问题可能来自我的一个库。

在 build.gradle 中,旧库通常会突出显示,但 Firebase BOM 并非如此。

我有:

implementation platform('com.google.firebase:firebase-bom:26.1.1')
Run Code Online (Sandbox Code Playgroud)

原来这已经很老了。更新到后

implementation platform('com.google.firebase:firebase-bom:29.0.4')
Run Code Online (Sandbox Code Playgroud)

一切都很好。不再有 FLAG_IMMUTABLE 错误


Reh*_*han 8

如果您让您的应用程序在 android 12 中运行,则会有一个新的 PendingIntent 可变性标志。如果您不希望 PendingIntent 被静音,请使用

爪哇

PendingIntent updatedPendingIntent = PendingIntent.getActivity(
   applicationContext,
   NOTIFICATION_REQUEST_CODE,
   updatedIntent,
   PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT // setting the mutability flag 
)
Run Code Online (Sandbox Code Playgroud)

科特林

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

如果您希望 PendingIntent 静音,请使用以下命令:

爪哇

PendingIntent updatedPendingIntent = PendingIntent.getActivity(
   applicationContext,
   NOTIFICATION_REQUEST_CODE,
   updatedIntent,
   PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT // setting the mutability flag 
)
Run Code Online (Sandbox Code Playgroud)

科特林

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

最后实现这个依赖

//Work Manager dependency
implementation 'androidx.work:work-runtime:2.7.1'
Run Code Online (Sandbox Code Playgroud)

  • 从逻辑上讲,如果我们之前使用了 UPDATE_CURRENT 标志,那么我们不应该使用 MUTABLE 标志吗?我们显然希望有一个可更新/可变的挂起意图。因此,如果我们使用标志 CANCEL_CURRENT,不应该使用 IMMUTABLE 吗?我不明白为什么要使用带有 IMMUTABLE 标志的 UPDATE_CURRENT ,它们实际上不是相互矛盾的吗? (2认同)

Vas*_*nov 5

我遇到过类似的崩溃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
    }
Run Code Online (Sandbox Code Playgroud)

使用示例:

val quickReplyPendingIntent = PendingIntent.getBroadcast(
                context, notificationId, replyIntent,
                getPendingIntentFlags(true)
            )
Run Code Online (Sandbox Code Playgroud)