android - Android 11 MediaStyle 通知崩溃
问题描述
我在我的应用程序中使用了 MediaStyle 通知。在 Android 11 之前它一直运行良好。在 Android 11 上,它会导致 Android UI 崩溃(不仅仅是应用程序,它还会关闭 Android 的 UI)。
应用程序上的logcat没有错误,但Android本身有错误。
fun buildNotificationAsync(sessionToken: MediaSessionCompat.Token): Deferred<Notification> = GlobalScope.async {
if (shouldCreateNowPlayingChannel()) {
createNowPlayingChannel()
}
val controller = MediaControllerCompat(context, sessionToken)
val description = controller.metadata.description
val playbackState = controller.playbackState
val builder = NotificationCompat.Builder(context, NOW_PLAYING_CHANNEL)
// Only add actions for skip back, play/pause, skip forward, based on what's enabled.
var playPauseIndex = 0
if (playbackState.isSkipToPreviousEnabled) {
builder.addAction(skipToPreviousAction)
++playPauseIndex
}
if (playbackState.isRewindEnabled) {
builder.addAction(rewindAction)
++playPauseIndex
}
if (playbackState.isPlaying) {
builder.addAction(pauseAction)
} else if (playbackState.isPlayEnabled) {
builder.addAction(playAction)
}
if (playbackState.isFastForwardEnabled) {
builder.addAction(fastForwardAction)
}
if (playbackState.isSkipToNextEnabled) {
builder.addAction(skipToNextAction)
}
val isHuaweiLollipop = (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP_MR1 ||
Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP) &&
Build.MANUFACTURER.toLowerCase(Locale.getDefault()).contains("huawei")
if (!isHuaweiLollipop) {
val mediaStyle = MediaStyle()
.setCancelButtonIntent(stopPendingIntent)
.setMediaSession(sessionToken)
.setShowActionsInCompactView(playPauseIndex)
.setShowCancelButton(true)
builder.setStyle(mediaStyle)
}
description.iconUri?.let { uri ->
val largeIcon = CoverCache.getInstance().fetchLargeIfNecessary(context, uri)
largeIcon?.let { icon -> builder.setLargeIcon(icon) }
}
return@async builder.setContentIntent(controller.sessionActivity)
.setContentText(description.subtitle)
.setContentTitle(description.title)
.setDeleteIntent(stopPendingIntent)
.setOnlyAlertOnce(true)
.setSmallIcon(R.drawable.ic_stat)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.build()
}
我看到了这个我认为相关的异常:
AndroidRuntime E FATAL EXCEPTION: SysUiBg
E Process: com.android.systemui, PID: 26311
E java.lang.SecurityException: Permission Denial: opening provider androidx.core.content.FileProvider from ProcessRecord{410d665 26311:com.android.systemui/u0a141} (pid=26311, uid=10141) that is not exported from UID 10151
E at android.os.Parcel.createExceptionOrNull(Parcel.java:2373)
E at android.os.Parcel.createException(Parcel.java:2357)
E at android.os.Parcel.readException(Parcel.java:2340)
E at android.os.Parcel.readException(Parcel.java:2282)
E at android.app.IActivityManager$Stub$Proxy.getContentProvider(IActivityManager.java:5702)
E at android.app.ActivityThread.acquireProvider(ActivityThread.java:6813)
E at android.app.ContextImpl$ApplicationContentResolver.acquireUnstableProvider(ContextImpl.java:2930)
E at android.content.ContentResolver.acquireUnstableProvider(ContentResolver.java:2481)
E at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1967)
E at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1921)
E at android.graphics.ImageDecoder$ContentResolverSource.createImageDecoder(ImageDecoder.java:274)
E at android.graphics.ImageDecoder.decodeBitmapImpl(ImageDecoder.java:1862)
E at android.graphics.ImageDecoder.decodeBitmap(ImageDecoder.java:1855)
E at com.android.systemui.media.MediaDataManager.loadBitmapFromUri(MediaDataManager.kt:462)
E at com.android.systemui.media.MediaDataManager.loadBitmapFromUri(MediaDataManager.kt:433)
E at com.android.systemui.media.MediaDataManager.loadMediaDataInBg(MediaDataManager.kt:331)
E at com.android.systemui.media.MediaDataManager.access$loadMediaDataInBg(MediaDataManager.kt:89)
E at com.android.systemui.media.MediaDataManager$loadMediaData$1.run(MediaDataManager.kt:241)
E at android.os.Handler.handleCallback(Handler.java:938)
E at android.os.Handler.dispatchMessage(Handler.java:99)
E at android.os.Looper.loop(Looper.java:223)
E at android.os.HandlerThread.run(HandlerThread.java:67)
E Caused by: android.os.RemoteException: Remote stack trace:
E at com.android.server.am.ActivityManagerService.getContentProviderImpl(ActivityManagerService.java:7155)
E at com.android.server.am.ActivityManagerService.getContentProvider(ActivityManagerService.java:7594)
E at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:2381)
E at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2883)
E at android.os.Binder.execTransactInternal(Binder.java:1159)
如果我删除设置小图标的构建器的行,它可以正常工作(但这会使通知只是一个没有媒体样式的普通通知)。您会注意到例外情况是缺少从文件提供程序获取某些内容的权限,但通知中没有使用类似的内容。
解决方案
我发现了这个问题。由于这是一个 MediaStyle,我们设置了 MediaSession,会话可以访问 MediaMetadataCompat 项。为了构建这些项目,我们有:
val builder = MediaMetadataCompat.Builder()
.putString(MediaMetadataCompat.METADATA_KEY_TITLE, doc.title)
.putString(MediaMetadataCompat.METADATA_KEY_AUTHOR, doc.author ?: "Unknown")
.putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID, doc.documentId)
.putString(MediaMetadataCompat.METADATA_KEY_ALBUM, folders.firstOrNull { it.folderId == doc.folderId }?.folderName)
.putString(MediaMetadataCompat.METADATA_KEY_GENRE, sourceType?.name ?: "Unknown") // We don't have Genre info, we'll use for the sourceType
.putLong(METADATA_KEY_UAMP_FLAGS, MediaBrowserCompat.MediaItem.FLAG_PLAYABLE.toLong())
if (originalDocumentType != null) {
// We don't have a disc no, so
builder.putLong(MediaMetadataCompat.METADATA_KEY_DISC_NUMBER, originalDocumentType.ordinal.toLong())
}
// we'll use it doc type.
if (icon != null) {
builder.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON_URI, icon.toString())
}
它是设置 Icon uri 的最后一行。那需要许可。在该行上方添加此内容
context.grantUriPermission("com.android.systemui", icon, Intent.FLAG_GRANT_READ_URI_PERMISSION)
现在应用程序运行正常。但是,由于缺少该权限而导致 Android UI 崩溃的事实仍然是一个错误。我希望无法显示图标甚至使应用程序崩溃,但肯定不会使 Android 本身崩溃。
推荐阅读
- postgresql - 执行位图索引扫描到仅索引扫描的原因?
- java - java线程中的sleep方法,它具体暂停了什么?
- java - 循环遍历 ArrayList 并更新属性
- python - 播放音频文件后如何让机器人自动断开连接
- java - 如何在 Java Swing 中实现多个定时器
- r - R包设计:如何将内部函数导出到集群
- c - 如何从文件中获取随机结构?
- jenkins - jenkins 安装 windows 10 “服务登录凭据”
- python - 如何找到最近的兄弟姐妹
- 对于每个
- ?
- python - pandas.read_excel() 在不存在日期列时输出“溢出错误:日期值超出范围”