缺少可变性标志:Android 12 带有 NavDeepLinkBuilder 的待处理意图

Lek*_*esh 11 android android-pendingintent android-architecture-navigation android-deep-link android-12

我\xc2\xb4已经开始测试我的应用程序在Android 12上的问题,并且收到了一些关于为主屏幕小部件设置的待处理意图的可变性标志的警告。这些可变性标志现在从 SDK 31 开始是强制性的。在 31 之前,此代码可以工作,但会出现 lint 警告:

\n
val myIntent = Intent(context, MainActivity::class.java)\nval myPendingIntent = PendingIntent.getActivity(context, 0, myIntent, PendingIntent.FLAG_UPDATE_CURRENT )\nmyRemoteViews.setOnClickPendingIntent(R.id.widget_button, myPendingIntent)\n
Run Code Online (Sandbox Code Playgroud)\n

在 Android 12 上,需要添加第二个标志,如下所示:

\n
val myIntent = Intent(context, MainActivity::class.java)\nval myPendingIntent = PendingIntent.getActivity(context, 0, myIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)\nmyRemoteViews.setOnClickPendingIntent(R.id.widget_button, myPendingIntent)\n
Run Code Online (Sandbox Code Playgroud)\n

到目前为止,一切都很好。但是,对于某些小部件操作,不仅需要导航到应用程序,还需要导航到特定片段并添加片段参数。对于这些情况,我\xc2\xb4一直在使用 NavDeepLinkBuilder 创建pendingIntent\n https://developer.android.google.cn/reference/kotlin/androidx/navigation/NavDeepLinkBuilder

\n
val myPendingIntent = NavDeepLinkBuilder(context)\n        .setGraph(R.navigation.nav_main)\n        .setDestination(R.id.myFragment)\n        .setArguments(\n            myFragment.bundle(myArgs)\n        )\n        .createPendingIntent()\nmyRemoteViews.setOnClickPendingIntent(R.id.widget_button, myPendingIntent)\n
Run Code Online (Sandbox Code Playgroud)\n

在您将构建目标设置为 sdk 31 并在 Android 12(模拟器)上构建之前,此方法非常有效。在这种情况下,它会在使用以下堆栈跟踪创建小部件时崩溃:

\n
   2021-11-03 17:41:27.792 20309-20309/com.package.debug E/AndroidRuntime: FATAL EXCEPTION: main\n    Process: com.package.debug, PID: 20309\n    java.lang.RuntimeException: Unable to start receiver com.package.widgets.mywidget.ui.MyWidgetProvider: java.lang.IllegalArgumentException: com.package.debug: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.\n    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.\n        at android.app.ActivityThread.handleReceiver(ActivityThread.java:4321)\n        at android.app.ActivityThread.access$1600(ActivityThread.java:247)\n        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2068)\n        at android.os.Handler.dispatchMessage(Handler.java:106)\n        at android.os.Looper.loopOnce(Looper.java:201)\n        at android.os.Looper.loop(Looper.java:288)\n        at android.app.ActivityThread.main(ActivityThread.java:7842)\n        at java.lang.reflect.Method.invoke(Native Method)\n        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)\n        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)\n     Caused by: java.lang.IllegalArgumentException: com.package.debug: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.\n    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.\n        at android.app.PendingIntent.checkFlags(PendingIntent.java:375)\n        at android.app.PendingIntent.getActivitiesAsUser(PendingIntent.java:593)\n        at android.app.PendingIntent.getActivities(PendingIntent.java:575)\n        at androidx.core.app.TaskStackBuilder.getPendingIntent(TaskStackBuilder.java:341)\n        at androidx.core.app.TaskStackBuilder.getPendingIntent(TaskStackBuilder.java:312)\n        at androidx.navigation.NavDeepLinkBuilder.createPendingIntent(NavDeepLinkBuilder.java:260)\n        at com.mypackage.widgets.listwidget.ui.ListWidgetProvider.buildRemoteViews(ListWidgetProvider.kt:91)\n        at com.mypackage.widgets.listwidget.ui.ListWidgetProvider.updateListWidget(ListWidgetProvider.kt:44)\n        at com.mypackage.widgets.listwidget.ui.ListWidgetProvider.onUpdate(ListWidgetProvider.kt:39)\n        at android.appwidget.AppWidgetProvider.onReceive(AppWidgetProvider.java:66)\n        at com.mypackage.widgets.listwidget.ui.ListWidgetProvider.onReceive(ListWidgetProvider.kt:169)\n        at android.app.ActivityThread.handleReceiver(ActivityThread.java:4312)\n            ... 9 more\n
Run Code Online (Sandbox Code Playgroud)\n

所以问题是:在使用 NavDeepLinkBuilder 构建待处理意图时如何设置强制可变性标志?我在 NavDeepLinkBuilder 的文档中找不到任何相关信息。像第二个代码片段一样设置挂起的意图是可能的,我可以使用意图操作或额外的来设置“地址”以到达所需的片段,但我失去了将捆绑参数发送到片段本身的可能性。感谢所有有关如何解决此问题的意见。

\n

ian*_*ake 15

根据Navigation 2.4.0-alpha04 发行说明

NavDeepLinkBuilder现在添加PendingIntent.FLAG_IMMUTABLEPendingIntent返回的 中createPendingIntent(),确保此 API 在面向 Android 12 时按预期工作。( If8c52 )

如果您想要修复此问题,则需要升级到 Navigation 2.4.0-alpha04 或更高版本(当前为 2.4.0-beta01)。

  • 导航版本 2.4.0+ 包括多个 backstack。所以,我无法使用这个最新版本。如何在不更新到最新版本的情况下修复此崩溃,或者如何在最新版本中停止多个 backstack? (2认同)

小智 6

如果您在升级到新版本后遇到错误。您可以像这样创建PendingIntent

NavDeepLinkBuilder(context)
    .createTaskStackBuilder()
    .getPendingIntent(
        RequestCode,
        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
    )
Run Code Online (Sandbox Code Playgroud)