媒体会话与其管理的播放器共存。您应该在媒体会话及其关联播放器所属 Activity 或服务的 onCreate()
方法中创建并初始化媒体会话。
初始化媒体会话
新创建的媒体会话没有功能。您必须通过执行以下步骤来初始化会话:
- 设置标记,以便媒体会话可以接收来自媒体控制器和媒体按钮的回调。
- 创建并初始化
PlaybackStateCompat
的实例,并将其分配给会话。播放状态在整个会话过程中会发生变化,因此我们建议您缓存PlaybackStateCompat.Builder
以便重复使用。 - 创建
MediaSessionCompat.Callback
的实例并将其分配给会话(下文详述回调)。
您应该在媒体会话所属的 Activity 或服务的 onCreate()
方法中创建并初始化媒体会话。
应用刚刚初始化(或停止)时,为了让媒体按钮正常工作,其 PlaybackState
必须包含与媒体按钮发送的 Intent 相符的播放操作。这就是在初始化过程中为会话状态分配 ACTION_PLAY
的原因。如需了解详情,请参阅响应媒体按钮。
保持播放状态和元数据
有两个类表示媒体会话的状态。
PlaybackStateCompat
类用于描述播放器当前的运行状态。这其中包括:
- 传输状态(播放器是否正在播放/暂停/缓冲等。请参阅
getState()
) - 错误代码和可选的错误消息(适用时)。(请参阅
getErrorCode()
并阅读下文中的状态和错误。) - 播放器位置
- 可在当前状态下处理的有效控制器操作
MediaMetadataCompat
类说明正在播放的素材:
- 音乐人、专辑和曲目的名称
- 曲目时长
- 要在锁定屏幕上显示的专辑封面。图片为位图,最大尺寸为 320x320dp(如果尺寸较大,则会按比例缩小)。
- 指向较大版本封面的
ContentUris
实例
播放器状态和元数据在媒体会话的整个生命周期内会发生变化。每当状态或元数据发生更改时,您必须为每个类(PlaybackStateCompat.Builder()
或 MediaMetadataCompat.Builder()
)使用相应的构建器,然后通过调用 setPlaybackState()
或 setMetaData()
将新实例传递给媒体会话。要减少这些频繁操作的总体内存消耗,最好一次性创建构建器,并在整个会话生命周期内重复使用它们。
状态和错误
请注意,PlaybackState
对象为会话的播放状态 (getState()
) 并在必要时为关联的错误代码 (getErrorCode()
) 包含单独的值。错误可能是严重错误或非严重错误:
每当播放中断时,您应该生成严重错误:将传输状态设置为 STATE_ERROR
并指定与 setErrorMessage(int, CharSequence)
相关联的错误。只要播放被错误阻止,PlaybackState
就应继续报告 STATE_ERROR
和错误。
如果您的应用无法处理请求,但可以继续播放,则会发生非严重错误:传输仍处于“正常”状态(如 STATE_PLAYING
),但 PlaybackState
包含错误代码。例如,如果最后一首歌曲正在播放且用户请求跳至下一首歌曲,则可继续播放,但您应创建新的 PlaybackState
并包含错误代码ERROR_CODE_END_OF_QUEUE
,然后调用 setPlaybackState()
。附加到会话中的媒体控制器会收到回调 onPlaybackStateChanged()
并向用户说明发生了什么情况。非严重错误应仅在出现时报告一次。下次会话更新时,PlaybackState
不会再次设置相同的非严重错误(除非因响应新请求而出现错误)。
媒体会话锁定屏幕
从 Android 4.0(API 级别 14)开始,系统可以访问媒体会话的播放状态和元数据。这就是锁定屏幕显示媒体控件和封面的方式。此行为因 Android 版本而异。
专辑封面
在 Android 4.0(API 级别 14)及更高版本中,锁定屏幕的背景会显示专辑封面,但前提是媒体会话元数据包含背景位图。
传输控件
在 Android 4.0(API 级别 14)到 Android 4.4(API 级别 19)中,当媒体会话处于活动状态且媒体会话元数据包含背景位图时,锁定屏幕会自动显示传输控件。
在 Android 5.0(API 级别 21)或更高版本中,系统不会在锁定屏幕上提供传输控件。您应使用 MediaStyle 通知来显示传输控件。
添加自定义操作
您可以使用 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());
有关完整示例,请参阅 Universal Music Player。
您通过 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)) { ... } }
另请参阅 Universal Music Player。
媒体会话回调
主媒体会话回调方法为 onPlay()
、onPause()
和 onStop()
。您可以在此处添加控制播放器的代码。
由于您在运行时实例化并设置了会话的回调(在 onCreate()
中),您的应用可以定义使用不同播放器的备用回调,并根据设备和/或系统级别选择合适的回调/播放器组合。您可以在不更改应用的其余部分的情况下更改播放器。例如,在 Android 4.1(API 级别 16)或更高版本上运行时,您可以使用 ExoPlayer,在早期的系统中,您可以使用 MediaPlayer
。
除了控制播放器和管理媒体会话状态转换之外,回调还会启用和停用应用的功能,并控制其与其他应用和设备硬件的活动方式。(请参阅控制音频输出)。
媒体会话回调方法的实现取决于应用的结构。请参阅单独的页面了解如何使用音频应用和视频应用中的回调,以及应如何为各类应用实现回调。