本节解释了如何将媒体播放器应用分为媒体控制器(用于 UI)和媒体会话(用于实际播放器)。它描述了两种媒体应用架构:适用于音频应用的客户端/服务器设计和适用于视频播放器的单 Activity 设计。它还展示了如何使媒体应用响应硬件控制,并与其他使用音频输出流的应用协作。
播放器和 UI
播放音频或视频的多媒体应用通常包含两部分:
- 一个播放器,接收数字媒体并将其渲染为视频和/或音频
- 一个带有传输控制器的 UI,用于运行播放器并可选地显示播放器的状态
在 Android 中,您可以从头开始构建自己的播放器,也可以从以下选项中选择:
- MediaPlayer 类为支持最常见音频/视频格式和数据源的基本播放器提供了核心功能。
- ExoPlayer 是一个开源库,构建在
MediaCodec
和AudioTrack
等较低级别媒体框架组件之上。ExoPlayer 支持MediaPlayer
中不提供的高性能功能,例如 DASH。您可以自定义 ExoPlayer 代码,从而轻松添加新组件。ExoPlayer 仅可用于 Android 4.1 及更高版本。
媒体会话和媒体控制器
虽然 UI 和播放器的 API 可以是任意的,但两者之间的交互性质对于所有媒体播放器应用来说基本相同。Android 框架定义了两个类:一个“媒体会话”和一个“媒体控制器”,它们为构建媒体播放器应用施加了明确的结构。
媒体会话和媒体控制器通过对应于标准播放器操作(播放、暂停、停止等)的预定义回调以及用于定义应用特有特殊行为的可扩展自定义调用进行通信。
媒体会话
媒体会话负责与播放器的所有通信。它将播放器的 API 隐藏在应用的其余部分之外。播放器仅通过控制它的媒体会话调用。
会话维护播放器状态(播放/暂停)和正在播放内容的表示。会话可以接收来自一个或多个媒体控制器的回调。这使得您的播放器可以由您的应用 UI 以及运行 Wear OS 和 Android Auto 的配套设备控制。响应回调的逻辑必须一致。MediaSession
回调的响应应该相同,无论哪个客户端应用发起了回调。
媒体控制器
媒体控制器隔离了您的 UI。您的 UI 代码只与媒体控制器通信,而不直接与播放器本身通信。媒体控制器将传输控制操作转换为媒体会话的回调。它还在媒体会话状态改变时接收来自媒体会话的回调。这提供了一种自动更新关联 UI 的机制。媒体控制器一次只能连接到一个媒体会话。
当您使用媒体控制器和媒体会话时,可以在运行时部署不同的接口和/或播放器。您可以根据设备的功能独立更改应用的外观和/或性能。
视频应用与音频应用
播放视频时,您的眼睛和耳朵都会参与。播放音频时,您正在听,但同时也可以使用不同的应用。针对每种用例有不同的设计。
视频应用
视频应用需要一个用于查看内容的窗口。因此,视频应用通常作为单个 Android Activity 实现。视频出现的屏幕是 Activity 的一部分。
音频应用
音频播放器并不总是需要可见的 UI。一旦开始播放音频,播放器就可以作为后台任务运行。用户可以切换到另一个应用并工作,同时继续收听。
要在 Android 中实现此设计,您可以使用两个组件构建音频应用:用于 UI 的 Activity 和用于播放器的服务。如果用户切换到另一个应用,该服务可以在后台运行。通过将音频应用的两个部分分解为单独的组件,每个部分都可以更高效地独立运行。与播放器相比,UI 通常是短命的,而播放器可以在没有 UI 的情况下长时间运行。
支持库提供了两个类来实现这种客户端/服务器方法:MediaBrowserService
和 MediaBrowser
。服务组件作为包含媒体会话及其播放器的 MediaBrowserService
的子类实现。包含 UI 和媒体控制器的 Activity 应包含一个 MediaBrowser
,它与 MediaBrowserService
进行通信。
使用 MediaBrowserService
使得配套设备(如 Android Auto 和 Wear)可以轻松发现您的应用、连接到它、浏览内容和控制播放,而无需访问您的应用的 UI Activity。实际上,可以有多个应用同时连接到同一个 MediaBrowserService
,每个应用都有自己的 MediaController
。提供 MediaBrowserService
的应用应能够处理多个并发连接。
媒体应用和 Android 音频基础设施
设计良好的媒体应用应与其他播放音频的应用“和谐相处”。它应该准备好共享手机并与设备上使用音频的其他应用协作。它还应该响应设备上的硬件控制。
所有这些行为都在控制音频输出中进行了描述。
media-compat 库
media-compat 库包含有助于构建播放音频和视频的应用的类。这些类与运行 Android 2.3(API 级别 9)及更高版本的设备兼容。它们还与其他 Android 功能配合使用,以创建舒适、熟悉的 Android 体验。
媒体会话和媒体控制器的推荐实现是 media-compat 支持库中定义的 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。返回的实际指标取决于类。