Android13+ Media3:蓝牙指令响应与通知自定义图标问题
Android 13+ 基于AndroidX Media实现蓝牙耳机指令响应与自定义通知图标方案
核心解决思路
不要移除默认的seek_to_previous/seek_to_next指令(这是蓝牙耳机指令触发的关键),而是通过自定义通知操作按钮替换系统默认图标,同时在指令回调中实现快退/快进逻辑。
具体实现步骤
保留默认指令的可用状态
在ForwardingPlayer和PlaybackState中保留ACTION_SEEK_TO_PREVIOUS和ACTION_SEEK_TO_NEXT的可用状态,确保蓝牙耳机发送的指令能被系统捕获并传递到你的回调:// 构建PlaybackState时添加指令 val playbackState = PlaybackStateCompat.Builder() .setState(currentState, currentPosition, playbackSpeed) .addAction(PlaybackStateCompat.ACTION_SEEK_TO_PREVIOUS) .addAction(PlaybackStateCompat.ACTION_SEEK_TO_NEXT) .addAction(PlaybackStateCompat.ACTION_PLAY_PAUSE) // 其他必要指令 .build() mediaSession.setPlaybackState(playbackState)创建自定义通知操作按钮
用你的自定义Drawable图标创建通知Action,关联到默认的seek指令Intent,这样点击按钮和蓝牙耳机指令都会触发相同的逻辑:// 自定义快退按钮 val rewindAction = Notification.Action.Builder( R.drawable.ic_custom_rewind, // 你的自定义快退图标 "快退", MediaButtonReceiver.buildMediaButtonPendingIntent( context, PlaybackStateCompat.ACTION_SEEK_TO_PREVIOUS ) ).build() // 自定义快进按钮 val forwardAction = Notification.Action.Builder( R.drawable.ic_custom_forward, // 你的自定义快进图标 "快进", MediaButtonReceiver.buildMediaButtonPendingIntent( context, PlaybackStateCompat.ACTION_SEEK_TO_NEXT ) ).build()构建带自定义按钮的媒体通知
将自定义Action添加到通知中,并通过MediaStyle设置显示这些按钮,系统会优先使用你自定义的图标:val mediaNotification = NotificationCompat.Builder(context, MEDIA_CHANNEL_ID) .setContentTitle(currentMediaTitle) .setContentText(currentMediaSubtitle) .setSmallIcon(R.drawable.ic_notification) .addAction(rewindAction) .addAction(playPauseAction) // 播放/暂停按钮 .addAction(forwardAction) .setStyle(MediaStyle() .setMediaSession(mediaSession.sessionToken) .setShowActionsInCompactView(0, 1, 2) // 指定要显示的按钮索引 ) .setPriority(NotificationCompat.PRIORITY_HIGH) .build() // 更新通知 mediaSession.setSessionActivity(pendingIntent) notificationManager.notify(NOTIFICATION_ID, mediaNotification)实现快退/快进逻辑
在MediaSession.Callback中重写对应方法,实现快退/快进而非切换媒体项:class MediaSessionCallback : MediaSessionCompat.Callback() { override fun onSeekToPrevious() { // 执行快退逻辑,比如倒退10秒 val newPosition = max(0, currentPosition - 10000) player.seekTo(newPosition) } override fun onSeekToNext() { // 执行快进逻辑,比如前进10秒 val newPosition = min(player.duration, currentPosition + 10000) player.seekTo(newPosition) } // 其他回调方法... }
关键说明
- 保留默认seek指令是为了让蓝牙耳机的系统级指令能正常触发回调,不能移除;
- 自定义通知Action关联默认指令的Intent,保证按钮点击和蓝牙指令的逻辑一致性;
- 系统媒体通知会优先使用你添加的自定义Action图标,不会再显示默认的切换图标。
内容的提问来源于stack exchange,提问作者dabluck
相关产品推荐
相关产品推荐

