Files
2026-11-05 14:35:04 +08:00

2.9 KiB

05_Launcher卡片流程

Launcher 卡片做什么

Launcher 蓝牙音乐卡片负责:

1. 显示蓝牙音乐标题
2. 显示歌手
3. 显示封面
4. 显示播放状态
5. 显示当前进度和总时长
6. 提供上一曲、播放/暂停、下一曲按钮

核心文件:

F:\zdCode\tongli\YX_Launcher\src\main\java\com\yaxon\launcher\card\BluetoothMusicCardView.java
F:\zdCode\tongli\YX_Launcher\src\main\res\layout\card_bluetoothmusic.xml

卡片显示流程

1. BluetoothAvrcpClient 收到歌曲信息或播放状态
   ↓
2. BtInfoPushManager.sendMusicInfoToLauncher()
      或 sendMusicStateToLauncher()
   ↓
3. 组装 BtMusicInfo
   ↓
4. DataManager.putObject(BT_MUSIC_INFO, btInfo)
   ↓
5. 发送 ACTION_UPDATE_MUSIC_WIDGET 广播
   ↓
6. Launcher 的 Id3Info 读取 BT_MUSIC_INFO
   ↓
7. Id3Info 回调 BluetoothMusicCardView.onBtMusicInfo()
   ↓
8. BluetoothMusicCardView.bindInfo()
   ↓
9. 更新卡片 UI

卡片显示字段

卡片内容 数据字段
歌曲名 BtMusicInfo.mTitle
歌手 BtMusicInfo.mArtist
封面 BtMusicInfo.mAlbumUrl
播放状态 BtMusicInfo.mPlayState
当前进度 BtMusicInfo.mPlayPosition
总时长 BtMusicInfo.mSongLen

卡片进度条逻辑

1. 收到 BtMusicInfo
   ↓
2. 保存 mLastPositionMs
   ↓
3. 保存 mLastDurationMs
   ↓
4. 保存 mLastUpdateUptimeMs
   ↓
5. 如果是播放中
   ↓
6. 每秒用本地时间估算进度
   ↓
7. updateProgress()

这意味着:

Launcher 卡片不是每秒都等蓝牙栈回调,
而是在播放中自己按时间推进进度条。

卡片控制流程

1. 用户点击 Launcher 卡片按钮
   ↓
2. BluetoothMusicCardView.onClick()
   ↓
3. notifyBtSourceActive()
   ↓
4. DataManager.putInt(SOURCE_ID, SOURCE_BT_MUSIC)
   ↓
5. sendBtControl(cmd)
   ↓
6. DataManager.putInt(MUSIC_BT_CONTROL_STATE, cmd)
   ↓
7. BtMusicAudioManager 的 ContentObserver 收到变化
   ↓
8. 如果蓝牙音乐没有焦点,先 requestAudioFocus()
   ↓
9. 根据 cmd 调用 BtMusicManager
   ↓
10. BtMusicManager 调用 BluetoothAvrcpClient
   ↓
11. 手机音乐 App 响应
   ↓
12. MUSIC_BT_CONTROL_STATE 重置为 -1

卡片按钮命令

卡片按钮 写入命令
上一曲 StateUtils.MUSIC_BT_CONTROL_PRE
下一曲 StateUtils.MUSIC_BT_CONTROL_NEXT
播放 StateUtils.MUSIC_BT_CONTROL_PLAY
暂停 StateUtils.MUSIC_BT_CONTROL_PAUSE

为什么要重置为 -1

如果连续点击同一个按钮,比如连续点下一曲:

第一次写入 MUSIC_BT_CONTROL_NEXT
  ↓
ContentObserver 触发
  ↓
处理完成后写回 -1
  ↓
下一次再写 MUSIC_BT_CONTROL_NEXT
  ↓
值发生变化,ContentObserver 可以再次触发

如果不重置,同一个值可能不会再次触发观察。