Android 13前台服务通知METADATA_KEY_ALBUM_ART重叠问题求助
问题:Android 13前台服务通知位图重叠
升级Pixel设备到Android 13后,更新前台服务通知时出现专辑封面位图重叠——旧封面不会被清除,与新封面叠加显示。
相关代码
private fun refreshNotification() { val sounds = // code if (sounds.isEmpty()) { if (!audioFocusTakenBackground) { stopForegroundService() } return } else { val item = // code val icon = // code if (icon != null && icon.isNotEmpty()) { val loader = this@SoundPlayerService.imageLoader val req = ImageRequest.Builder(this@SoundPlayerService) .data(icon) .target { result -> val bitmap = (result as BitmapDrawable).bitmap buildNotification(bitmap, item) } .build() loader.enqueue(req) } else { buildNotification(null, item) } } } private fun buildNotification(imageBitmap: Bitmap?, item: MediaItem){ val builder = NotificationCompat.Builder(this, CHANNEL_ID).apply { val name: String = // code // update session metadata mediaSession.isActive = true if (imageBitmap != null) { mediaSession.setMetadata( MediaMetadataCompat.Builder() .putBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART, imageBitmap) .putString(MediaMetadata.METADATA_KEY_TITLE, name) .putString(MediaMetadata.METADATA_KEY_ARTIST, "Artist") .build() ) } else { mediaSession.setMetadata( MediaMetadataCompat.Builder() .putString(MediaMetadata.METADATA_KEY_TITLE, name) .putString(MediaMetadata.METADATA_KEY_ARTIST, "Artist") .build() ) } setVisibility(NotificationCompat.VISIBILITY_PUBLIC) setContentTitle(getString(R.string.action_now_playing)) setContentText(name) setSmallIcon(R.drawable.ic_icon_small) setContentIntent(relaunchPendingIntent()) setSilent(true) setCategory(NotificationCompat.CATEGORY_SERVICE) setAutoCancel(false) color = this@SoundPlayerService.getColor(R.color.magenta) addAction(NotificationCompat.Action(R.drawable.ic_playbar_stop, getString(R.string.action_stop), stopIntent)) setStyle( androidx.media.app.NotificationCompat.MediaStyle() .setShowActionsInCompactView(0) .setMediaSession(mediaSession.sessionToken) .setShowCancelButton(true) .setCancelButtonIntent(stopIntent) ) } if (isForegroundActive){ updateNotification(builder) } else { startForegroundApp(builder) } } private fun updateNotification(builder: NotificationCompat.Builder){ Timber.i("UPDATE FOREGROUND SERVICE") val notificationManager: NotificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager notificationManager.notify(ONGOING_NOTIFICATION_ID, builder.build()); } private fun startForegroundApp(builder: NotificationCompat.Builder){ if (!audioFocusTakenBackground && Application.instance.isAppInForeground && !isForegroundActive) { isForegroundActive = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { startForeground( ONGOING_NOTIFICATION_ID, builder.build(), ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK ) true } else { startForeground( ONGOING_NOTIFICATION_ID, builder.build() ) true } } } private fun stopForegroundService(){ isForegroundActive = false stopForeground(true) }
执行流程
- 调用
refreshNotification方法,尝试下载可用图片 - 从
refreshNotification中调用buildNotification方法 - 根据前台服务是否已启动,选择启动服务或更新通知
已尝试设置setLargeIcon(bitmap),问题依旧。
解决办法
1. 强制清空MediaSession元数据
Android 13的MediaSession元数据缓存机制可能导致旧Bitmap未被清除,更新元数据前先调用clear()清空所有原有元数据:
if (imageBitmap != null) { mediaSession.setMetadata( MediaMetadataCompat.Builder() .clear() // 清空原有元数据 .putBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART, imageBitmap) .putString(MediaMetadata.METADATA_KEY_TITLE, name) .putString(MediaMetadata.METADATA_KEY_ARTIST, "Artist") .build() ) } else { mediaSession.setMetadata( MediaMetadataCompat.Builder() .clear() // 清空原有元数据 .putString(MediaMetadata.METADATA_KEY_TITLE, name) .putString(MediaMetadata.METADATA_KEY_ARTIST, "Artist") .build() ) }
2. 确保每次更新都创建全新的MediaStyle实例
避免复用MediaStyle对象,每次构建通知时都创建新的MediaStyle实例(你的代码已实现,但需确认无外部复用情况):
setStyle( androidx.media.app.NotificationCompat.MediaStyle() .setShowActionsInCompactView(0) .setMediaSession(mediaSession.sessionToken) .setShowCancelButton(true) .setCancelButtonIntent(stopIntent) )
3. 处理Bitmap实例,避免缓存复用
对下载的Bitmap进行拷贝,生成全新实例后再传入通知:
val req = ImageRequest.Builder(this@SoundPlayerService) .data(icon) .target { result -> val originalBitmap = (result as BitmapDrawable).bitmap // 拷贝生成新Bitmap实例 val newBitmap = originalBitmap.copy(originalBitmap.config, true) buildNotification(newBitmap, item) } .build()
同时在buildNotification中同步设置setLargeIcon(newBitmap)和MediaMetadata中的专辑封面。
4. 临时方案:重启前台服务
如果上述方法无效,可尝试先停止前台服务再重新启动,强制清除旧通知:
private fun updateNotification(builder: NotificationCompat.Builder){ Timber.i("UPDATE FOREGROUND SERVICE") // 停止前台但不清除通知 stopForeground(false) // 重新启动前台服务 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { startForeground(ONGOING_NOTIFICATION_ID, builder.build(), ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK) } else { startForeground(ONGOING_NOTIFICATION_ID, builder.build()) } }
此方法可能导致通知短暂闪烁,但能有效解决重叠问题。
内容的提问来源于stack exchange,提问作者brettywhite
相关产品推荐
相关产品推荐

