【问题标题】:How to resolve "Missing PendingIntent mutability flag" lint warning in android api 30+?如何解决 android api 30+ 中的“缺少 PendingIntent 可变性标志”lint 警告?
【发布时间】:2021-07-06 18:43:24
【问题描述】:

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

在不影响应用功能的情况下,我应该如何处理这种 lint?

【问题讨论】:

标签: android android-pendingintent lint


【解决方案1】:

您可以将待处理的意图设置为

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,仅在以下情况下使用 FLAG_MUTABLE 某些功能取决于 PendingIntent 是可变的,例如如果 它需要与内联回复或气泡一起使用。

相应地选择您的标志。

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

【讨论】:

  • 对于 Android 21+:if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT } else { PendingIntent.FLAG_UPDATE_CURRENT }
  • 再说一次,这是 Google 的另一个糟糕的设计决策。它没有设置默认行为并记录警告,而是使应用程序崩溃......
  • 谢谢你,我为我的依赖问题做了一个fix
  • 这在 kotline 中效果很好
【解决方案2】:

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

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

请注意,2.7.0-alpha02 仅与 Android 12 Developer Preview 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 即可看到此崩溃。

here 所述,解决方案是在您的build.gradle 文件中添加一个依赖项以用于Android 12 构建:

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

请注意,无论您使用的是仅 Java、Kotlin + 协程、RxJava2、GCMNetworkManager 等,这种依赖都是不同的。所以请务必检查上面的 dox。

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

【讨论】:

  • 这方面有更新吗?我使用-alpha04 进行了尝试,但仍然收到错误消息。我的应用程序只有 1 个 PendingIntent 并且无法从这次崩溃中继续前进。第三方库会导致此崩溃吗?
  • 我试过implementation "androidx.work:work-runtime:2.7.0-alpha05"。它在 java 中运行良好。
  • Adam——很有可能是另一个库导致了崩溃。您可以使用“./gradlew :app:dependencies”(在 Linux 中)查看项目的完整依赖关系树。例如,play-services-ads-lite:20.2.0 依赖于 androidx.work:work-runtime:2.1 .0 我认为这就是问题所在(在android.googlesource.com/platform/frameworks/support/+/… 中修复)
  • @Satheesh,是的——它们在源代码中为 2.7.0.beta-01,但它似乎在存储库中不可用,用于生成构建但 android.googlesource.com/platform/frameworks/support/+/… 另请参阅maven.google.com/web/…
  • 我不使用工作库,也没有它 build.gradle
【解决方案3】:

如果您让您的应用在 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;
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。如果需要,您可以将版本更新到最新版本。

【讨论】:

  • 不应该是版本S而不是M吗?
  • 对于FLAG_MUTABLE是的,应该是S,因为它是在SDK 31中添加的,FLAG_INMUTABLE是在SDK 23中添加的,所以M是可以的
  • 感谢您,解决了我对从小部件中的 ListView 动态加载 URL 的 Intent 的 FLAG_MUTABLE 要求。
【解决方案4】:

如果您使用 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'
        }
    }

【讨论】:

【解决方案5】:

在我的情况下,它也是由使用旧 WorkManager 版本的第三方库来强制所有依赖项上的新 Android Work 版本在您的 root build.gradle 文件中使用的:

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

【讨论】:

    【解决方案6】:

    此崩溃已通过以下方式解决: implementation 'androidx.work:work-runtime:2.7.1'

    【讨论】:

      【解决方案7】:

      如果您的应用面向 Android 12 (targetSdkVersion = 31),并且直接使用旧版本的 WorkManager任何第三方库 strong> 那么您需要将其更新到最新版本才能解决。

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

      【讨论】:

        【解决方案8】:

        这是工作库的问题。 连最新版本都受影响2.7.0-alpha04

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

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

        【讨论】:

          【解决方案9】:

          我将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版本here来解决上述错误的。

          【讨论】:

            【解决方案10】:

            由于我的代码中有四个不同的 PendingIntent,我首先将 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 错误

            【讨论】:

              【解决方案11】:

              对于 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);
              

              【讨论】:

                【解决方案12】:

                我遇到过像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)
                            )
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2015-11-20
                  • 2013-07-14
                  • 2014-08-23
                  • 1970-01-01
                  • 2021-12-18
                  • 2021-05-17
                  • 2019-01-02
                  相关资源
                  最近更新 更多