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

如何在ExoPlayer播放时添加Android通知栏控制?

实现ExoPlayer通知栏控制步骤

1. 配置通知渠道(Android 8.0+必备)

在MediaPlayerService启动时先创建通知渠道,否则8.0以上系统无法显示通知:

private fun createNotificationChannel() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val channel = NotificationChannel(
            "AUDIO_PLAYER_CHANNEL",
            "音频播放控制",
            NotificationManager.IMPORTANCE_LOW
        ).apply {
            description = "用于音频播放的通知栏控制"
        }
        val notificationManager = getSystemService(NotificationManager::class.java)
        notificationManager.createNotificationChannel(channel)
    }
}

2. 构建MediaStyle通知与控制按钮

编写通知构建方法,使用MediaStyle适配媒体播放场景,添加播放/暂停、关闭按钮:

// 先定义Action常量,放在Service类顶部
const val ACTION_PLAY_PAUSE = "com.your.package.action.PLAY_PAUSE"
const val ACTION_STOP = "com.your.package.action.STOP"

private fun buildPlayerNotification(): Notification {
    // 播放/暂停按钮的PendingIntent
    val playPauseIntent = Intent(this, MediaPlayerService::class.java).apply {
        action = ACTION_PLAY_PAUSE
    }
    val playPausePendingIntent = PendingIntent.getService(
        this,
        0,
        playPauseIntent,
        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
    )

    // 关闭按钮的PendingIntent
    val stopIntent = Intent(this, MediaPlayerService::class.java).apply {
        action = ACTION_STOP
    }
    val stopPendingIntent = PendingIntent.getService(
        this,
        1,
        stopIntent,
        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
    )

    // 根据当前播放状态切换按钮图标
    val playPauseIcon = if (exoPlayer.isPlaying) R.drawable.ic_pause else R.drawable.ic_play
    val playPauseText = if (exoPlayer.isPlaying) "暂停" else "播放"

    // 构建通知
    return NotificationCompat.Builder(this, "AUDIO_PLAYER_CHANNEL")
        .setSmallIcon(R.drawable.ic_audio_player)
        .setContentTitle("当前播放音频")
        .setContentText("音频名称")
        .setStyle(
            androidx.media.app.NotificationCompat.MediaStyle()
                .setShowActionsInCompactView(0, 1) // 紧凑模式下显示前两个按钮
        )
        .addAction(playPauseIcon, playPauseText, playPausePendingIntent)
        .addAction(R.drawable.ic_stop, "停止", stopPendingIntent)
        .setPriority(NotificationCompat.PRIORITY_LOW)
        .build()
}

3. 处理通知按钮的Action逻辑

在MediaPlayerService的onStartCommand中响应按钮点击:

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
    intent?.action?.let { action ->
        when (action) {
            ACTION_PLAY_PAUSE -> {
                if (exoPlayer.isPlaying) exoPlayer.pause() else exoPlayer.play()
                updateNotification()
            }
            ACTION_STOP -> {
                exoPlayer.stop()
                stopForeground(STOP_FOREGROUND_REMOVE)
                stopSelf()
            }
        }
    }
    return START_STICKY
}

private fun updateNotification() {
    val notification = buildPlayerNotification()
    startForeground(1, notification)
}

4. 监听ExoPlayer状态自动更新通知

给ExoPlayer添加状态监听器,播放状态变化时自动刷新通知:

private fun setupPlayerListener() {
    exoPlayer.addListener(object : Player.Listener {
        override fun onPlaybackStateChanged(playbackState: Int) {
            super.onPlaybackStateChanged(playbackState)
            updateNotification()
        }

        override fun onIsPlayingChanged(isPlaying: Boolean) {
            super.onIsPlayingChanged(isPlaying)
            updateNotification()
        }
    })
}

5. 启动前台服务

在初始化ExoPlayer并开始播放时,启动前台服务:

fun startPlaying(audioUri: Uri) {
    // 初始化ExoPlayer逻辑
    exoPlayer.setMediaItem(MediaItem.fromUri(audioUri))
    exoPlayer.prepare()
    exoPlayer.play()

    // 创建渠道+启动前台服务
    createNotificationChannel()
    startForeground(1, buildPlayerNotification())
    setupPlayerListener()
}

关键注意事项

  • 必须将MediaPlayerService设为前台服务,Android 8.0+后台服务无法显示通知,必须调用startForeground
  • PendingIntent的FLAG_IMMUTABLE需适配API 31+,低于该版本可使用FLAG_UPDATE_CURRENT
  • 替换代码中的图标资源为你项目里的播放、暂停、停止图标
  • 若要显示当前音频的标题、歌手信息,可从MediaItem的mediaMetadata中提取后设置到通知的setContentTitle/setContentText中

内容的提问来源于stack exchange,提问作者Andongwisye Mwamengo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 18:45:19