播放器是应用中用于播放媒体内容的组件。
Media3 Player 接口
为通常由播放器处理的功能设置了概要。这包括:
- 影响播放控件,例如播放、暂停和跳转
- 查询当前播放媒体的属性,例如播放位置
- 管理媒体内容的播放列表/队列
- 配置播放属性,例如随机播放、重复播放、播放速度和 音量
- 将视频呈现到屏幕
Media3 还提供了 Player 接口的实现,称为
ExoPlayer。
组件之间的通用接口
Media3 中的多个组件实现了 Player 接口,例如:
| 组件 | 说明和行为备注 |
|---|---|
ExoPlayer |
媒体播放器 API,也是 Player 接口的默认实现。 |
MediaController |
与 MediaSession 交互以发送播放命令。如果
您的 Player 和 MediaSession 位于与播放器界面所在的 Activity 或
Fragment 分开的
Service 中,您可以将您的
MediaController 分配为您的
界面组件(如 PlayerView 或 Player
可组合项)的播放器。播放和播放列表方法调用会通过 MediaSession 发送到 Player。 |
MediaBrowser |
除了
MediaController 提供的功能之外,还与
MediaLibrarySession 交互以浏览可用的媒体内容。
|
SimpleBasePlayer |
一种 Player 实现,可将需要实现的方法数量
减少到最少。当您使用要连接到 MediaSession 的自定义播放器时,此方法非常有用。 |
ForwardingSimpleBasePlayer |
一种 SimpleBasePlayer 子类,旨在将播放操作转发到另一个 Player,同时允许与 SimpleBasePlayer 相同的行为自定义。使用
此类可以抑制或修改特定的播放操作。
|
RemoteCastPlayer |
一种 Player 实现,用于控制远程 Cast 接收器应用上的播放。 |
CastPlayer |
一种 Player 实现,用于控制本地和远程 Cast 播放。 |
虽然 MediaSession 不实现 Player 接口,但在创建时需要 Player。其目的是允许其他进程或线程访问 Player。
Media3 播放架构
如果您有权访问 Player,则应直接调用其方法来发出播放命令。您可以通过实现 MediaSession 来宣传播放并授予外部来源播放控制权。这些外部来源实现 MediaController,这有助于连接到媒体会话并发出播放命令请求。
在后台播放媒体时,您需要将媒体会话和播放器放在作为前台服务运行的 MediaSessionService 或 MediaLibraryService 中。这样做可以将播放器与应用中包含播放控制界面的 Activity 分开。这可能需要您使用媒体控制器。
Player 接口在 Media3 的架构中发挥着关键
作用。玩家状态
实现 Player 接口的媒体播放器的状态主要包含 4 类信息:
- 播放状态
- 使用
getPlaybackState()检索。 - 接口定义的状态值包括
STATE_IDLE、STATE_BUFFERING、STATE_READY和STATE_ENDED。
- 使用
- 媒体内容的播放列表
- 用于播放的
MediaItem实例序列。 - 使用
getCurrentTimeline()检索 Player实例可以提供播放列表操作方法,例如 添加或移除 一个MediaItem,以及便捷方法,例如getCurrentMediaItem()。
- 用于播放的
- 播放/暂停属性,例如:
playWhenReady:指示用户是否希望媒体在可能的情况下播放或保持暂停状态- 播放抑制原因:
指示播放被抑制的原因(如果适用),即使
playWhenReady为true也是如此 isPlaying:指示播放器当前是否正在播放,只有当播放状态为STATE_READY、playWhenReady为true且播放未被抑制时,此值才为true
- 播放位置,包括:
- 当前媒体文件索引:
播放列表中当前
MediaItem的索引。 isPlayingAd:指示是否正在播放插入的广告。- 当前播放位置:
当前
MediaItem或插入的广告中的当前播放位置。
- 当前媒体文件索引:
播放列表中当前
此外,Player 接口还允许访问
可用轨道、
媒体元数据、
播放速度、
音量和其他
辅助播放属性。
监听更改
使用 Player.Listener
监听 Player 中的更改。如需详细了解如何创建和使用监听器,请参阅 ExoPlayer 文档中有关
播放器事件的
内容。
请注意,监听器接口不包含任何用于跟踪正常播放进度的回调。如需持续监控播放进度(例如设置进度条界面),您应以适当的时间间隔查询当前位置。
Kotlin
fun checkPlaybackPosition(delayMs: Long): Boolean = handler.postDelayed( { val currentPosition = player.currentPosition // Update UI based on currentPosition checkPlaybackPosition(delayMs) }, delayMs, )
Java
boolean checkPlaybackPosition(long delayMs) { return handler.postDelayed( () -> { long currentPosition = player.getCurrentPosition(); // Update UI based on currentPosition checkPlaybackPosition(delayMs); }, delayMs); }
控制播放
Player 接口提供了多种方法来操纵状态和控制播放:
- 基本播放控件
例如
play()、pause()、prepare()和stop()。 - 播放列表操作,例如
addMediaItem()或removeMediaItem()。 - 跳转以更改 当前项或位置。
- 设置重复模式和 随机播放模式。
- 更新 轨道选择偏好设置。
- 设置 播放速度。
自定义 Player 实现
如需创建自定义播放器,您可以扩展
SimpleBasePlayer
Media3 中包含的。此类提供了 Player 接口的基本实现,可将需要实现的方法数量减少到最少。
首先,替换 getState() 方法。此方法在调用时应填充当前播放器状态,包括:
- 可用命令集
- 播放属性,例如播放器是否应在播放状态为
STATE_READY时开始播放、当前播放的媒体文件的索引以及当前项中的播放位置
Kotlin
class CustomPlayer(looper: Looper) : SimpleBasePlayer(looper) { override fun getState(): State { return State.Builder() .setAvailableCommands(Commands.EMPTY) // Set which playback commands the player can handle // Configure additional playback properties .setPlayWhenReady(true, PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST) .setCurrentMediaItemIndex(0) .setContentPositionMs(0) .build() } }
Java
private static final class CustomPlayer extends SimpleBasePlayer { public CustomPlayer(Looper looper) { super(looper); } @Override protected State getState() { return new State.Builder() .setAvailableCommands(Commands.EMPTY) // Set which playback commands the player can handle // Configure additional playback properties .setPlayWhenReady(true, PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST) .setCurrentMediaItemIndex(0) .setContentPositionMs(0) .build(); } }
SimpleBasePlayer 将强制使用有效的状态值组合创建 State。它还会处理监听器并通知监听器状态变化。如果您需要手动触发状态更新,
请调用 invalidateState()。
除了 getState() 方法之外,您只需实现用于播放器声明为可用的命令的方法。找到与您要实现的功能对应的可替换处理程序方法。例如,
替换 handleSeek()
方法以支持 COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM
和 COMMAND_SEEK_TO_NEXT_MEDIA_ITEM等操作。
修改 Player 实现
您可以使用
ForwardingSimpleBasePlayer修改现有
Player的状态和行为,而无需创建完全自定义的Player。如需了解详情,请参阅自定义页面上的
指南。