У меня есть довольно простая задача: реализация потокового видео HLS с использованием фреймворка Leanback и Exoplayer.
Я использую простой макет с одним фрагментом:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="@+id/video_fragment"
android:name="android.support.v17.leanback.app.VideoFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
Судя по всему, VideoFragment
поставляется с HUD по умолчанию, который выглядит так:
Согласно документам, рекомендуемый подход к соединению медиаплеера с элементами управления воспроизведением — через PlaybackGlue
. Например, приложение-витрина Leanback использует MediaPlayer
и, следовательно, использует MediaPlayerGlue
. Я для своих целей взял ExoPlayerGlue
из этого проекта.
private PlaybackFragmentGlueHost glueHost;
private PlaybackControlGlue glue;
@Override
public void onCreate(Bundle savedInstanceState) {
// ...
final VideoFragment videoFragment = (VideoFragment) getFragmentManager.findFragmentById(R.id.video_fragment);
glueHost = new VideoFragmentGlueHost(videoFragment);
glue = ExoPlayerGlue(this, player)
glue.setHost(glueHost);
}
Этот код выполняет свою работу: он привязывает клики к событиям плеера, поэтому пауза/возобновление и перемотка назад/вперед работают как положено.
Сложная часть — настройка элементов управления воспроизведением. PlaybackGlueHost
предоставляет методы setPlaybackRow(Row row)
и setPlaybackRowPresenter(PlaybackRowPresenter presenter)
. Стоит отметить, что эти методы не действуют в onCreate()
, поэтому мне либо нужно использовать обработчик, либо переместить их в onPostCreate()
:
@Override
public void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Buttons I need in my HUD
final Action skipPreviousAction = new PlaybackControlsRow.SkipPreviousAction(this); // |<
final Action rewindAction = PlaybackControlsRow.RewindAction(this); // <<
final Action playPauseAction = PlaybackControlsRow.PlayPauseAction(this);
final Action fastForwardAction = PlaybackControlsRow.FastForwardAction(this); // >>
final Action skipNextAction = PlaybackControlsRow.SkipNextAction(this); // >|
final Action repeatAction = PlaybackControlsRow.RepeatAction(this);
final PresenterSelector controlPresenterSelector = ControlButtonPresenterSelector();
final PlaybackControlsRow playbackControlsRow = PlaybackControlsRow();
final ArrayObjectAdapter primaryAdapter = ArrayObjectAdapter(controlPresenterSelector);
final ArrayObjectAdapter secondaryAdapter = ArrayObjectAdapter(controlPresenterSelector);
// First row
primaryAdapter.add(skipPreviousAction);
primaryAdapter.add(rewindAction);
primaryAdapter.add(playPauseAction);
primaryAdapter.add(fastForwardAction);
primaryAdapter.add(skipNextAction);
// Second row
secondaryAdapter.add(repeatAction);
playbackControlsRow.primaryActionsAdapter = primaryAdapter;
playbackControlsRow.secondaryActionsAdapter = secondaryAdapter;
// Applying row to glue host
glueHost.setPlaybackRowPresenter(PlaybackControlsRowPresenter());
glueHost.setPlaybackRow(playbackControlsRow);
}
Теперь у меня есть настроенная строка воспроизведения, но проигрыватель больше не реагирует на нажатия кнопок.
Мне трудно понять, как PlaybackGlue
на самом деле реагирует на события из PlaybackGlueHost
. Я знаю, что могу установить OnActionClickedListener
в презентаторе строки и обрабатывать действия вручную, но это делает модель взаимодействия клея/хоста бесполезной. Как это работало в первую очередь? Я не смог найти строку воспроизведения по умолчанию... Я вижу, что каждый Action
соответствует набору кодов клавиш, но я не уверен, что я могу с этим сделать.
Может ли кто-нибудь указать мне в правильном направлении? На удивление мало информации по этому вопросу.
Спасибо.