152 lines
3.3 KiB
Markdown
152 lines
3.3 KiB
Markdown
# 03_AVRCP歌曲信息与播放状态流程
|
|||
|
|
|
||
|
|
## AVRCP 是什么
|
||
|
|
|
||
|
|
```text
|
||
|
|
AVRCP = 蓝牙媒体控制协议
|
||
|
|
|
||
|
|
它负责两类事情:
|
||
|
|
1. 车机控制手机:播放、暂停、上一曲、下一曲
|
||
|
|
2. 手机告诉车机:歌名、歌手、封面、播放状态、进度
|
||
|
|
```
|
||
|
|
|
||
|
|
## MediaBrowser 连接流程
|
||
|
|
|
||
|
|
```text
|
||
|
|
1. BluetoothAvrcpClient.init(context)
|
||
|
|
↓
|
||
|
|
2. initMediaBrowserHelper()
|
||
|
|
↓
|
||
|
|
3. new MediaBrowserClient(context)
|
||
|
|
↓
|
||
|
|
4. MediaBrowserClient 连接系统服务:
|
||
|
|
com.android.bluetooth.avrcpcontroller.BluetoothMediaBrowserService
|
||
|
|
↓
|
||
|
|
5. 连接成功后创建 MediaControllerCompat
|
||
|
|
↓
|
||
|
|
6. 注册 MediaControllerCompat.Callback
|
||
|
|
↓
|
||
|
|
7. 可以接收 metadata 和 playbackState
|
||
|
|
```
|
||
|
|
|
||
|
|
## 歌曲信息流程
|
||
|
|
|
||
|
|
```text
|
||
|
|
1. 手机音乐 App 播放或切歌
|
||
|
|
↓
|
||
|
|
2. 手机通过 AVRCP 上报 metadata
|
||
|
|
↓
|
||
|
|
3. Android 蓝牙服务接收 metadata
|
||
|
|
↓
|
||
|
|
4. MediaBrowserClient.mediaControlCallback.onMetadataChanged()
|
||
|
|
↓
|
||
|
|
5. BluetoothAvrcpClient.callback.onMetadataChanged()
|
||
|
|
↓
|
||
|
|
6. BtMusicManager.onMetadataChanged()
|
||
|
|
↓
|
||
|
|
7. 解析字段:
|
||
|
|
artist
|
||
|
|
title
|
||
|
|
album
|
||
|
|
albumUrl
|
||
|
|
duration
|
||
|
|
↓
|
||
|
|
8. 保存到 MusicInfo
|
||
|
|
↓
|
||
|
|
9. 通知 BtMusicViewModel.onPlayMusicInfo()
|
||
|
|
↓
|
||
|
|
10. mLiveDataMusicInfo.postValue(musicInfo)
|
||
|
|
↓
|
||
|
|
11. BluetoothMusicActivity 更新 UI
|
||
|
|
```
|
||
|
|
|
||
|
|
## 播放状态流程
|
||
|
|
|
||
|
|
```text
|
||
|
|
1. 手机音乐播放状态变化
|
||
|
|
↓
|
||
|
|
2. MediaBrowserClient.onPlaybackStateChanged()
|
||
|
|
↓
|
||
|
|
3. BluetoothAvrcpClient.onPlaybackStateChanged()
|
||
|
|
↓
|
||
|
|
4. BtMusicManager.onPlaybackStateChanged()
|
||
|
|
↓
|
||
|
|
5. 判断:
|
||
|
|
state == PlaybackStateCompat.STATE_PLAYING
|
||
|
|
↓
|
||
|
|
6. 更新 MusicInfo.isPlaying
|
||
|
|
↓
|
||
|
|
7. 更新 MusicInfo.playPosition
|
||
|
|
↓
|
||
|
|
8. 通知 BtMusicViewModel.onPlayMusicState(isPlaying)
|
||
|
|
↓
|
||
|
|
9. BluetoothMusicActivity 更新播放按钮图标
|
||
|
|
```
|
||
|
|
|
||
|
|
## 同步给 Launcher 的流程
|
||
|
|
|
||
|
|
同样的 AVRCP 数据,还会推给桌面卡片。
|
||
|
|
|
||
|
|
```text
|
||
|
|
BluetoothAvrcpClient.onMetadataChanged()
|
||
|
|
↓
|
||
|
|
BtInfoPushManager.sendMusicInfoToLauncher()
|
||
|
|
↓
|
||
|
|
转换为 BtMusicInfo
|
||
|
|
↓
|
||
|
|
DataManager.putObject(BT_MUSIC_INFO, btInfo)
|
||
|
|
↓
|
||
|
|
发送 ACTION_UPDATE_MUSIC_WIDGET
|
||
|
|
↓
|
||
|
|
Launcher 卡片刷新
|
||
|
|
```
|
||
|
|
|
||
|
|
播放状态也是类似:
|
||
|
|
|
||
|
|
```text
|
||
|
|
BluetoothAvrcpClient.onPlaybackStateChanged()
|
||
|
|
↓
|
||
|
|
BtInfoPushManager.sendMusicStateToLauncher()
|
||
|
|
↓
|
||
|
|
DataManager.putObject(BT_MUSIC_INFO, btInfo)
|
||
|
|
↓
|
||
|
|
Launcher 卡片刷新
|
||
|
|
```
|
||
|
|
|
||
|
|
## MusicInfo 字段
|
||
|
|
|
||
|
|
| 字段 | 含义 | 来源 |
|
||
|
|
|---|---|---|
|
||
|
|
| `artist` | 歌手 | `MediaMetadata.METADATA_KEY_ARTIST` |
|
||
|
|
| `title` | 歌曲名 | `MediaMetadata.METADATA_KEY_TITLE` |
|
||
|
|
| `album` | 专辑 | `MediaMetadata.METADATA_KEY_ALBUM` |
|
||
|
|
| `albumUrl` | 封面 | `MediaMetadata.METADATA_KEY_ALBUM_ART_URI` |
|
||
|
|
| `songLen` | 总时长 | `MediaMetadata.METADATA_KEY_DURATION` |
|
||
|
|
| `playPosition` | 当前进度 | `PlaybackStateCompat.getPosition()` |
|
||
|
|
| `isPlaying` | 是否播放 | `PlaybackStateCompat.STATE_PLAYING` |
|
||
|
|
|
||
|
|
## Unknown 处理
|
||
|
|
|
||
|
|
在 `BtMusicManager.onMetadataChanged()` 中:
|
||
|
|
|
||
|
|
```text
|
||
|
|
如果 artist/title/album 为空、unknow、Not Provided
|
||
|
|
↓
|
||
|
|
替换为 strings.xml 中的 unknow 文案
|
||
|
|
```
|
||
|
|
|
||
|
|
在 `BluetoothMusicActivity` 中:
|
||
|
|
|
||
|
|
```text
|
||
|
|
如果 title 为空或等于 unknow
|
||
|
|
↓
|
||
|
|
setIsOpenApp(true)
|
||
|
|
```
|
||
|
|
|
||
|
|
含义:
|
||
|
|
|
||
|
|
```text
|
||
|
|
A2DP 可能已经连接,但手机音乐 App 没有提供有效歌曲信息。
|
||
|
|
页面可能提示用户打开手机音乐 App。
|
||
|
|
```
|
||
|
|
|