# 04_播放控制与音频焦点流程 ## 页面按钮控制流程 ```text 1. 用户点击蓝牙音乐页面按钮 ↓ 2. BluetoothMusicActivity.onClick() ↓ 3. 根据按钮 ID 判断动作 ↓ 4. 调用 BtMusicViewModel ↓ 5. BtMusicViewModel 调用 BtMusicControlManager ↓ 6. BtMusicControlManager 调用 BtMusicManager ↓ 7. BtMusicManager 调用 BluetoothAvrcpClient ↓ 8. BluetoothAvrcpClient 调用 MediaController.TransportControls ↓ 9. 手机音乐 App 响应 ``` ## 页面按钮映射 | 控件 ID | 方法 | 最终 AVRCP 控制 | |---|---|---| | `iv_bt_music_pre` | `preBtMusic()` | `skipToPrevious()` | | `iv_bt_music_state` | `playBtMusic()` / `pauseBtMusic()` | `play()` / `pause()` | | `iv_bt_music_next` | `nextBtMusic()` | `skipToNext()` | ## 播放命令详细链路 ```text BluetoothMusicActivity.onClick() ↓ mViewModel.playBtMusic() ↓ BtMusicViewModel.playBtMusic() ↓ BtMusicControlManager.playBtMusic() ↓ BtMusicManager.requestFocus() ↓ BtMusicAudioManager.requestAudioFocus() ↓ BtMusicManager.playBtMusic() ↓ BluetoothAvrcpClient.play() ↓ TransportControls.play() ``` ## 暂停命令详细链路 ```text BluetoothMusicActivity.onClick() ↓ mViewModel.pauseBtMusic() ↓ BtMusicViewModel.pauseBtMusic() ↓ BtMusicControlManager.pauseBtMusic() ↓ BtMusicManager.pauseBtMusic() ↓ BluetoothAvrcpClient.pause() ↓ TransportControls.pause() ``` ## 切歌命令详细链路 ```text 上一曲: BluetoothMusicActivity ↓ BtMusicViewModel.preBtMusic() ↓ BtMusicControlManager.preBtMusic() ↓ BtMusicManager.preBtMusic() ↓ BluetoothAvrcpClient.previous() ↓ TransportControls.skipToPrevious() 下一曲: BluetoothMusicActivity ↓ BtMusicViewModel.nextBtMusic() ↓ BtMusicControlManager.nextBtMusic() ↓ BtMusicManager.nextBtMusic() ↓ BluetoothAvrcpClient.next() ↓ TransportControls.skipToNext() ``` ## 音频焦点是什么 ```text 音频焦点 = 当前谁有资格出声 车机里可能同时有: 蓝牙音乐 收音机 USB 音乐 视频 导航播报 蓝牙电话 所以蓝牙音乐播放前必须申请焦点。 ``` ## 焦点申请流程 ```text 1. 用户点击播放 ↓ 2. BtMusicManager.requestFocus() ↓ 3. BtMusicAudioManager.requestAudioFocus() ↓ 4. AudioManager.requestAudioFocus() ↓ 5. 如果返回 AUDIOFOCUS_REQUEST_GRANTED ↓ 6. setA2dpUnMute() ↓ 7. isFocus = true ↓ 8. setMediaButtonEvent() ↓ 9. 允许执行 AVRCP play() ``` ## 焦点变化处理 | 焦点变化 | 处理 | |---|---| | `AUDIOFOCUS_GAIN` | 恢复 A2DP 出声,必要时恢复播放,通知语音当前是蓝牙音乐。 | | `AUDIOFOCUS_LOSS` | 释放焦点,暂停蓝牙音乐,清空 Launcher 蓝牙音乐信息。 | | `AUDIOFOCUS_LOSS_TRANSIENT` | 临时失焦,A2DP 静音,暂停蓝牙音乐。 | | `AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK` | 降低蓝牙音乐音量。 | ## 失焦流程 ```text 1. 其他音源抢焦点 ↓ 2. BtMusicAudioManager.mAudioFocusListener.onAudioFocusChange() ↓ 3. 收到 AUDIOFOCUS_LOSS 或 AUDIOFOCUS_LOSS_TRANSIENT ↓ 4. 记录当前是否正在播放 ↓ 5. setA2dpMute() ↓ 6. BtMusicManager.pauseBtMusic() ↓ 7. 手机音乐暂停 ``` ## 恢复焦点流程 ```text 1. 蓝牙音乐重新获得焦点 ↓ 2. 收到 AUDIOFOCUS_GAIN ↓ 3. isFocus = true ↓ 4. setA2dpUnMute() ↓ 5. 如果 isPlayingLossFocus == true ↓ 6. BtMusicManager.playBtMusic() ↓ 7. 手机音乐恢复播放 ``` ## 注意点 `BluetoothA2dpSinkClient` 中这两个方法底层调用目前被注释: ```text setFluorideAudioTrackGain() setFluorideStreaming() ``` 所以焦点切换时,A2DP 静音/恢复是否真正生效,需要真机验证。