本节介绍如何将媒体播放器应用拆分为媒体控制器(用于 UI)和媒体会话(用于实际播放器)。它描述了两种媒体应用架构:适用于音频应用的客户端/服务器设计和适用于视频播放器的单活动设计。它还展示了如何使媒体应用响应硬件控件并与使用音频输出流的其他应用协作。
播放器和 UI
播放音频或视频的多媒体应用程序通常包含两个部分
- 一个播放器,接收数字媒体并将其渲染为视频和/或音频
- 一个带传输控件的 UI,用于运行播放器并可选地显示播放器的状态
在 Android 中,您可以从头开始构建自己的播放器,也可以选择以下选项
- MediaPlayer 类提供了基本播放器的基本功能,支持最常见的音频/视频格式和数据源。
- ExoPlayer 是一个构建在更低级别媒体框架组件(如
MediaCodec
和AudioTrack
)之上的开源库。ExoPlayer 支持诸如 DASH 之类的高性能功能,而这些功能在MediaPlayer
中不可用。您可以自定义 ExoPlayer 代码,从而轻松添加新组件。ExoPlayer 只能与 Android 4.1 及更高版本一起使用。
媒体会话和媒体控制器
虽然 UI 和播放器的 API 可以是任意的,但这两部分之间的交互本质上对于所有媒体播放器应用都是相同的。Android 框架定义了两个类,即媒体会话和媒体控制器,它们为构建媒体播放器应用强加了一个定义良好的结构。
媒体会话和媒体控制器使用预定义的回调相互通信,这些回调对应于标准播放器操作(播放、暂停、停止等),以及您可以用来定义特定于您的应用的特殊行为的可扩展自定义调用。
媒体会话
媒体会话负责与播放器的所有通信。它向应用程序的其余部分隐藏了播放器的 API。播放器仅从控制它的媒体会话中调用。
会话维护播放器状态(正在播放/已暂停)的表示形式以及有关正在播放内容的信息。会话可以从一个或多个媒体控制器接收来自 回调。这使得您的播放器可以由您的应用的 UI 以及运行 Wear OS 和 Android Auto 的配套设备控制。响应回调的逻辑必须一致。无论哪个客户端应用启动了回调,对 MediaSession
回调的响应都应该相同。
媒体控制器
媒体控制器隔离了您的 UI。您的 UI 代码仅与媒体控制器通信,而不是播放器本身。媒体控制器将传输控制操作转换为对媒体会话的回调。它还在会话状态发生变化时从媒体会话接收回调。这提供了一种自动更新关联 UI 的机制。媒体控制器一次只能连接到一个媒体会话。
当您使用媒体控制器和媒体会话时,您可以在运行时部署不同的界面和/或播放器。您可以根据运行它的设备的功能独立地更改应用程序的外观和/或性能。
视频应用与音频应用
播放视频时,您的眼睛和耳朵都会参与其中。播放音频时,您正在收听,但您也可以同时使用其他应用。每个用例都有不同的设计。
视频应用
视频应用需要一个窗口来查看内容。出于这个原因,视频应用通常实现为单个 Android 活动。视频显示的屏幕是活动的一部分。
音频应用
音频播放器并不总是需要显示其 UI。一旦开始播放音频,播放器就可以作为后台任务运行。用户可以切换到另一个应用并在继续收听的同时工作。
要在 Android 中实现此设计,您可以使用两个组件构建音频应用:用于 UI 的活动和用于播放器的服务。如果用户切换到另一个应用,则服务可以在后台运行。通过将音频应用的两个部分分解成单独的组件,每个组件都可以更有效地独立运行。与播放器相比,UI 通常是短暂的,播放器可以在没有 UI 的情况下运行很长时间。
支持库提供了两个类来实现这种客户端/服务器方法:MediaBrowserService
和 MediaBrowser
。服务组件实现为 MediaBrowserService
的子类,包含媒体会话及其播放器。带有 UI 和媒体控制器的活动应包含一个 MediaBrowser
,它与 MediaBrowserService
通信。
使用 MediaBrowserService
使配套设备(如 Android Auto 和 Wear)可以轻松发现您的应用、连接到它、浏览内容和控制播放,而根本无需访问您的应用的 UI 活动。实际上,可以有多个应用同时连接到同一个 MediaBrowserService
,每个应用都有自己的 MediaController
。提供 MediaBrowserService
的应用应该能够处理多个同时连接。
媒体应用和 Android 音频基础架构
设计良好的媒体应用应该能够与其他播放音频的应用“良好协作”。它应该准备好共享手机并与设备上使用音频的其他应用协作。它还应该响应设备上的硬件控件。
所有这些行为都在 控制音频输出 中进行了描述。
媒体兼容库
媒体兼容 库包含有助于构建播放音频和视频的应用的类。这些类与运行 Android 2.3(API 级别 9)及更高版本的设备兼容。它们还与其他 Android 功能一起使用,以创建舒适、熟悉的 Android 体验。
媒体会话和媒体控制器的推荐实现是类 MediaSessionCompat
和 MediaControllerCompat
,它们在 媒体兼容支持库 中定义。它们替换了在 Android 5.0(API 级别 21)中引入的早期版本的 MediaSession
和 MediaController
类。兼容类提供了相同的功能,但使开发您的应用变得更容易,因为您只需要编写一个 API。该库通过在可用时将媒体会话方法转换为旧平台版本上的等效方法来处理向后兼容性。
如果您已经有了一个使用旧类的工作应用,我们建议您更新到兼容类。当您使用兼容版本时,您可以删除对 registerMediaButtonReceiver()
的所有调用以及来自 RemoteControlClient
的任何方法。
衡量性能
在 Android 8.0(API 级别 26)及更高版本中,getMetrics()
方法可用于某些媒体类。它返回一个包含配置和性能信息的 PersistableBundle
对象,以属性和值的映射形式表示。这些媒体类定义了 getMetrics()
方法
MediaPlayer.getMetrics()
MediaRecorder.getMetrics()
MediaCodec.getMetrics()
MediaExtractor.getMetrics()
每个实例的指标都会单独收集,并在实例的生命周期内持续存在。如果没有可用的指标,则该方法返回 null。返回的实际指标取决于类。