You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Kotlin如何设置全屏通知背景?仿Spotify样式

如何实现类似Spotify/SoundCloud的全屏通知背景?

我想要设置如示例图所示的通知全屏背景,但当前实现的效果如结果图所示。

现有实现尝试

最初我尝试用setLargeIcon来设置背景,但图片显示模糊:

val notification = androidx.core.app.NotificationCompat.Builder(this, CHANNEL_ID)
            .setContentTitle(data.name)
            .setContentText(data.author)
            .setSmallIcon(R.drawable.ic_launcher_foreground)
            .setContentIntent(dataAction.intent)
            .setPriority(androidx.core.app.NotificationCompat.PRIORITY_HIGH)
            .setVisibility(androidx.core.app.NotificationCompat.VISIBILITY_PUBLIC)
            .setColorized(true)
            .setCategory(AUDIO_SERVICE)
            .setOngoing(true)
            .setLargeIcon(largeBitmap)// 尝试用这个设置通知全屏背景
            .setStyle(
                NotificationCompat.MediaStyle().setMediaSession(mediaSessionCompat.sessionToken)
            )
            .addAction(R.drawable.ic_previous, "Previous", dataAction.previous)
            .addAction(R.drawable.ic_pause, "Play", dataAction.play)
            .addAction(R.drawable.ic_next, "Next", dataAction.next)
            .addAction(R.drawable.ic_exit, "Exit", dataAction.exit)
            .build()
startForeground(1, notification)

起初我以为是图片质量问题,但把图片放到ImageView或者用BigPictureStyle测试时,图片显示清晰。我用setLargeIcon是因为这是我找到的唯一能设置通知背景的方法,但实际效果模糊。

自定义布局尝试(Android 12/13)

之后我尝试用自定义布局,但通知直接不显示:

val contentView = RemoteViews(packageName, R.layout.notification_layout)
notification.setStyle(NotificationCompat.DecoratedMediaCustomViewStyle())
notification.setCustomContentView(contentView)

自定义布局文件notification_layout.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/mainLayoutNotification"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="3dp">

    <ImageView
        android:id="@+id/imageBackground"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginEnd="10dp"
        android:src="@drawable/testimg" />

</LinearLayout>

补充信息

我测试了2048x2048分辨率的图片,转换Bitmap的代码:

val withDrawable = BitmapFactory.decodeResource(resources, R.drawable.testimg)

也尝试从音频文件获取内嵌封面:

val path ="/storage/emulated/0/Download/Ahhhhhhh/Glichery - Sea Of Problems.mp3"
val withEmbededImage = getAudioFileAlbumArt(path)

fun getAudioFileAlbumArt(filePath: String): Bitmap? {
    val retriever = MediaMetadataRetriever()

    try {
        retriever.setDataSource(filePath)

        val rawArt = retriever.embeddedPicture
        if (rawArt != null) {
            return BitmapFactory.decodeByteArray(rawArt, 0, rawArt.size)
        }
    } catch (e: Exception) {
        e.printStackTrace()
    } finally {
        retriever.release()
    }
    return null
}

但设置为LargeIcon后背景还是模糊。


解决方案

1. 用MediaStyle原生方法设置背景(推荐)

AndroidX的NotificationCompat.MediaStyle提供了setBackgroundBitmap()方法,这才是设置媒体通知全屏背景的正确方式,setLargeIcon只是设置通知左侧的小图标,并非背景。修改代码如下:

val notification = androidx.core.app.NotificationCompat.Builder(this, CHANNEL_ID)
    .setContentTitle(data.name)
    .setContentText(data.author)
    .setSmallIcon(R.drawable.ic_launcher_foreground)
    .setContentIntent(dataAction.intent)
    .setPriority(NotificationCompat.PRIORITY_HIGH)
    .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
    .setColorized(true)
    .setCategory(NotificationCompat.CATEGORY_TRANSPORT) // 必须用这个分类,系统才会识别为媒体通知
    .setOngoing(true)
    .setStyle(
        NotificationCompat.MediaStyle()
            .setMediaSession(mediaSessionCompat.sessionToken)
            .setBackgroundBitmap(largeBitmap) // 设置全屏背景图
    )
    .addAction(R.drawable.ic_previous, "Previous", dataAction.previous)
    .addAction(R.drawable.ic_pause, "Play", dataAction.play)
    .addAction(R.drawable.ic_next, "Next", dataAction.next)
    .addAction(R.drawable.ic_exit, "Exit", dataAction.exit)
    .build()
startForeground(1, notification)

注意:

  • 背景图推荐使用2:1比例(如1080x540),或高度控制在256dp-400dp之间,避免拉伸模糊。
  • 必须设置CATEGORY_TRANSPORT分类,否则系统不会应用背景样式。

2. 修复自定义布局不显示问题

如果坚持用自定义布局,需调整以下几点:

  • 根布局高度不要用wrap_content,改为固定高度(如256dp):
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/mainLayoutNotification"
        android:layout_width="match_parent"
        android:layout_height="256dp"
        android:padding="3dp">
    
  • 给ImageView添加scaleType避免拉伸:
    <ImageView
        android:id="@+id/imageBackground"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        android:src="@drawable/testimg" />
    
  • 确保smallIcon正确设置,这是通知显示的必要条件。

3. 优化Bitmap解码质量

解码图片时禁止系统自动缩放,保证原始分辨率:

// 解码资源图片
val options = BitmapFactory.Options()
options.inScaled = false
options.inPreferredConfig = Bitmap.Config.ARGB_8888
val withDrawable = BitmapFactory.decodeResource(resources, R.drawable.testimg, options)

// 解码内嵌封面
fun getAudioFileAlbumArt(filePath: String): Bitmap? {
    val retriever = MediaMetadataRetriever()
    try {
        retriever.setDataSource(filePath)
        val rawArt = retriever.embeddedPicture
        if (rawArt != null) {
            val options = BitmapFactory.Options()
            options.inScaled = false
            options.inPreferredConfig = Bitmap.Config.ARGB_8888
            return BitmapFactory.decodeByteArray(rawArt, 0, rawArt.size, options)
        }
    } catch (e: Exception) {
        e.printStackTrace()
    } finally {
        retriever.release()
    }
    return null
}

内容的提问来源于stack exchange,提问作者Nguyễn Minh Khoa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 19:34:50