전송 컨트롤 사용

Compose를 사용한 효과적인 개발
Android TV OS용 Jetpack Compose를 사용하여 최소한의 코드로 멋진 UI를 만듭니다.

Leanback UI 툴킷에는 더 나은 선택과 향상된 경험을 제공하는 재생 컨트롤이 있습니다. 있습니다. 동영상 앱의 경우 전송 컨트롤에서 동영상 스크러빙을 지원합니다. 사용할 수 있습니다. 스크러빙 중에는 디스플레이에 동영상을 탐색하는 데 유용한 미리보기 이미지가 표시됩니다.

라이브러리에는 추상 클래스와 사전 빌드된 즉시 사용 가능한 구현이 포함되어 있습니다. 개발자에게 보다 세밀한 제어 기능을 제공합니다. 사전 빌드된 많은 코딩 없이도 기능이 풍부한 앱을 신속하게 빌드할 수 있습니다. 맞춤설정이 더 필요하면 라이브러리의 사전 빌드된 구성요소를 확장하면 됩니다.

컨트롤 및 플레이어

Leanback UI 툴킷은 전송 컨트롤 UI를 동영상을 재생하는 플레이어입니다. 구분하는 데 구성요소 두 개가 사용됩니다. 그중 하나는 전송 컨트롤(선택적으로 동영상)을 표시하는 재생 지원 프래그먼트이고, 다른 하나는 미디어 플레이어를 캡슐화하는 플레이어 어댑터입니다.

재생 프래그먼트

앱의 UI 활동은 PlaybackSupportFragment 또는 VideoSupportFragment를 사용해야 합니다. 둘 다 leanback 전송 컨트롤을 포함하고 있습니다.

프래그먼트의 ObjectAdapter를 맞춤설정하여 UI를 개선할 수 있습니다. 예를 들어 setAdapter()를 사용하여 '관련 동영상' 행을 추가할 수 있습니다.

PlayerAdapter

PlayerAdapter는 기본 미디어 플레이어를 제어하는 추상 클래스입니다. 개발자는 사전 빌드된 MediaPlayerAdapter 구현을 선택하거나 직접 이 클래스의 구현을 작성할 수 있습니다.

요소 연결

'컨트롤 글루'를 사용하여 재생 프래그먼트를 플레이어에 연결해야 합니다. leanback 라이브러리에서는 다음 두 종류의 글루를 제공합니다.

leanback 전송 컨트롤 글루

앱에서 동영상 스크러빙을 지원하려면 PlaybackTransportControlGlue를 사용해야 합니다.

'글루 호스트'도 지정해야 함 저것 접착제를 재생에 프래그먼트를 호출하고 UI에서 전송 컨트롤을 그리고 상태를 유지합니다. 전송 제어 이벤트를 다시 글루로 전달합니다. 이 호스트는 재생 프래그먼트 유형과 일치해야 합니다. 사용 PlaybackSupportFragmentGlueHost, PlaybackFragmentVideoSupportFragmentGlueHost, VideoFragment입니다.

이 그림은 leanback 전송 컨트롤의 요소가 어떻게 맞추기:

leanback 전송 컨트롤 글루

앱을 묶는 코드는 UI를 정의하는 PlaybackSupportFragment 또는 VideoSupportFragment 내에 있어야 합니다.

다음에서 예를 들어 앱은 PlaybackTransportControlGlue의 인스턴스를 생성합니다. 이름을 playerGlue로 지정하고 VideoSupportFragment를 새로 생성된 MediaPlayerAdapter에 연결합니다. 이후 VideoSupportFragment입니다. 설정 코드가 setHost()를 호출하여 VideoSupportFragmentGlueHost에서 playerGlue(으)로 코드는 클래스 내에 포함되어 있습니다. VideoSupportFragment를 확장합니다.

Kotlin

class MyVideoFragment : VideoSupportFragment() {

  fun onCreate(savedInstanceState: Bundle) {
      super.onCreate(savedInstanceState)
      val playerGlue = PlaybackTransportControlGlue(getActivity(),
          MediaPlayerAdapter(getActivity()))
      playerGlue.setHost(VideoSupportFragmentGlueHost(this))
      playerGlue.addPlayerCallback(object : PlaybackGlue.PlayerCallback() {
          override fun onPreparedStateChanged(glue: PlaybackGlue) {
              if (glue.isPrepared()) {
                  playerGlue.seekProvider = MySeekProvider()
                  playerGlue.play()
              }
          }
      })
      playerGlue.setSubtitle("Leanback artist")
      playerGlue.setTitle("Leanback team at work")
      val uriPath = "android.resource://com.example.android.leanback/raw/video"
      playerGlue.getPlayerAdapter().setDataSource(Uri.parse(uriPath))
  }
}

자바

public class MyVideoFragment extends VideoSupportFragment {

  @Override
  public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      final PlaybackTransportControlGlue<MediaPlayerAdapter> playerGlue =
              new PlaybackTransportControlGlue(getActivity(),
                      new MediaPlayerAdapter(getActivity()));
      playerGlue.setHost(new VideoSupportFragmentGlueHost(this));
      playerGlue.addPlayerCallback(new PlaybackGlue.PlayerCallback() {
          @Override
          public void onPreparedStateChanged(PlaybackGlue glue) {
              if (glue.isPrepared()) {
                  playerGlue.setSeekProvider(new MySeekProvider());
                  playerGlue.play();
              }
          }
      });
      playerGlue.setSubtitle("Leanback artist");
      playerGlue.setTitle("Leanback team at work");
      String uriPath = "android.resource://com.example.android.leanback/raw/video";
      playerGlue.getPlayerAdapter().setDataSource(Uri.parse(uriPath));
  }
}

설정 코드는 미디어 플레이어에서 발생한 이벤트를 처리하는 PlayerAdapter.Callback도 정의합니다.

UI 글루 맞춤설정

사용자는 PlaybackBannerControlGluePlaybackTransportControlGluePlaybackControlsRow입니다.

제목과 설명 맞춤설명

재생 컨트롤 상단에 표시되는 제목과 설명을 맞춤설정하려면 onCreateRowPresenter()를 재정의하세요.

Kotlin

override fun onCreateRowPresenter(): PlaybackRowPresenter {
    return super.onCreateRowPresenter().apply {
        (this as? PlaybackTransportRowPresenter)
                ?.setDescriptionPresenter(MyCustomDescriptionPresenter())
    }
}

자바

@Override
protected PlaybackRowPresenter onCreateRowPresenter() {
  PlaybackTransportRowPresenter presenter = (PlaybackTransportRowPresenter) super.onCreateRowPresenter();
  presenter.setDescriptionPresenter(new MyCustomDescriptionPresenter());
  return presenter;
}

컨트롤 추가

컨트롤 글루에서는 PlaybackControlsRow에 작업 컨트롤을 표시합니다.

PlaybackControlsRow의 작업 두 그룹(기본 작업보조 작업)에 할당됩니다. 작업을 참조하세요. 기본 그룹용 컨트롤은 탐색 막대 위에, 보조 그룹용 컨트롤은 탐색 막대 아래에 표시됩니다. 처음에는 기본 액션이 하나만 있습니다. 재생/일시중지 버튼에 해당하며 보조 작업은 없습니다.

다음을 재정의하여 기본 및 보조 그룹에 작업을 추가할 수 있습니다. onCreatePrimaryActions()onCreateSecondaryActions()

Kotlin

private lateinit var repeatAction: PlaybackControlsRow.RepeatAction
private lateinit var pipAction: PlaybackControlsRow.PictureInPictureAction
private lateinit var thumbsUpAction: PlaybackControlsRow.ThumbsUpAction
private lateinit var thumbsDownAction: PlaybackControlsRow.ThumbsDownAction
private lateinit var skipPreviousAction: PlaybackControlsRow.SkipPreviousAction
private lateinit var skipNextAction: PlaybackControlsRow.SkipNextAction
private lateinit var fastForwardAction: PlaybackControlsRow.FastForwardAction
private lateinit var rewindAction: PlaybackControlsRow.RewindAction

override fun onCreatePrimaryActions(primaryActionsAdapter: ArrayObjectAdapter) {
    // Order matters, super.onCreatePrimaryActions() will create the play / pause action.
    // Will display as follows:
    // play/pause, previous, rewind, fast forward, next
    //   > /||      |<        <<        >>         >|
    super.onCreatePrimaryActions(primaryActionsAdapter)
    primaryActionsAdapter.apply {
        add(skipPreviousAction)
        add(rewindAction)
        add(fastForwardAction)
        add(skipNextAction)
    }
}

override fun onCreateSecondaryActions(adapter: ArrayObjectAdapter?) {
    super.onCreateSecondaryActions(adapter)
    adapter?.apply {
        add(thumbsDownAction)
        add(thumbsUpAction)
    }
}

자바

private PlaybackControlsRow.RepeatAction repeatAction;
private PlaybackControlsRow.PictureInPictureAction pipAction;
private PlaybackControlsRow.ThumbsUpAction thumbsUpAction;
private PlaybackControlsRow.ThumbsDownAction thumbsDownAction;
private PlaybackControlsRow.SkipPreviousAction skipPreviousAction;
private PlaybackControlsRow.SkipNextAction skipNextAction;
private PlaybackControlsRow.FastForwardAction fastForwardAction;
private PlaybackControlsRow.RewindAction rewindAction;

@Override
protected void onCreatePrimaryActions(ArrayObjectAdapter primaryActionsAdapter) {
    // Order matters, super.onCreatePrimaryActions() will create the play / pause action.
    // Will display as follows:
    // play/pause, previous, rewind, fast forward, next
    //   > /||      |<        <<        >>         >|
    super.onCreatePrimaryActions(primaryActionsAdapter);
    primaryActionsAdapter.add(skipPreviousAction);
    primaryActionsAdapter.add(rewindAction);
    primaryActionsAdapter.add(fastForwardAction);
    primaryActionsAdapter.add(skipNextAction);
}

@Override
protected void onCreateSecondaryActions(ArrayObjectAdapter adapter) {
    super.onCreateSecondaryActions(adapter);
    adapter.add(thumbsDownAction);
    adapter.add(thumbsUpAction);
}

재정의해야 함 onActionClicked(): 새 작업을 처리합니다.

Kotlin

override fun onActionClicked(action: Action) {
    when(action) {
        rewindAction -> {
            // Handle Rewind
        }
        fastForwardAction -> {
            // Handle FastForward
        }
        thumbsDownAction -> {
            // Handle ThumbsDown
        }
        thumbsUpAction -> {
            // Handle ThumbsUp
        }
        else ->
            // The superclass handles play/pause and delegates next/previous actions to abstract methods,
            // so those two methods should be overridden rather than handling the actions here.
            super.onActionClicked(action)
    }
}

override fun next() {
    // Skip to next item in playlist.
}

override fun previous() {
    // Skip to previous item in playlist.
}

자바

@Override
public void onActionClicked(Action action) {
    if (action == rewindAction) {
        // Handle Rewind
    } else if (action == fastForwardAction ) {
        // Handle FastForward
    } else if (action == thumbsDownAction) {
        // Handle ThumbsDown
    } else if (action == thumbsUpAction) {
        // Handle ThumbsUp
    } else {
        // The superclass handles play/pause and delegates next/previous actions to abstract methods,
        // so those two methods should be overridden rather than handling the actions here.
        super.onActionClicked(action);
    }
}

@Override
public void next() {
    // Skip to next item in playlist.
}

@Override
public void previous() {
    // Skip to previous item in playlist.
}

특별한 경우에는 PlaybackTransportRowPresenter 를 사용하여 맞춤 컨트롤을 렌더링하고 PlaybackSeekUi

동영상 스크러빙

앱에서 VideoSupportFragment를 사용하며 동영상 스크러빙을 지원하려는 경우

스크러빙

PlaybackSeekDataProvider 구현을 제공해야 합니다. 이 구성요소는 스크롤할 때 사용되는 동영상 미리보기 이미지를 제공합니다. 다음을 확장하여 자체 제공자를 구현해야 합니다. PlaybackSeekDataProvider 다음 예제를 참조하세요. <ph type="x-smartling-placeholder"></ph> Leanback 쇼케이스 앱에 설명되어 있습니다. 에서 자세한 내용을 확인하실 수 있습니다.