【问题标题】:MediaSessionCompat:Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntentMediaSessionCompat:Targeting S+(版本 31 及更高版本)要求在创建 PendingIntent 时指定 FLAG_IMMUTABLE 或 FLAG_MUTABLE 之一
【发布时间】:2021-09-29 01:37:52
【问题描述】:

我正在尝试将我的应用程序更新到 Android SDK 31,但我遇到了 MediaSessionCompat 问题。

我有一个扩展 MediaBrowserServiceCompat() 的 MediaService,并在该服务的 onCreate 方法中初始化 MediaSessionCompat。

override fun onCreate() {
  super.onCreate()
  mediaSession = MediaSessionCompat(this, TAG).apply {
    setCallback(mediaSessionCallback)
    isActive = true
  }
...

但是我遇到了以下错误

java.lang.RuntimeException: Unable to create service com.radio.core.service.MediaService: java.lang.IllegalArgumentException: com.xxx.xxx: Targeting S+ (version 31 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.ActivityThread.handleCreateService(ActivityThread.java:4498)
        at android.app.ActivityThread.access$1500(ActivityThread.java:250)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2064)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loopOnce(Looper.java:201)
        at android.os.Looper.loop(Looper.java:288)
        at android.app.ActivityThread.main(ActivityThread.java:7829)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:982)
     Caused by: java.lang.IllegalArgumentException: com.xxx.xxx: Targeting S+ (version 31 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:375)
        at android.app.PendingIntent.getBroadcastAsUser(PendingIntent.java:645)
        at android.app.PendingIntent.getBroadcast(PendingIntent.java:632)
        at android.support.v4.media.session.MediaSessionCompat.<init>(MediaSessionCompat.java:567)
        at android.support.v4.media.session.MediaSessionCompat.<init>(MediaSessionCompat.java:537)
        at android.support.v4.media.session.MediaSessionCompat.<init>(MediaSessionCompat.java:501)
        at android.support.v4.media.session.MediaSessionCompat.<init>(MediaSessionCompat.java:475)
        at com.radio.core.service.MediaService.onCreate(MediaService.kt:63)
        at android.app.ActivityThread.handleCreateService(ActivityThread.java:4485)
            ... 9 more

我正在使用最新版本的媒体库 ("androidx.media:media:1.4.0"),它能够处理来自 Andriod "S"" 的这一要求。正如在MediaSessionCompact.java 类。


// TODO(b/182513352): Use PendingIntent.FLAG_MUTABLE instead from S.
/**
 * @hide
 */
@RestrictTo(LIBRARY)
public static final int PENDING_INTENT_FLAG_MUTABLE = 
  Build.VERSION.CODENAME.equals("S") ? 0x02000000 : 0;

...

if (mbrComponent != null && mbrIntent == null) {
  // construct a PendingIntent for the media button
  Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
  // the associated intent will be handled by the component being registered
  mediaButtonIntent.setComponent(mbrComponent);
  mbrIntent = PendingIntent.getBroadcast(context,
    0/* requestCode, ignored */, mediaButtonIntent,
    PENDING_INTENT_FLAG_MUTABLE);
}

演示问题的源代码 - https://github.com/adelinolobao/issue-media-session-compat

你们知道我该如何解决这个错误吗?

【问题讨论】:

标签: java android android-studio kotlin android-mediaplayer


【解决方案1】:

如果您不在任何地方使用PendingIntent。通过添加或更新此依赖项可能会解决此问题

    // required to avoid crash on Android 12 API 31
    implementation 'androidx.work:work-runtime-ktx:2.7.0'

这解决了我的问题。

【讨论】:

  • 获奖答案!也解决了我的问题。看起来它已在 v-alpha-02 中修复:developer.android.com/jetpack/androidx/releases/…
  • 进行此更改后,Pending Intent 标志错误消失了,但现在面临以下错误:Caused by: java.lang.ClassNotFoundException: Didn't find class "androidx.work.impl.WorkManagerInitializer"
  • @SonuSourav 您可能与您正在使用的另一个库发生冲突
  • 奇怪的是,代码中的一个bug通过集成库解决了。或许我们正朝着错误的方向发展……
  • 您可以在项目的终端中执行./gradlew app:dependencies 并发现包含work-runtime 和旧版本的依赖项。然后,您可以尝试升级该依赖项以正确地做事
【解决方案2】:

解决了这个错误 刚刚用于 Android 版本 12 或 S 的 PendingIntent.FLAG_MUTABLE

PendingIntent pendingIntent = null;
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
        pendingIntent = PendingIntent.getActivity
               (this, 0, notificationIntent, PendingIntent.FLAG_MUTABLE);
    }
    else
    {
         pendingIntent = PendingIntent.getActivity
                (this, 0, notificationIntent, PendingIntent.FLAG_ONE_SHOT);
    }

【讨论】:

  • 哇!多么棒的解决方案!就一个问题。您打算如何将其集成到 MediaSessionCompat 初始化中?你知道,就像问的问题一样。
【解决方案3】:

如果您的应用面向 Android 12,则必须指定应用创建的每个 PendingIntent 对象的可变性。

在您的情况下,android.support.v4.media.session.MediaSessionCompat 负责在 MediaSessionCompat 的初始化期间创建 PendingItent

解决方案: 幸运的是,MediaSessionCompat 类还有一个额外的@constructor,因此我们可以将pendingItent 作为参数传递。 如果我们为component 参数传递null,它将在库中初始化。

override fun onCreate() {
        super.onCreate()

        val mediaButtonIntent = Intent(Intent.ACTION_MEDIA_BUTTON)
        val pendingItent = PendingIntent.getBroadcast(
            baseContext,
            0, mediaButtonIntent,
            PendingIntent.FLAG_IMMUTABLE
        )

        mediaSession = MediaSessionCompat(baseContext, TAG, null, pendingItent).also {
            it.isActive = true
        }

        sessionToken = mediaSession.sessionToken
        packageValidator = PackageValidator(this@MediaService, R.xml.allowed_media_browser_callers)
    }

源码:https://github.com/dautovicharis/issue-media-session-compat

更新: 感谢:

1.3.0 版本中,MediaSessionCompat 发生了新变化,根据 TODO(b/182513352) 评论,我们可以清楚地看到与 Android 12 相关的某些内容缺失。

在新的androidx.media:media: 发布之前,使用我提供的解决方法应该可以正常工作。

更新: 我们希望TODO(b/182513352) 将在即将发布的版本中得到修复。 在此之前,我们可以使用支持FLAG_IMMUTABLEimplementation "androidx.media:media:1.3.0-rc02"。

【讨论】:

  • 我知道那个构造函数,但问题是我正在使用媒体组件中的更多方法,这些方法会因这个问题而崩溃。例如,MediaButtonReceiver.buildMediaButtonPendingIntent 返回一个带有错误标志的 PendingIntent,我们无法更改它。我认为目前 androidx.media 库在 Android 31 中不可用,我认为这很奇怪,因为大多数音频应用程序都依赖这个库
  • 您是否尝试过使用支持 FLAG_IMMUTABLE 的 1.3.0-rc2 版本?
  • @Adelino 我已经测试了实现“androidx.media:media:1.3.0-rc02”并且它不会崩溃,所以也许选择在新版本之前使用这个版本。
  • 现在我感觉很愚蠢,因为这就是解决方案:|奇怪的是为什么他们没有在最新版本中包含 1.3.0-rc02 的更改
  • 新版本“androidx.media:media:1.4.1”在Android SDK 31 developer.android.com/jetpack/androidx/releases/…中正常工作
【解决方案4】:

对于那些使用 Java 的人:

将以下行添加到您的build.gradle(app) 下的dependencies

dependencies {
  // ...
  implementation 'androidx.work:work-runtime:2.7.1'
}

【讨论】:

    【解决方案5】:

    如果您更新到至少 1.4.1 版本,现在应该可以解决此问题

    https://developer.android.com/jetpack/androidx/releases/media#media-1.4.1

    版本 1.4.1 2021 年 8 月 4 日

    androidx.media:media:1.4.1 已发布。 1.4.1 版包含这些提交。

    错误修复

    • 修复了创建 PendingIntent 的可变性标志,以防止在针对 Android S 时崩溃。
    • 修复 NotificationCompat.MediaStyle 的 ClassVerificationFailure。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-10-05
      • 2023-01-01
      • 2022-01-08
      • 1970-01-01
      • 1970-01-01
      • 2021-09-14
      • 1970-01-01
      • 2023-01-30
      相关资源
      最近更新 更多