MediaSessionCompat: 目标 S + (版本31及以上)要求在创建 PendingInant 时指定 FLAG_IMMUTABLE 或 FLAG_MUTABLE 之一

我正在尝试将我的应用程序升级到 Android SDK 31,但是我在 MediaSessionCompat 上遇到了一个问题。

我有一个 MediaService,它扩展了 MediaBrowserServiceCompat () ,在该服务的方法 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

你们知道怎么修复这个错误吗?

83718 次浏览

如果你的应用针对的是 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)
}

源代码: < a href = “ https://github.com/dautovicharis/problem-media-session-compat”rel = “ norefrer”> https://github.com/dautovicharis/issue-media-session-compat

更新 : 谢谢浏览:

  • CommonsWare -> 用于指出库需要基于 TODO 进行更新(b/182513352)。
  • Adelino -> 提供发布说明链接,其中我们可以看到在 < a href = “ https://developer.android.com/jetpack/androidx/release/media # media-1.3.0-rc02”rel = “ noReferrer”> 1.3.0-rc02中支持 FLAG _ IMMUTABLE

1.3.0版本中,MediaSessionCompat发生了新的变化,我们可以清楚地看到基于 TODO (b/182513352)评论的 Android 12缺少了一些东西。

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

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

如果您没有在任何地方使用 PendingIntent,这个问题可以通过添加或更新这个依赖项来解决

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

这解决了我的问题。

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

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);
}

对于使用 Java 的用户:

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

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

如果您更新到至少1.4.1版本,这个问题现在就应该解决了

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

版本1.4.1 2021年8月4日

Media: 1.4.1已经发布,版本1.4.1包含了这些提交。

修补漏洞

  • 修正了创建 PendingInent 的可变性标志,以防止在针对 Android S 时崩溃。
  • 修复 NotificationCompat.MediaStyle 的分类验证失败。

对我来说,我必须升级

    liteImplementation "com.google.android.gms:play-services-ads:20.4.0"

    liteImplementation "com.google.android.gms:play-services-ads:20.6.0"

显然,play-services-ads: 20.4.0依赖于不支持 sdk 31的 work-running 版本。

如果你没有在你的应用程序中使用挂起的意图,那么试试这个。 实现‘ androidx.work: work-running-ktx: 2.7.0’

Else 如果使用挂起意图,则更改此

pendingIntent = PendingIntent.getActivity(
this,
0, intentToLaunchThisActivityFromNotification,
PendingIntent.FLAG_UPDATE_CURRENT);

致:

   if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
pendingIntent = PendingIntent.getActivity(
this,
0, intentToLaunchThisActivityFromNotification,
PendingIntent.FLAG_IMMUTABLE);
}
else
{
pendingIntent = PendingIntent.getActivity(
this,
0, intentToLaunchThisActivityFromNotification,
PendingIntent.FLAG_UPDATE_CURRENT);
}

或者 C #/Xamarin 安卓:

   PendingIntent pendingIntent = null;
if (Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.S)
{
pendingIntent = PendingIntent.GetActivity(mContext, 0, intent, PendingIntentFlags.Mutable);
}
else
{
pendingIntent = PendingIntent.GetActivity(mContext, 0, intent, PendingIntentFlags.OneShot);
}
  1. 将以下代码行添加到 build.gradle (app)
implementation 'androidx.work:work-runtime:2.7.1'
  1. 向 Manifest.xml 添加以下权限
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
  1. 按以下方式修改挂起的意图

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) { alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, PendingIntent.getBroadcast(getApplicationContext(), 0, alertIntent, PendingIntent.FLAG_MUTABLE)); } else { alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, PendingIntent.getBroadcast(getApplicationContext(), 0, alertIntent, PendingIntent.FLAG_UPDATE_CURRENT)); }

在将 SdkVersion 更改为31之后,我更新了您的库,然后错误消失了

如果使用 java 或者 response-national,那么将其粘贴到 app/build.gradle 中

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

如果使用科特林,然后使用这个

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

使用“挂起意图”时出错

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {


 



pendingIntent = PendingIntent.getActivity(
this,
0, intentToLaunchThisActivityFromNotification,
PendingIntent.FLAG_IMMUTABLE);
}
else
{
pendingIntent = PendingIntent.getActivity(
this,
0, intentToLaunchThisActivityFromNotification,
PendingIntent.FLAG_UPDATE_CURRENT);
}

如果有人仍然面临 android 12的崩溃问题,那么请确保在 AndroidMenifest.xml 中添加以下内容

<activity
...
android:exported="true" // in most cases it is true but based on requirements it can be false also
>




// If using react-native push notifications then make sure to add into it also


<receiver
android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationBootEventReceiver" android:exported="true">
 

//  Similarly
 

<service android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationListenerService" android:exported="true">

使用 Android Version 12或 S 升级应用程序目标,仅使用 PendingInent.FLAG _ MUTABLE 和 PendingInent.FLAG _ IMMUTABLE

int intentFlagType = PendingIntent.FLAG_ONE_SHOT;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
intentFlagType = PendingIntent.FLAG_IMMUTABLE;  // or only use FLAG_MUTABLE >> if it needs to be used with inline replies or bubbles.
}
PendingIntent pendingIntent = PendingIntent.getActivity(context, notificationID, intent, intentFlagType);

这是为我工作->

PendingIntent pendingIntent = PendingIntent.getBroadcast(context, REQUEST_CODE, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);

我在调度调用类中使用了可变的 Flag

alarmMgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmIntent = PendingIntent.getBroadcast(this, 0, new Intent(this, AlarmReceiver.class), PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);

有时候你只需要更新 Android 工作室中的 Gradle 构建工具。只需要升级到最新版本,就可以解决导致我出现这种情况的问题。

要更新到 Gradle 的最新版本,只需点击 Android Studio 右下角显示的 Gradle 更新对话框。

有两个改变要做

  1. 如下所示更新您的工作库依赖项

Def work _ version = “2.7.0”

// (Java only)
implementation "androidx.work:work-runtime:$work_version"


// Kotlin + coroutines
implementation "androidx.work:work-runtime-ktx:$work_version"
  1. 在创建挂起意图时添加 FLAG _ IMMUTABLE

    PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, FLAG_IMMUTABLE);
    

在我的情况下,原因是关于旧版本查克图书馆. 。

我把它从

implementation 'com.readystatesoftware.chuck:library:1.1.0'

到新的实现,如

dependencies {
debugImplementation "com.github.chuckerteam.chucker:library:3.5.2"
releaseImplementation "com.github.chuckerteam.chucker:library-no-op:3.5.2"
}


val client = OkHttpClient.Builder()
.addInterceptor(ChuckerInterceptor(context))
.build()




android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}


// For Kotlin projects add also this line
kotlinOptions.jvmTarget = "1.8"
}

然后崩溃就消失了。

请参阅文档: https://github.com/ChuckerTeam/chucker