三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

MediaSession与MediaController

MediaSession与MediaController

一、核心概念

Android 音频播放架构采用 C/S(客户端/服务端)模型:

组件角色类比
MediaSession服务端电视机
MediaController客户端遥控器
MediaSession.Token连接凭证遥控器的红外配对码

MediaSession运行在音频播放服务中,掌握播放器的实际控制权。

MediaController运行在 UI 层或外部应用,通过向 Session 发送指令来控制播放。

两者通过 Binder 机制实现跨进程通信。

二、原理详解

2.1 连接原理:如何拿到 MediaSession?

MediaController 与 MediaSession 的连接依赖 MediaSession.Token。

客户端进程

服务进程

生成

setActive true

发现/传递 Token

new Controller
token

Binder 双向通信

MediaSession

Token

系统服务
MediaSessionManager

MediaController

已连接的 Controller

连接步骤:
1.服务端公开令牌:
-创建 MediaSession 时,系统自动生成唯一 Token。
-调用 mediaSession.setActive(true) 将 Session 注册到系统服务 MediaSessionManager。
-系统服务维护一个“活跃媒体会话列表”,供外部发现。
2.客户端获取令牌(两种方式):
-内部连接(同 App):Service 直接把 session.getSessionToken() 传给 Activity。
-外部发现(跨 App/系统):通过 MediaSessionManager.getActiveSessions() 获取列表,或通过 MediaBrowserService 连接。
3.建立双向通道:
-客户端调用 new MediaController(context, token) 完成绑定。
-底层通过 Binder 建立双向通信,Controller 发指令,Session 回推状态。

2.2 状态同步原理
状态同步采用 推送模型,即服务端主动推送变化,客户端被动接收。不走轮询。

MediaController系统服务MediaSession播放器MediaController系统服务MediaSession播放器歌曲切换setMetadata(新歌名)Binder 推送元数据变化onMetadataChanged(metadata)更新UI / 通知栏 / 手表暂停setPlaybackState(PAUSED)Binder 推送状态变化onPlaybackStateChanged(state)按钮变回"播放"图标

同步的两个时机:

时机方式说明
刚连接时全量拉取调用controller.getMetadata()getPlaybackState()获取当前快照
之后变化时增量推送通过注册的 Callback,由 Session 主动触发set方法实现同步

开发者必须手动更新的三项:
setMetadata() — 歌曲信息(标题、歌手、封面)
setPlaybackState() — 播放状态(播放/暂停/缓冲中),包括进度
setQueue() — 播放列表(如果需要)

问题答案要点
Token 错误/失效的原因?最常见是 Session 已release()但 Controller 没重建。必须每次onServiceConnected都拿新 Token 建新 Controller。
onSessionDestroyed()什么时候回调?Session 被释放或服务进程死亡时。应在此回调中清理 UI、置空 Controller。
多个 Controller 同时连接会怎样?正常。Session 支持一对多,所有 Controller 都会收到推送。这是手表、通知栏、车载能同时同步的基础。

MediaBrowserService是 Android 提供的一个专门用于媒体内容浏览的服务基类。如果说 MediaSession 负责“播放控制”,那 MediaBrowserService 就负责“内容发现和浏览”。

MediaBrowserService = 内容发现入口 + 权限控制网关 + 向外部暴露 MediaSession 的桥梁。
二、核心作用
1. 提供可浏览的媒体内容树
onGetRoot():告诉客户端“你有权限看什么”。比如你的车机只想看音乐,不想看播客。
onLoadChildren():返回指定目录下的子项。点进“歌单”就返回歌曲列表。
2. 连接认证与权限控制
外部 App(如 Android Auto、Wear OS)通过 MediaBrowser 连接你的 MediaBrowserService 时,你可以在 onGetRoot() 里校验包名、签名,决定能访问什么内容或直接拒绝。
3. 配合 MediaSession 使用
安卓系统要求:如果要让 Android Auto 或 Wear OS 能够连接你的 App,只实现 MediaSession 是不够的,还必须实现 MediaBrowserService。

MediaBrowserService 帮助客户端发现你的 MediaSession.Token。客户端连接后,通过 getSessionToken() 拿到 Token,进而创建 MediaController 来控制播放。

MediaSessionMediaBrowserService客户端 如手表MediaSessionMediaBrowserService客户端 如手表connect()onGetRoot() 校验权限返回根节点subscribe(parentId)onLoadChildren() 返回歌单返回歌曲列表(UI展示)getSessionToken()返回 Tokennew MediaController(token)状态同步,可控制播放
← 返回列表