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

Android 13+无需addAction,基于PlaybackState实现通知控制按钮

基于PlaybackState实现Android13+ MediaStyle通知控制按钮

核心逻辑

Android13及以上版本中,系统会直接从MediaSession绑定的PlaybackState自动生成MediaStyle通知的操作按钮,无需手动调用addAction。要让按钮正常工作,必须满足三个关键条件:通知绑定MediaSession的sessionToken、PlaybackState正确配置操作项、状态变更时同步更新PlaybackState和通知。


具体实现步骤

1. 绑定通知与MediaSession

构建MediaStyle通知时,必须调用setMediaSession(mediaSession.sessionToken),这是系统获取PlaybackState操作配置的核心入口:

fun buildNotification(playbackState: PlaybackStateCompat): Notification {
    val notificationBuilder = NotificationCompat.Builder(this, PLAYBACK_CHANNEL_ID)
        .setContentTitle("当前播放曲目")
        .setContentText("艺术家名称")
        .setSmallIcon(R.drawable.ic_notify_play)
        .setStyle(
            androidx.media.app.NotificationCompat.MediaStyle()
                .setMediaSession(mediaSession.sessionToken) // 关键:关联MediaSession
                .setShowActionsInCompactView(0, 1, 2) // 紧凑模式固定显示前3个操作
        )
        .setPriority(NotificationCompat.PRIORITY_HIGH)
    
    // 无需手动addAction,系统将自动从PlaybackState加载按钮
    return notificationBuilder.build()
}

2. 正确配置PlaybackState的操作项

根据当前播放状态动态配置支持的操作,系统会自动匹配显示对应的按钮(比如播放中显示暂停,暂停时显示播放)。同时通过addCustomAction添加自定义操作:

private fun updatePlaybackState(state: Int) {
    val stateBuilder = PlaybackStateCompat.Builder()
        .setState(
            state,
            exoPlayer.currentPosition,
            exoPlayer.playbackParameters.speed
        )
        // 添加自定义关闭按钮
        .addCustomAction("Close", "关闭", R.drawable.btn_close)
        // 根据当前状态筛选可用操作,避免无效按钮显示
        .setActions(
            when(state) {
                PlaybackStateCompat.STATE_PLAYING -> {
                    PlaybackStateCompat.ACTION_PAUSE or
                    PlaybackStateCompat.ACTION_STOP or
                    PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS or
                    PlaybackStateCompat.ACTION_SKIP_TO_NEXT or
                    PlaybackStateCompat.ACTION_SEEK_TO
                }
                PlaybackStateCompat.STATE_PAUSED -> {
                    PlaybackStateCompat.ACTION_PLAY or
                    PlaybackStateCompat.ACTION_STOP or
                    PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS or
                    PlaybackStateCompat.ACTION_SKIP_TO_NEXT or
                    PlaybackStateCompat.ACTION_SEEK_TO
                }
                else -> {
                    PlaybackStateCompat.ACTION_PLAY or
                    PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS or
                    PlaybackStateCompat.ACTION_SKIP_TO_NEXT
                }
            }
        )
    mediaSession.setPlaybackState(stateBuilder.build())
}

3. 状态变更时同步更新通知

在MediaSession回调中,每次播放状态改变后,需更新PlaybackState并重新发布通知:

override fun onPlay() {
    exoPlayer.playWhenReady = true
    updatePlaybackState(PlaybackStateCompat.STATE_PLAYING)
    startForeground(PLAYBACK_NOTIFICATION_ID, buildNotification(mediaSession.playbackState))
}

override fun onPause() {
    exoPlayer.playWhenReady = false
    updatePlaybackState(PlaybackStateCompat.STATE_PAUSED)
    startForeground(PLAYBACK_NOTIFICATION_ID, buildNotification(mediaSession.playbackState))
}

// 处理自定义按钮逻辑
override fun onCustomAction(action: String?, extras: Bundle?) {
    if ("Close" == action) {
        updatePlaybackState(PlaybackStateCompat.STATE_STOPPED)
        stopForeground(STOP_FOREGROUND_REMOVE)
    }
}

常见问题排查

  • 确认已申请Android13+的POST_NOTIFICATIONS权限,且通知渠道创建正常
  • 检查MediaSession是否设置了FLAG_HANDLES_TRANSPORT_CONTROLS标志,确保能响应系统操作
  • 自定义按钮图标建议使用纯色矢量图,避免在不同系统版本中显示异常

内容的提问来源于stack exchange,提问作者이경준

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 19:38:08