MediaSessionCompat:Targeting S+(31及以上版本)要求在创建PendingIntent时指定FLAG_IMMUTABLE或FLAG_MUTABLE之一
MediaSessionCompat:Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent
我正在尝试将我的应用程序更新到 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.access00(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 class.
中查看
// 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
你们知道我该如何修复这个错误吗?
如果您的应用以 Android12 为目标,您必须指定应用创建的每个 PendingIntent
对象的可变性。
在您的例子中,android.support.v4.media.session.MediaSessionCompat
负责在 MediaSessionCompat
初始化期间创建 PendingItent
。
解法:
幸运的是,MediaSessionCompat
class 还有一个额外的 @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
更新:
感谢转至:
- CommonsWare -> 指出库需要根据 TODO(b/182513352).
进行更新
- Adelino -> For providing release note link where we can see that FLAG_IMMUTABLE is supported in 1.3.0-rc02
在版本 1.3.0 there were new changes in MediaSessionCompat 中,根据 TODO(b/182513352) 评论,我们可以清楚地看到与 Android 12 相关的内容缺失。
在发布新的 androidx.media:media:
之前,使用我提供的解决方法应该可以正常工作。
更新:
我们希望 TODO(b/182513352) 将在即将发布的版本中得到修复。
在那之前,我们可以使用 implementation "androidx.media:media:1.3.0-rc02
" 支持 FLAG_IMMUTABLE
。
如果您没有在任何地方使用 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
Version 1.4.1
August 4, 2021
androidx.media:media:1.4.1 is released. Version 1.4.1 contains these commits.
Bug Fixes
- Fix mutability flag for creating PendingIntent to prevent crash when targeting Android S.
- Fix ClassVerificationFailure for 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-runtime 版本。
如果您没有在您的应用中使用挂起的 Intent,请试试这个。
实施 'androidx.work:work-runtime-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);
}`
- 将以下行添加到 build.gradle(app)
implementation 'androidx.work:work-runtime:2.7.1'
- 将以下权限添加到 Manifest.xml
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
- 修改待定意向如下
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 后更新了您的库,然后错误消失了
我正在尝试将我的应用程序更新到 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.access00(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 class.
中查看
// 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
你们知道我该如何修复这个错误吗?
如果您的应用以 Android12 为目标,您必须指定应用创建的每个 PendingIntent
对象的可变性。
在您的例子中,android.support.v4.media.session.MediaSessionCompat
负责在 MediaSessionCompat
初始化期间创建 PendingItent
。
解法:
幸运的是,MediaSessionCompat
class 还有一个额外的 @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
更新: 感谢转至:
- CommonsWare -> 指出库需要根据 TODO(b/182513352). 进行更新
- Adelino -> For providing release note link where we can see that FLAG_IMMUTABLE is supported in 1.3.0-rc02
在版本 1.3.0 there were new changes in MediaSessionCompat 中,根据 TODO(b/182513352) 评论,我们可以清楚地看到与 Android 12 相关的内容缺失。
在发布新的 androidx.media:media:
之前,使用我提供的解决方法应该可以正常工作。
更新:
我们希望 TODO(b/182513352) 将在即将发布的版本中得到修复。
在那之前,我们可以使用 implementation "androidx.media:media:1.3.0-rc02
" 支持 FLAG_IMMUTABLE
。
如果您没有在任何地方使用 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
Version 1.4.1 August 4, 2021
androidx.media:media:1.4.1 is released. Version 1.4.1 contains these commits.
Bug Fixes
- Fix mutability flag for creating PendingIntent to prevent crash when targeting Android S.
- Fix ClassVerificationFailure for 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-runtime 版本。
如果您没有在您的应用中使用挂起的 Intent,请试试这个。 实施 'androidx.work:work-runtime-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);
}`
- 将以下行添加到 build.gradle(app)
implementation 'androidx.work:work-runtime:2.7.1'
- 将以下权限添加到 Manifest.xml
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
- 修改待定意向如下
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 后更新了您的库,然后错误消失了