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