I'm using a MediaStyle Notification in my app. Its been working fine until Android 11. On Android 11 it crashes the Android UI (not just the app, it takes down Android's UI).
There are no error in logcat on the app, but there are errors from Android itself.
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()
}
I see this exception that I think is related:
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)
If I remove the line of the builder that sets the small icon, it works fine (but that makes the notification just a plain notification without the media style). You'll note the exception is about lack for permission for fetching something from a file provider, but nothing in the notification uses anything like that.