Files
Obsidian/项目文档/同力/蓝牙音乐/04_播放控制与音频焦点流程.md
2026-11-05 14:35:04 +08:00

197 lines
3.7 KiB
Markdown

# 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 静音/恢复是否真正生效,需要真机验证。