播放媒体的应用需要用户界面组件来显示媒体和控制播放。Media3 库包含一个包含多个 UI 组件的 UI 模块。要依赖 UI 模块,请添加以下依赖项
Kotlin
implementation("androidx.media3:media3-ui:1.4.1")
Groovy
implementation "androidx.media3:media3-ui:1.4.1"
最重要的组件是 PlayerView
,一个用于媒体播放的视图。 PlayerView
在播放期间显示视频、图像、字幕和专辑封面,以及播放控件。
PlayerView
具有一个 setPlayer
方法,用于附加和分离(通过传递 null
)播放器实例。
PlayerView
PlayerView
可用于视频、图像和音频播放。在视频播放的情况下,它会渲染视频和字幕,在图像播放的情况下会渲染位图,并且可以显示音频文件中包含的元数据中的插图。您可以像任何其他 UI 组件一样将其包含在布局文件中。例如,可以使用以下 XML 包含 PlayerView
<androidx.media3.ui.PlayerView
android:id="@+id/player_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:show_buffering="when_playing"
app:show_shuffle_button="true"/>
以上代码片段说明了 PlayerView
提供了几个属性。这些属性可用于自定义视图的行为,以及外观和风格。大多数这些属性都有相应的 setter 方法,可用于在运行时自定义视图。在 PlayerView
Javadoc 中详细列出了这些属性和 setter 方法。
在布局文件中声明视图后,可以在 Activity 的 onCreate
方法中查找它
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // ... playerView = findViewById(R.id.player_view) }
Java
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // ... playerView = findViewById(R.id.player_view); }
初始化播放器后,可以通过调用 setPlayer
将其附加到视图
Kotlin
// Instantiate the player. val player = ExoPlayer.Builder(context).build() // Attach player to the view. playerView.player = player // Set the media item to be played. player.setMediaItem(mediaItem) // Prepare the player. player.prepare()
Java
// Instantiate the player. player = new ExoPlayer.Builder(context).build(); // Attach player to the view. playerView.setPlayer(player); // Set the media item to be played. player.setMediaItem(mediaItem); // Prepare the player. player.prepare();
选择表面类型
PlayerView
的 surface_type
属性允许您设置用于视频播放的表面类型。除了 spherical_gl_surface_view
(这是球形视频播放的特殊值)和 video_decoder_gl_surface_view
(这是使用扩展渲染器进行视频渲染的)值之外,允许的值还有 surface_view
、texture_view
和 none
。如果视图仅用于音频播放,则应使用 none
以避免创建表面,因为这样做可能会很昂贵。
如果视图用于常规视频播放,则应使用 surface_view
或 texture_view
。对于视频播放,SurfaceView
比 TextureView
具有许多优势
- 在许多设备上显著降低功耗。
- 更准确的帧定时,从而实现更流畅的视频播放。
- 在支持的设备上支持更高质量的 HDR 视频输出。
- 在播放受 DRM 保护的内容时支持安全输出。
- 能够在将 UI 层上移的 Android TV 设备上以显示屏的完整分辨率渲染视频内容。
因此,应尽可能优先使用 SurfaceView
而不是 TextureView
。仅当 SurfaceView
无法满足您的需求时,才应使用 TextureView
。一个示例是在 Android 7.0(API 级别 24)之前需要视频表面的平滑动画或滚动,如下面的注释中所述。对于这种情况,最好仅在 SDK_INT
小于 24(Android 7.0)时使用 TextureView
,否则使用 SurfaceView
。
Android TV 上的方向键导航
Android TV 的遥控器有一个方向键控件,它发送作为键事件到达您 Activity
的 dispatchKeyEvent(KeyEvent)
的命令。这些需要委托给播放器视图
Kotlin
override fun dispatchKeyEvent(event: KeyEvent?): Boolean{ return playerView.dispatchKeyEvent(event!!) || super.dispatchKeyEvent(event) }
Java
@Override public boolean dispatchKeyEvent(KeyEvent event) { return playerView.dispatchKeyEvent(event) || super.dispatchKeyEvent(event); }
请求播放器视图的焦点对于导航播放控件和跳过广告非常重要。考虑在 Activity
的 onCreate
中请求焦点
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // ... playerView.requestFocus() // ... }
Java
@Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); // ... playerView.requestFocus(); // ... }
如果您在 Android TV 上使用 Compose,则需要使 AndroidView
可聚焦,并通过相应地将修饰符参数传递到 AndroidView
中来委托事件
AndroidView(
modifier = modifier
.focusable()
.onKeyEvent { playerView.dispatchKeyEvent(it.nativeKeyEvent) },
factory = { playerView }
)
覆盖绘图对象
PlayerView
使用 PlayerControlView
显示播放控件和进度条。PlayerControlView
使用的绘图对象可以由应用程序中定义的同名绘图对象覆盖。有关可覆盖的控件绘图对象的列表,请参阅 PlayerControlView
Javadoc。
进一步自定义
在需要超出上述描述的自定义的情况下,我们希望应用程序开发者实现自己的 UI 组件,而不是使用 Media3 的 UI 模块提供的组件。