Android Dev Summit, October 23-24: two days of technical content, directly from the Android team. Sign-up for livestream updates.

媒体应用架构概览

本部分将说明如何将媒体播放器应用分离成媒体控制器(界面)和媒体会话(实际播放器)。 我们将介绍两种媒体应用架构:非常适合音频应用的客户端/服务器设计,以及面向音频播放器的单个 Activity 设计。 本文还将介绍如何让媒体应用响应硬件控件以及与使用音频输出流的其他应用协作。

播放器和界面

播放音频或视频的多媒体应用通常包含两个部分:

  • 播放器,用于吸收数字媒体并将其呈现为视频和/或音频
  • 界面,带有用于运行播放器并显示播放器状态(可选)的传输控件

ui-and-player

在 Android 中,您可以从零开始构建自己的播放器,也可以从以下选项中进行选择:

  • MediaPlayer 类提供准系统播放器的基本功能,支持最常见的音频/视频格式和数据源。
  • ExoPlayer 是一个提供低层级 Android 音频 API 的开放源代码库。 ExoPlayer 支持 DEMO 和 HLS 流式传输等高性能功能,这些功能在 MediaPlayer 中未提供。 您可以自定义 ExoPlayer 代码,从而轻松添加新组件。 ExoPlayer 只能用于 Android 4.1 及更高版本。

媒体会话和媒体控制器

虽然界面和播放器采用的 API 可能各不相同,但是对所有媒体播放器应用来说,这两部分之间的交互的性质都基本相同。 Android 框架定义了两个类(媒体会话和媒体控制器),它们为构建媒体播放器应用提供了一个完善的结构。

媒体会话和媒体控制器通过以下方式相互通信:使用与标准播放器操作(播放、暂停、停止等)相对应的预定义回调,以及用于定义应用独有的特殊行为的可扩展自定义调用。

controller-and-session

媒体会话

媒体会话负责与播放器的所有通信。 它会对应用的其他部分隐藏播放器的 API。 系统只能从控制播放器的媒体会话中调用播放器。

会话会维护播放器状态(播放/暂停)的表示形式以及播放内容的相关信息。 会话可以接收来自一个或多个媒体控制器的回调。 这样,应用的界面以及运行 Wear OS 和 Android Auto 的配套设备便可以控制您的播放器。

媒体控制器

媒体控制器会隔离您的界面。 您的界面代码只与媒体控制器(而非播放器本身)通信。 媒体控制器会将传输控制操作转换为对媒体会话的回调。 每当会话状态发生变化时,它也会接收来自媒体会话的回调。 这提供了一种自动更新关联界面的机制。 媒体控制器一次只能连接到一个媒体会话。

当您使用媒体控制器和媒体会话时,您可以在运行时部署不同的接口和/或播放器。 您可以根据运行应用的设备的功能单独更改该应用的外观和/或性能。

视频应用与音频应用的差异

播放视频时,您的眼睛和耳朵都需要参与互动。 播放音频时,您需要聆听,但同时也可以使用其他应用。 每种用例都有不同的设计。

视频应用

视频应用需要一个窗口来查看内容。 出于这个原因,视频应用通常作为单个 Android Activity 来实现。 呈现视频的界面是 Activity 的一部分。

视频播放器 Activity

音频应用

音频播放器并不总是需要显示其界面。 一旦开始播放音频,播放器就可以作为后台任务运行。 用户可以切换到其他应用,同时继续聆听。

要在 Android 中实现此设计,您可以使用两个组件构建音频应用:对界面使用 Activity,对播放器使用服务。 如果用户切换到其他应用,该服务可以在后台运行。 通过将音频应用的两个部分分解为单独的组件,每个组件都可以更高效地独立运行。 与播放器(可能会在没有界面的情况下运行很长时间)不同,界面通常是短时的。

Audio Activity 和 BrowserService

支持库提供了两个类来实现此客户端/服务器方法:MediaBrowserServiceMediaBrowser。 服务组件作为包含媒体会话及其播放器的 MediaBrowserService 子类来实现。 包含界面和媒体控制器的 Activity 应该包括一个 MediaBrowser,后者与 MediaBrowserService 进行通信。

使用 MediaBrowserService 可以让配套设备(如 Android Auto 和 Wear)轻松发现您的应用,连接到该应用,浏览内容并控制播放,而根本无需访问您的界面 Activity。

媒体应用和 Android 音频基础架构

设计良好的媒体应用应该能够与其他播放音频的应用“和谐共存”。 它应准备好与设备上使用音频的其他应用共用手机并相互配合。 它还应该对设备上的硬件控件做出响应。

plays-with-others

所有这些行为都在处理音频输出的变化中进行了介绍。

media-compat 库

media-compat 库包含可帮助您构建音频和视频播放应用的类。 这些类与运行 Android 2.3(API 级别 9)及更高版本的设备兼容。 它们还可与其他 Android 功能配合使用,以打造舒适亲切的 Android 体验。

媒体会话和媒体控制器的建议实现方式是 MediaSessionCompatMediaControllerCompat 类,它们在 media-compat 支持库中定义。 它们取代了 Android 5.0(API 级别 21)中引入的早期版本的 MediaSessionMediaController 类。 compat 类提供相同的功能,但可让您更轻松地开发应用,因为您只需写入一个 API。 该库通过将媒体会话方法转换为更低版本平台上的等效方法(可用时)来保证向后兼容性。

如果您已经有使用旧类的实际应用,我们建议更新到 compat 类。 在使用 compat 版本时,您可以从 RemoteControlClient 中移除对 registerMediaButtonReceiver() 的所有调用以及所有函数。

衡量性能

在 Android 8.0(API 级别 26)及更高版本中,getMetrics() 函数可用于某些媒体类。 它会返回一个包含配置和性能信息的 PersistableBundle 对象(表示为属性和值的对应关系)。 可以为这些媒体类定义 getMetrics() 函数:

系统会为每个实例分别收集相关指标,并在实例的整个生命周期内保留这些指标。 如果没有任何可用指标,则该函数会返回 null。 返回的实际指标取决于类。