媒体会话提供了一种与音频或视频播放器交互的通用方式。通过通知 Android 应用程序正在播放媒体,播放控制可以委托给应用程序。与媒体会话集成允许应用程序在外部宣传媒体播放,并接收来自外部来源的播放命令。这些来源可以是物理按钮(例如,耳机上的播放按钮或电视遥控器上的播放按钮)或间接命令(例如,指示 Google 助理“暂停”)。然后,媒体会话将这些命令委托给应用,该应用将它们应用于媒体播放器,对于该播放器来说,命令的来源是透明的。
媒体会话与它管理的播放器并存。您应该在拥有媒体会话及其关联播放器的活动或服务的 onCreate()
方法中创建和初始化媒体会话。
初始化媒体会话
新创建的媒体会话没有功能。您必须通过执行以下步骤来初始化会话
- 设置标志,以便媒体会话可以接收来自媒体控制器和媒体按钮的回调。
- 创建并初始化
PlaybackStateCompat
的实例,并将其分配给会话。播放状态在整个会话中发生变化,因此我们建议缓存PlaybackStateCompat.Builder
以供重用。 - 创建
MediaSessionCompat.Callback
的实例,并将其分配给会话(有关回调的更多信息,请参见下文)。
您应该在拥有该会话的 活动 或 服务 的 onCreate()
方法中创建和初始化媒体会话。
为了让 媒体按钮 在您的应用程序新初始化(或停止)时工作,其 PlaybackState
必须包含与媒体按钮发送的意图匹配的播放操作。这就是为什么在初始化期间将 ACTION_PLAY
分配给会话状态的原因。有关更多信息,请参见 响应媒体按钮。
维护播放状态和元数据
有两个类表示媒体会话的状态。
The PlaybackStateCompat
类描述了播放器的当前运行状态。这包括
- 传输状态(播放器是否正在播放/暂停/缓冲等。请参见
getState()
) - 错误代码和可选错误消息(如果适用)。(请参见
getErrorCode()
并阅读下面的 状态和错误。) - 播放器位置
- 在当前状态下可以处理的有效控制器操作
The MediaMetadataCompat
类描述了正在播放的素材
- 艺术家、专辑和音轨的名称
- 音轨时长
- 在锁定屏幕上显示的专辑封面。该图像是位图,最大尺寸为 320x320dp(如果更大,则缩小)。
- 指向更大版本的艺术品的
ContentUris
实例
播放器状态和元数据在媒体会话的生命周期中可能会发生变化。每次状态或元数据发生变化时,您都必须使用每个类的相应构建器 PlaybackStateCompat.Builder()
或 MediaMetadataCompat.Builder()
,然后通过调用 setPlaybackState()
或 setMetaData()
将新的实例传递给媒体会话。为了减少这些频繁操作的总内存消耗,最好只创建一次构建器,并在整个会话的生命周期中重复使用它们。
状态和错误
请注意,PlaybackState
是一个对象,它包含会话的播放状态 (getState()
) 和必要时的关联错误代码 (getErrorCode()
) 的单独值。错误可能是致命的或非致命的
无论何时播放中断,您都应生成致命错误:将传输状态设置为 STATE_ERROR
,并使用 setErrorMessage(int, CharSequence)
指定关联的错误。只要播放被错误阻止,PlaybackState
应继续报告 STATE_ERROR
和错误。
非致命错误是指您的应用程序无法处理请求,但可以继续播放:传输保持在“正常”状态(例如 STATE_PLAYING
),但 PlaybackState
包含错误代码。例如,如果正在播放最后一首歌曲,而用户请求跳到下一首歌曲,则播放可以继续,但您应该使用错误代码 ERROR_CODE_END_OF_QUEUE
创建一个新的 PlaybackState
,然后调用 setPlaybackState()
。附加到会话的媒体控制器将收到回调 onPlaybackStateChanged()
并向用户解释发生了什么。非致命错误应仅报告一次,即在发生时报告。下次会话更新 PlaybackState
时,不要再次设置相同的非致命错误(除非该错误是响应新请求而发生的)。
媒体会话锁定屏幕
从 Android 4.0(API 级别 14)开始,系统可以访问媒体会话的播放状态和元数据。这就是锁定屏幕可以显示媒体控件和艺术品的方式。行为根据 Android 版本而有所不同。
专辑封面
在 Android 4.0(API 级别 14)到 Android 10(API 级别 29)中,锁定屏幕的背景会显示您的专辑封面,但这只有在媒体会话元数据包含背景位图的情况下才会发生。
传输控制
在 Android 4.0(API 级别 14)到 Android 4.4(API 级别 19)中,当媒体会话处于活动状态且媒体会话元数据包含背景位图时,锁定屏幕会自动显示传输控件。
在 Android 5.0(API 级别 21)或更高版本中,系统不会在锁定屏幕上提供传输控件。相反,您应该使用 MediaStyle 通知 来显示传输控件。
添加自定义操作
媒体应用程序可以定义自定义操作;例如:点赞、喜欢或倒退 30 秒。自定义操作应实现全新的行为。不要使用自定义操作来替换 PlaybackStateCompat 中定义的标准传输控制操作之一。
使用 addCustomAction()
添加自定义操作。以下示例展示了如何添加点赞操作的控件
Kotlin
stateBuilder.addCustomAction( PlaybackStateCompat.CustomAction.Builder( CUSTOM_ACTION_THUMBS_UP, resources.getString(R.string.thumbs_up), thumbsUpIcon ).run { setExtras(customActionExtras) build() } )
Java
stateBuilder.addCustomAction(new PlaybackStateCompat.CustomAction.Builder( CUSTOM_ACTION_THUMBS_UP, resources.getString(R.string.thumbs_up), thumbsUpIcon) .setExtras(customActionExtras) .build());
请参见 通用音乐播放器,以获取完整的示例。
您使用 onCustomAction()
响应该操作。
Kotlin
override fun onCustomAction(action: String, extras: Bundle?) { when(action) { CUSTOM_ACTION_THUMBS_UP -> { ... } } }
Java
@Override public void onCustomAction(@NonNull String action, Bundle extras) { if (CUSTOM_ACTION_THUMBS_UP.equals(action)) { ... } }
另请参见 通用音乐播放器。
媒体会话回调
主要媒体会话回调方法是 onPlay()
、onPause()
和 onStop()
。您可以在此处添加控制播放器的代码。
由于您是在运行时(在 onCreate()
中)实例化并设置会话的回调的,因此您的应用程序可以定义使用不同播放器的备用回调,并根据设备和/或系统级别选择合适的回调/播放器组合。您可以更改播放器,而无需更改应用程序的其余部分。例如,您可以在 Android 4.1(API 级别 16)或更高版本上运行时使用 ExoPlayer,并在更早的系统上使用 MediaPlayer
。
除了控制播放器和管理媒体会话状态转换之外,回调还启用和禁用应用程序的功能,并控制它与其他应用程序和设备硬件的交互方式。(请参见 控制音频输出)。
媒体会话回调方法的实现取决于应用程序的结构。请参见单独的页面,其中描述了如何在 音频应用程序 和 视频应用程序 中使用回调,以及如何针对每种类型的应用程序实现回调。