当前位置: 首页 > news >正文

android 媒体之 MediaSession

一、框架

1. MediaSession (媒体会话)

• 角色: 核心枢纽和状态机。它是整个媒体播放控制的核心。

• 作用:

封装播放状态: 持有当前播放状态(如播放/暂停、当前播放位置、播放速度、播放队列、当前媒体项元数据等)。 暴露控制接口: 通过 setCallback()设置一个 MediaSession.Callback。这个回调定义了如何处理来自外部的控制命令(如 onPlay(), onPause(), onSkipToNext(), onSeekTo()等)。应用的后台播放逻辑主要实现在这里。 分发状态更新: 当播放状态发生变化(如开始播放、暂停、切歌、进度更新)时,MediaSession 会主动通知所有连接到它的 MediaController。 提供令牌(Token): 生成一个 MediaSession.Token。这个 Token 是 MediaSession的唯一标识符和安全凭证,用于前台组件(通过 MediaBrowser)连接到后台服务并获取 MediaController。

• 位置: 通常由后台服务(MediaBrowserService)创建并持有。

• 关键点: 它不直接处理媒体播放,而是定义接口和保存状态,具体的播放动作由 MediaSession.Callback 的实现者(你的播放逻辑)完成。

2. MediaBrowserService (媒体浏览器服务)

• 角色: 后台服务的基类。它是长期运行在后台(通常在一个独立的进程)的服务,负责管理媒体内容库、播放逻辑以及与前台 UI 的连接。

• 作用:

生命周期管理: 作为 Android Service,它可以在 UI 不可见时(如应用退到后台、锁屏)继续运行,保证播放不中断。 托管 MediaSession: 创建并持有 MediaSession 实例,实现其 Callback 中的播放控制逻辑。 管理内容库: 实现 onLoadChildren()等方法,向连接的客户端(MediaBrowser)提供媒体内容的结构(如专辑列表、歌曲列表)。 连接点: 提供 onGetRoot()方法,验证请求连接的客户端(MediaBrowser)是否有权限,并返回一个 BrowserRoot 对象(通常包含 MediaSession 的 Token)。这是前台连接后台的入口。 管理客户端连接: 维护连接到它的 MediaBrowser 客户端列表。

• 位置: 后台服务,继承自 Service。

• 关键点: 它是后台播放逻辑的容器和连接桥梁。它创建 MediaSession 并实现其核心播放逻辑。

3. MediaBrowser (媒体浏览器)

• 角色: 前台 UI 的连接器。由前台组件(如 Activity、Fragment)创建和使用。

• 作用:

连接到 MediaBrowserService: 使用 MediaBrowserService 的组件名(或通过 MediaSession.Token)发起连接请求。 获取会话令牌: 连接成功后,通过 getSessionToken()方法获取到 MediaBrowserService 所持有的 MediaSession 的 Token。 浏览媒体内容: 使用 subscribe()方法订阅媒体内容树(如“所有歌曲”、“按艺术家”)的更新,并通过 MediaBrowser.SubscriptionCallback 接收内容(MediaItem 列表)。使用 unsubscribe()取消订阅。 断开连接: 在 UI 销毁时断开与服务的连接。

• 位置: 前台 UI 组件(Activity/Fragment)。

• 关键点: 它主要负责建立连接和获取内容结构。它本身不直接控制播放。获取到 MediaSession.Token 后,它的主要任务就完成了(用于创建 MediaController)。

4. MediaController (媒体控制器)

• 角色: 前台 UI 的控制代理和状态接收器。

• 作用:

创建: 前台 UI 组件使用 MediaBrowser 连接成功后获取到的 MediaSession.Token,通过 MediaControllerCompat.getMediaController()或 MediaControllerCompat 的构造函数创建 MediaController。 发送控制命令: 提供方法(如 getTransportControls().play(), pause(), skipToNext(), seekTo())让 UI 发送播放控制命令。这些命令最终会被路由到后台 MediaSession 的 Callback 中执行。 获取当前状态: 提供方法(如 getPlaybackState(), getMetadata())让 UI 查询当前的播放状态和媒体元数据。 接收状态更新: 通过注册 MediaController.Callback,UI 可以监听 MediaSession 的状态变化(如播放状态改变、元数据更新、队列变化)。当后台状态变化时,MediaSession 会通知所有关联的 MediaController,这些 MediaController 再回调其注册的 Callback 通知 UI 更新。 与 MediaSession 交互: 它是前台 UI 与后台 MediaSession 交互的主要通道。

• 位置: 前台 UI 组件(Activity/Fragment),通常与 MediaBrowser 在同一组件中使用。

• 关键点: 它是 UI 控制播放和获取状态更新的主要工具。它通过 MediaSession.Token 与后台的 MediaSession 建立联系。

5.关系和工作流程

  1. 后台启动: 你的应用启动后台服务(继承自 MediaBrowserService)。该服务在 onCreate() 中创建 MediaSession,设置其 Callback(实现播放逻辑),并可能开始准备播放。
  2. 前台启动: 用户打开应用 UI(Activity/Fragment)。
  3. 连接: UI 创建 MediaBrowser 对象,使用 MediaBrowserService 的组件名调用 connect() 尝试连接。
  4. 验证与连接: MediaBrowserService 的 onGetRoot() 被调用,验证客户端权限并返回 BrowserRoot(包含 MediaSession.Token)。连接成功。
  5. 获取控制器: UI 的 MediaBrowser.ConnectionCallback.onConnected() 被调用。在这里,UI 通过 MediaBrowser.getSessionToken() 获取 MediaSession.Token,并用它创建 MediaController。
  6. 浏览内容 (可选): UI 可以使用 MediaBrowser.subscribe() 请求媒体内容结构(如显示歌曲列表)。
  7. 控制播放: 当用户点击 UI 上的播放按钮时,UI 调用 MediaController.getTransportControls().play()。
  8. 命令路由: MediaController 将 play() 命令发送给后台的 MediaSession。
  9. 执行命令: MediaSession 调用其 Callback.onPlay() 方法。你在这里实现的后台播放逻辑开始执行(例如,开始播放音乐)。
  10. 状态更新: 播放开始后,后台逻辑(在 Callback.onPlay() 中)更新 MediaSession 的状态(例如,设置播放状态为 PlaybackState.STATE_PLAYING)。
  11. 状态分发: MediaSession 自动将新的播放状态广播给所有连接的 MediaController。
  12. UI 更新: UI 的 MediaController 收到状态更新,触发其注册的 MediaController.Callback.onPlaybackStateChanged()。UI 在这里更新界面(如将按钮图标改为暂停图标,更新进度条)。
  13. 断开: 当 UI 销毁时,它调用 MediaController.unregisterCallback() 和 MediaBrowser.disconnect() 进行清理。

注意点

• MediaSession: 核心状态和控制接口。定义“能做什么”(Callback)和“当前状态是什么”。

• MediaBrowserService: 后台服务的基类。托管 MediaSession,实现播放逻辑,管理内容库,处理客户端连接。

• MediaBrowser: 前台连接器。负责连接到 MediaBrowserService 并获取 MediaSession.Token(用于创建 MediaController)和浏览内容。

• MediaController: 前台代理。利用 MediaSession.Token 与后台 MediaSession 通信,发送控制命令并接收状态更新,驱动 UI 变化。

http://www.cnnetsun.cn/news/139801.html

相关文章:

  • 校园网络规划
  • 护眼灯已足够优秀,为何仍需眼调节训练灯?答案藏在近视防控里
  • Visual Studio中的多态
  • MindSpore硬核实战:彻底搞懂自动混合精度(AMP)与函数式训练
  • Java异常处理详解。零基础小白到精通,收藏这篇就够了
  • 基于深度学习YOLOv12的犬种识别检测系统(YOLOv12+YOLO数据集+UI界面+登录注册界面+Python项目源码+模型)
  • 基于深度学习YOLOv11的犬种识别检测系统(YOLOv11+YOLO数据集+UI界面+登录注册界面+Python项目源码+模型)
  • [插电式混合动力车辆][交替方向乘子法(ADMM)结合CVX]插电式混合动力车辆的能源管理:基于凸优化算法用于模型预测控制MPC研究附Matlab代码
  • 【别花冤枉钱】学生党专享!2025年把AI率90%降到10%的“低成本”组合拳(含免费/付费工具避坑指南)
  • 前端Vue制作日历插件FullCalendar,零基础入门到精通,收藏这篇就够了
  • 基于MPC算法的P2构型混合动力汽车能量管理优化策略
  • 德克萨斯大学奥斯汀分校突破:球形利奇量化提升AI图像生成质量
  • 13、Unix 系统管理脚本实用指南(上)
  • 2026网络安全薪酬全景:哪些岗位是价值洼地,哪里又是薪资天花板?
  • Oracle领衔科技巨头5000亿美元AI数据中心租赁狂潮
  • Java算法——排序篇之快速排序,零基础小白到精通,收藏这篇就够了
  • 平安好医生:“人+机+生态”闭环 打造中国AI医疗标杆
  • Compose 适配 - 全屏显示 EdgeToEdge
  • python-flask-django重症监护室中急诊护理管理系统设计与实现_zjv2nt1d
  • 拿一句,逗得你家男人哭笑不得
  • 虎贲等考 AI:AI 赋能学术全流程,让论文写作从 “煎熬” 到 “高效”✨
  • 介观交通流仿真软件:VISSIM (介观模式)_(5).车辆行为模型
  • 英特尔酷睿Ultra第三代,如何推动AI PC规模化落地?
  • 15、密码学编程问题与解决方案
  • 【花雕学编程】Arduino BLDC 之基础差速转向小车(串口控制)
  • 【毕业设计】基于springboot+Android的研学旅行服务平台APP小程序设计(源码+文档+远程调试,全bao定制等)
  • 应用——管道与文件描述符
  • 【总结】【数据结构】【OS】【计组】【计网】
  • 小程序毕设项目:基于springboot的智能学习小程序(源码+文档,讲解、调试运行,定制等)
  • 小程序毕设项目:基于springboot+微信小程序的大学生餐厅点餐系统小程序(源码+文档,讲解、调试运行,定制等)