第17章 HarmonyOs开发图解之 媒体会话管理
HarmonyOS 学习系统 | 阶段三:高级深耕期
学习目标
| 序号 | 能力 |
|---|---|
| 1 | 理解 AVSession 四大核心类(Browser/Controller/BrowserService/Session)的分工 |
| 2 | 能够实现客户端与服务端的媒体会话连接与控制 |
| 3 | 掌握播放列表的订阅与媒体数据的获取 |
核心图解

内容讲解
17.1 媒体会话管理概述
AVSession 框架是 HarmonyOS 提供的标准化媒体控制协议,它将媒体播放的"控制方"和"播放方"解耦。控制方(如系统媒体栏、蓝牙耳机、语音助手)不需要知道播放方的内部实现,只需通过 AVSession 定义的标准接口即可控制播放。
生活化类比:AVSession 就像"遥控器 + 电视"的约定
想象你有一个万能遥控器(AVController/AVBrowser),可以控制任何品牌的电视(AVBrowserService)。但遥控器和电视之间需要一套约定------按 1 号键是什么功能,按 2 号键是什么功能。AVSession 就是这套约定,它定义了播放/暂停/上一曲/下一曲等标准控制指令。而 AVElement 就像电视节目单,告诉遥控器有哪些节目可以看。
17.2 AVSession 四大核心类
| 类名 | 角色 | 使用位置 | 说明 |
|---|---|---|---|
| AVBrowser | 媒体浏览器 | 客户端 | 用于浏览和发现媒体内容 |
| AVController | 媒体控制器 | 客户端 | 用于控制播放(播放/暂停/上下曲) |
| AVBrowserService | 媒体浏览器服务 | 服务端 | 提供媒体内容给客户端浏览 |
| AVSession | 媒体会话 | 服务端 | 管理播放状态,接收控制指令 |
17.3 客户端:连接与控制
客户端通过 AVBrowser 连接到服务端的 AVBrowserService,连接成功后创建 AVController 来控制播放。
java
// 创建 AVBrowser 连接服务
AVBrowser avBrowser = new AVBrowser(context,
new ElementName("com.example", "AVService"),
new AVConnectionCallback() {
@Override
public void onConnected() {
// 连接成功,创建控制器
AVController controller = new AVController(context,
avBrowser.getAVToken());
controller.setAVControllerCallback(myCallback);
// 订阅媒体数据(获取播放列表)
avBrowser.subscribeByParentMediaId("root",
new AVSubscriptionCallback() {
@Override
public void onAVElementListLoaded(List<AVElement> list) {
// 获取播放列表,更新 UI
for (AVElement element : list) {
HiLog.info(TAG, "媒体: " + element.getTitle());
}
}
});
}
@Override
public void onDisconnected() {
HiLog.info(TAG, "与服务端断开连接");
}
}, null);
avBrowser.connect(); // 发起连接
// 控制播放
controller.getPlayControls().play();
controller.getPlayControls().pause();
controller.getPlayControls().skipToNext();
controller.getPlayControls().skipToPrevious();
17.4 服务端:提供媒体内容
服务端通过继承 AVBrowserService 并配合 AVSession 来提供媒体内容:
java
public class AVService extends AVBrowserService {
@Override
public void onGetRoot(ElementName caller, int transportId, Bundle rootHints) {
// 返回根媒体ID,客户端通过此ID订阅内容
setSessionToken(session.getSessionToken());
}
@Override
public void onLoadChildren(String parentMediaId, Result<List<AVElement>> result) {
// 根据 parentMediaId 返回对应的媒体列表
List<AVElement> elements = queryMediaList(parentMediaId);
result.sendResult(elements);
}
}
代码速查卡
| API | 功能 | 示例 |
|---|---|---|
new AVBrowser(ctx, name, cb, opts) |
创建媒体浏览器 | new AVBrowser(context, elementName, callback, null) |
avBrowser.connect() |
连接服务端 | avBrowser.connect() |
new AVController(ctx, token) |
创建媒体控制器 | new AVController(context, avBrowser.getAVToken()) |
getPlayControls().play() |
播放 | controller.getPlayControls().play() |
getPlayControls().pause() |
暂停 | controller.getPlayControls().pause() |
subscribeByParentMediaId() |
订阅媒体列表 | avBrowser.subscribeByParentMediaId("root", cb) |
setSessionToken(token) |
设置会话令牌 | setSessionToken(session.getSessionToken()) |
与 Android/iOS 对比
| 特性 | HarmonyOS | Android | iOS |
|---|---|---|---|
| 会话框架 | AVSession | MediaSession | MPNowPlayingInfoCenter |
| 浏览器 | AVBrowser / AVBrowserService | MediaBrowser / MediaBrowserService | 不提供(需自建) |
| 控制器 | AVController | MediaController | MPRemoteCommandCenter |
| 系统媒体栏 | 自动集成 | 自动集成 | 自动集成 |
| 通知栏控制 | 通过 AVSession | 通过 MediaSession | 通过 MPNowPlayingInfoCenter |
⚠️ 踩坑回忆录
为什么 AVBrowser 连不上 AVBrowserService?
AVBrowser 和 AVBrowserService 是一对 CP,必须在 config.json 中正确配置 Ability 的 type 和 name。我犯过一个低级错误:Service 的 BundleName 写错了,导致连接回调永远不会触发------整个下午都在排查代码逻辑,最后发现是配置文件里的一个字母写错了。
另一个坑:subscribeByParentMediaId 前必须先调用 unsubscribeByParentMediaId,否则会重复订阅,导致回调被多次触发。这个"先退后进"的设计让人防不胜防,建议在 onConnected 里先统一 unsubscribe 一次。
必做实操任务
| 序号 | 任务 | 难度 |
|---|---|---|
| 1 | 实现一个简单的音乐播放服务端,提供播放列表 | 高 |
| 2 | 实现客户端连接服务端并控制播放/暂停 | 高 |
| 3 | 在客户端展示播放列表(通过 subscribeByParentMediaId) | 中 |
| 4 | 实现上一曲/下一曲切换功能 | 中 |
| 5 | 配合系统通知栏,实现锁屏状态下的媒体控制 | 高 |
学习检查清单
- 能说出 AVBrowser、AVController、AVBrowserService、AVSession 四者的关系
- 能实现客户端连接服务端的完整流程
- 能使用 AVController 控制播放/暂停/上下曲
- 能通过 subscribeByParentMediaId 获取播放列表
- 知道为什么 subscribe 前需要先 unsubscribe
- 能在 config.json 中正确配置 AVBrowserService
- 理解 AVElement 的作用(媒体元数据载体)
- 理解客户端与服务端分离的设计思想
进阶方向
- 实现完整的音乐播放器 App,包含服务端和客户端
- 学习 AVMetadata(媒体元数据)的设置与获取
- 探索蓝牙耳机按键如何通过 AVSession 控制播放
vice - 理解 AVElement 的作用(媒体元数据载体)
- 理解客户端与服务端分离的设计思想
进阶方向
- 实现完整的音乐播放器 App,包含服务端和客户端
- 学习 AVMetadata(媒体元数据)的设置与获取
- 探索蓝牙耳机按键如何通过 AVSession 控制播放