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,提问作者이경준
相关产品推荐
相关产品推荐

