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

回答 17 浏览 10.9万 2021-04-11

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

我应该如何在不影响应用功能的情况下处理这个提示呢?

Amir Hossein Ghasemi 提问于2021-04-11
stackoverflow.com/questions/70889493/android-12-pending-intent 有谁能帮助我解决这个问题?Dark_Clouds_369 2022-02-12
17 个回答
#1楼 已采纳
得票数 201

您可以将您的待定意向设置为

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是可变的情况下才使用FLAG_MUTABLE,例如,如果它需要与内联回复或气泡一起使用。

相应地选择你的旗帜。

如果你想阅读更多关于这方面的内容,我建议你在这里阅读这篇伟大的文章。https://medium.com/androiddevelopers/all-about-pendingintents-748c8eb8619

Mayur Gajra 提问于2021-04-11
对于安卓21岁以上的人。if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT } else { PendingIntent.FLAG_UPDATE_CURRENT }user924 2021-09-30
同样,这也是谷歌的另一个糟糕的设计决定。它没有设置一个默认行为并记录一个警告,而是使应用程序崩溃...doctorram 2021-10-07
谢谢你,我已经为我的依赖性问题做了一个fixRic17101 2021-10-15
我也收到了同样的错误,在看到各种解决方案后,我像这样设置了可变性标志 - ``如果(Build.VERSION.SDK_INT >= Build.VERSION_CODES.S){ pendingIntent = PendingIntent.getActivity (this, 0, intent, PendingIntent.FLAG_IMMUTABLE|PendingIntent.FLAG_UPDATE_CURRENT); } else { pendingIntent = PendingIntent.getActivity (this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); }```Zarar Mahmud 2022-04-18
是的,这里没有任何问题,直到几天前 -- 崩溃开始发生,我同意这是谷歌的一个糟糕的决定。gattsbr 2022-08-31
#2楼
得票数 74

如果你没有使用最新版本的WorkManager,你会看到这个问题。它已经在版本2.7.0-alpha02中得到了修复。

使PendingIntent的突变性显性化,以修复针对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 就能看到这种崩溃。

正如此处所概述的解决方案,是在您的build.gradle文件中添加一个用于Android 12构建的依赖项。

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

请注意,无论你是只使用Java、Kotlin + coroutines、RxJava2、GCMNetworkManager等,这个依赖性都是不同的。所以一定要检查上面的dox。

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

Noel 提问于2021-04-20
fattire 修改于2021-08-21
这方面有什么更新吗?我尝试使用-alpha04,但仍然收到错误。我的应用程序只有一个PendingIntent,无法从这个崩溃中继续前进。第三方库会导致这种崩溃吗?Adam Gardner 2021-07-01
我试着用implementation "androidx.work:work-runtime:2.7.0-alpha05"。它在java中工作得很好。satheesh 2021-08-18
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/+/…中修复)。fattire 2021-08-21
@Satheesh,是的--他们在源代码中已经达到了2.7.0.beta-01,但似乎还不能在仓库中用于生成构建 android.googlesource.com/platform/frameworks/support/+/… 也请看maven.google.com/web/…fattire 2021-08-21
这不是错误的答案,只是它可能不是完整的答案。如果你有这种崩溃,但你在你的PendingIntent中使用了正确的标志,那么这就是你需要的解决方案。Khantahr 2021-11-03
#3楼
得票数 67

如果你让你的应用程序在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。如果你愿意,你可以把版本更新到最新的版本。

Yosidroid 提问于2021-12-04
Yosidroid 修改于2022-05-01
不应该是S版,而不是M版吗?StainlessSteelRat 2022-01-06
对于FLAG_MUTABLE是的,它应该是S,因为它是在SDK31中添加的,FLAG_INMUTABLE是在SDK23中添加的,所以M是可以的。jcesarmobile 2022-02-04
谢谢你,解决了我在Intent上的FLAG_MUTABLE需求,该Intent可从Widget中的ListView动态加载一个URL。automaton 2022-02-15
在较早的API级别上使用较新的标志应该是安全的,因为该值是内联的。在较早的级别上不知道的标志,不应该干扰它对它所知道的标志的比特检查。mtotschnig 2022-04-30
除非我疯了,否则这会导致else块中出现"Missing PendingIntent mutability flag" linter警告。我们可以@SuppressLint("UnspecifiedImmutableFlag"),但似乎linter应该知道这个代码分支,不是吗?有什么更好的办法来解决这个警告吗?ksparrow 2022-06-07
#4楼
得票数 17

如果你的应用程序以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")        
}
Nikunj 提问于2022-02-14
Nikunj 修改于2022-06-08
这对我来说并不奏效。我在2.8 alpha上,仍然收到错误。Marty Miller 2022-09-24
#5楼
得票数 14
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);
beginner 提问于2022-03-02
beginner 修改于2022-06-10
#6楼
得票数 11

如果你使用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'
        }
    }
RRiVEN 提问于2021-10-24
这个问题从play-services-ads:20.4.0版本开始就被修复了,因为发行说明中说developers.google.com/admob/android/rel-notesilansas 2021-12-29
#7楼
得票数 10

在我的案例中,这也是由使用旧的WorkManager版本的第三方库造成的,为了在所有的依赖中强制使用新的Android Work版本,请在你的root build.gradle文件中使用这个。

allproject {
  project.configurations.all {
    resolutionStrategy {
      force 'androidx.work:work-runtime:2.7.0'
    }
  }
}
Niklas 提问于2021-10-26
#8楼
得票数 6

这个崩溃问题通过 : 实现 'androidx.work:work-runtime:2.7.1' 得到了解决。

Benoit Canonne 提问于2021-12-07
#9楼
得票数 6

如果你让你的应用程序在android 12中运行,有一个新的PendingIntent mutability标志。如果你不希望你的PendingIntent被突变,请使用

爪哇岛

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是静音的,请使用以下方法。

爪哇岛

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'
Rehan Khan 提问于2022-03-17
从逻辑上讲,如果我们之前使用的是标志UPDATE_CURRENT,我们是不是应该使用MUTABLE标志?我们显然希望有一个可更新/可改变的待定意图。相应地,如果我们使用了标志 CANCEL_CURRENT,就不应该使用 IMMUTABLE?我不明白为什么要使用 UPDATE_CURRENT 和 IMMUTABLE 标志,它们不是互相矛盾的吗?qkx 2022-10-05
#10楼
得票数 5

由于我的代码中有四个不同的PendingIntents,我开始在所有这些PendingIntents中添加FLAG_IMMUTABLE。在花了很多时间分析了我的4个Intents之后,我突然意识到问题可能来自我的一个库。

在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错误

j3App 提问于2022-02-02
#11楼
得票数 5

我有过像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)
            )
Vasily Kabunov 提问于2022-03-10
#12楼
得票数 3

这是工作库的问题,即使是最新的版本也受到了影响 2.7.0-alpha04

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

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

Aleksandr 提问于2021-07-20
#13楼
得票数 1

在我的项目中,这句话起作用了

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

Priyank Vyas 提问于2022-04-29
#14楼
得票数 1

这个问题是在你升级你的项目并以安卓12版为目标时出现的,安卓在安卓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'
Codeplayon 提问于2022-05-24
HI,我在Android 12上得到了这个错误,但只有当应用程序处于背景状态时才会出现。我正在设置FLAG_IMMUTABLE,但它仍然崩溃。有什么想法吗?谢谢你。TheLoy 2022-08-25
我也一样。只有在后台时才会崩溃。Marty Miller 2022-09-24
#15楼
得票数 0

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

Nihas Nizar 提问于2022-01-20
#16楼
得票数 0

这是我的用例,在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"

希望这能起作用,祝你有个好心情。

Yogendra 提问于2022-10-02
#17楼
得票数 0

你可以像这样更新待定的意向。

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

你可以将PendingIntent.FLAG_IMMUTABLE与|号一起加入,这样就可以工作了。

kamran 提问于2022-10-14