如何使用 PlaybackOverlayFragment 播放视频内容


如何使用 PlaybackOverlayFragment 播放视频内容

上次更新时间:2016 年 12 月。

在启用 Leanback 的项目中,播放视频内容是在 PlaybackOverlayActivity 中执行的。PlaybackOverlayActivity 的用户界面很简单:我们有一个全屏视频播放器负责播放内容。视频播放器的顶部是 PlaybackOverlayFragment,它负责显示所有媒体控件和管理底层内容播放。

有许多不同的视频播放器可以使用,但是当您首次部署启用了 Leanback 的项目时,默认的视频播放器是 VideoView。

VideoView 是一个非常基本的视频播放器,非常适合您只想以一种简单的方式显示非加密视频文件的情况。大多数开发者倾向于选择更强大、功能更丰富的播放器,对于 Fire TV,通常的选择是亚马逊定制版的 ExoPlayer。为了简单起见,我们将继续使用我们在默认的 Leanback 模板 VideoView 中找到的内容。

当我们在 PlaybackOverlayActivity 分析 UI 的 xml 文件时,我们看到只存在这两个组成部分:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <VideoView
        android:id="@+id/videoView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"
/>
    <fragment
        android:id="@+id/playback_controls_fragment"
        android:name="PlaybackOverlayFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
/>
</FrameLayout>

PlaybackOverlayActivity 的主要组成部分

PlaybackOverlayActivity 的基本设置非常简单,重点关注四个主要组成部分:

public class PlaybackOverlayActivity extends Activity implements
        PlaybackOverlayFragment.OnPlayPauseClickedListener {

private VideoView mVideoView;
private LeanbackPlaybackState mPlaybackState;
private MediaSession mSession;

...

}
  1. 侦听器: 我们可为 PlaybackOverlayActivity 添加大量侦听器,这对于为用户在其遥控器上执行的所有操作(播放、暂停、倒回等)添加回调非常有用。为简单起见,我们将查看 Leanback 模板上唯一可用的侦听器,即 OnPlayPauseClickedListener
  2. VideoView 是我们用来播放视频内容的播放器。
  3. LeanbackPlaybackState 只是一个标记,用于跟踪应用的状态(例如 LeanbackPlaybackState.PLAYING、LeanbackPlaybackState.PAUSED)。
  4. MediaSession: MediaSession 的主要任务是与底层的安卓框架通信,并管理使用遥控器执行的操作的所有权。

遥控器

Fire TV 和其他安卓设备之间的主要区别之一是,与 Fire TV 进行交互的唯一方式是通过其遥控器。

由于 Fire OS 5 是基于 Android Lollipop,因此 Fire TV 遥控器上生成的 KeyEvent 与经典安卓设备上生成的 KeyEvent 相同,不过是通过物理按钮生成的。

首先,我们需要确保我们的应用受遥控器的控制。我们可以通过在 MediaSession 中设置几个标记来轻松地做到这一点。

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.playback_controls);
    ...

    mSession = new MediaSession(this, "LeanbackSampleApp");
    mSession.setCallback(new MediaSessionCallback());
    mSession.setFlags(MediaSession.FLAG_HANDLES_MEDIA_BUTTONS
            | MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS
    );

    mSession.setActive(true);

}

MediaSession.setFlags() 被调用时,我们的应用将控制对遥控器按钮执行的操作。特别是,FLAG_HANDLES_MEDIA_BUTTONS 允许用户控制遥控器底部的按钮(倒回、播放/暂停和快进),而 FLAG_HANDLES_TRANSPORT_CONTROLS 允许我们的应用侦听导航按钮,这些按钮控制应用的视图中的移动(向上、向右、向下、向左)。

侦听遥控器上的 KeyEvents

现在我们已经设置了应用的 MediaSession,接下来我们可以开始侦听在遥控器上执行的操作。

要做到这一点,我们需要对 KeyEvent 做出反应:

@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
    PlaybackOverlayFragment playbackOverlayFragment =
		findFragmentById(R.id.playback_controls_fragment);
    switch (keyCode) {
        ...
        case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
            if (mPlaybackState == LeanbackPlaybackState.PLAYING) {
                playbackOverlayFragment.togglePlayback(false);
            } else {
                playbackOverlayFragment.togglePlayback(true);
            }
            return true;
        ...
    }
}

我们需要覆盖 onKeyUp(),因为这是当用户单击按钮并抬起手指时触发的事件(单击/操作结束)。

在本例中,我们演示如何在用户按下播放/暂停按钮时作出反应。我们对 KeyEvent: KEYCODE_MEDIA_PLAY_PAUSE 作出反应,然后检查当前的 LeanbackPlaybackState。如果我们正在播放,可以在 PlaybackOverlayFragment 上将播放切换为 false(停止播放)。否则,我们将其设置为 true,触发底层片段的回调。

触发播放

最后,我们需要在 VideoView 上触发播放。要做到这一点,我们需要在活动中实现 ClickListener 提供的回调(在我们的例子中为 PlaybackOverlayFragment.OnPlayPauseClickedListener)。

public void onFragmentPlayPause(Movie movie, int position, Boolean playPause) {
   mVideoView.setVideoPath(movie.getVideoUrl());
    ...
    if (mPlaybackState != LeanbackPlaybackState.PLAYING) {
        	mPlaybackState = LeanbackPlaybackState.PLAYING;
        	if (position > 0) {
            mVideoView.seekTo(position);
            mVideoView.start();
        }
    ...
}

以下是发生的情况的分步视图:

  1. 设置要播放的视频的 URL。为此,我们使用 VideoView.setVideoPath(),绕过视频的 URL。它可以是我们的云存储库中的简单视频文件,也可以是应用中的嵌入式视频。重要的是 URL 需要指向视频文件。
  2. 我们检查 LeanbackPlaybackState
  3. 如果我们需要开始播放内容,可以使用 seekTo() 设置视频中我们希望开始播放的位置(以毫秒为单位,通常为 0)。
  4. 调用 VideoView.start(),最终使视频播放。

支持 Leanback 的项目的其他功能

Leanback 模板相当复杂,但可为用户创造丰富的电视体验。例如,默认情况下,您可以定义在显示内容时推荐的视频。此外,开发者可以实现 SearchFragment 来创建自定义搜索体验。