Android TV 홈 화면 채널과 콘텐츠 통합(Kotlin)

이 Codelab에서는 Android TV 홈 화면에 채널과 프로그램을 추가하는 앱을 Kotlin 및 AndroidX 라이브러리를 사용하여 빌드하는 방법을 알아봅니다. 홈 화면에는 이 Codelab에서 다루는 것보다 더 많은 기능이 있습니다. 홈 화면의 모든 기능을 알아보려면 이 문서를 확인하세요.

개념

Android TV 홈 화면(간단히 홈 화면)에는 추천 콘텐츠가 채널 및 프로그램 목록으로 표시된 UI가 있습니다. 각 행이 채널입니다. 채널에는 이 채널에서 볼 수 있는 각 프로그램을 나타내는 카드가 포함되어 있습니다. 앱은 사용자가 홈 화면에 추가하는 여러 채널을 제공할 수 있습니다. 일반적으로 사용자가 각 채널을 선택하고 승인해야 채널이 홈 화면에 표시됩니다.

모든 앱에는 하나의 기본 채널을 만드는 옵션이 있습니다. 기본 채널의 특징은 사용자가 명시적으로 요청하지 않아도 홈 화면에 자동으로 표시된다는 점입니다.

aa0471dc91b5f815.png

개요

이 Codelab에서는 홈 화면에서 채널과 프로그램을 만들고 추가하고 업데이트하는 방법을 보여 줍니다. 컬렉션 및 영화의 모의 데이터베이스를 사용합니다. 단순화하기 위해 동일한 영화 목록이 모든 구독에 사용됩니다.

시작 프로젝트 저장소 클론

이 Codelab에서는 Android 앱 개발을 위한 IDE인 Android 스튜디오를 사용합니다.

아직 설치하지 않았다면 다운로드하여 설치하세요.

GitHub 저장소에서 소스 코드를 다운로드할 수 있습니다.

git clone https://github.com/googlecodelabs/tv-recommendations-kotlin.git

또는 ZIP 파일로 다운로드할 수 있습니다.

ZIP 파일 다운로드

Android 스튜디오를 열고 메뉴 바에서 File > Open을 클릭하거나 스플래시 화면에서 Open an Existing Android Studio Project를 클릭한 후 최근에 클론한 폴더를 선택합니다.

c0e57864138c1248.png

시작 프로젝트 이해

bd4f805254260df7.png

프로젝트에는 4단계가 있습니다. 각 단계에서 앱에 코드를 더 많이 추가하고 각 섹션의 모든 안내대로 완료한 후에 결과를 다음 단계의 코드와 비교할 수 있습니다.

앱의 기본 구성요소는 다음과 같습니다.

  • MainActivity는 프로젝트의 진입 활동입니다.
  • model/TvMediaBackground는 영화를 탐색하는 동안 배경 이미지용 객체입니다.
  • model/TvMediaCollection은 영화 컬렉션의 객체입니다.
  • model/TvMediaMetadata는 영화 정보를 저장하는 객체입니다.
  • model/TvMediaDatabase는 데이터베이스 홀더이며 기본 영화 데이터를 위한 기본 액세스 포인트 역할을 합니다.
  • fragments/NowPlayingFragment는 영화를 재생합니다.
  • fragments/MediaBrowserFragment는 미디어 브라우저 프래그먼트입니다.
  • workers/TvMediaSynchronizer는 피드 가져오기, 객체 구성, 채널 업데이트를 위한 코드가 포함된 데이터 동기화 클래스입니다.
  • utils/TvLauncherUtils는 AndroidX 라이브러리 및 TV 제공자를 사용하여 채널과 미리보기 프로그램을 관리하는 도우미 클래스입니다.

시작 프로젝트 실행

프로젝트를 실행해 봅니다. 문제가 발생하는 경우 이 문서에서 시작하는 방법을 참고하세요.

  1. Android TV를 연결하거나 에뮬레이터를 시작합니다.
  1. step_1 구성을 선택하고 Android 기기를 선택한 후 메뉴 바에서 run 버튼을 누릅니다. ba443677e48e0f00.png
  2. 동영상 컬렉션 3개로 구성된 간단한 TV 앱 개요가 표시됩니다.

364574330c4e90a5.png

학습한 내용

소개 섹션에서는 다음에 관해 알아봤습니다.

  • TV 홈 화면과 채널
  • 이 Codelab의 프로젝트 코드 구조 및 주요 클래스

다음 단계

홈 화면에 채널 추가

먼저 홈 화면에 채널을 추가합니다. 채널이 추가된 후에는 채널에 프로그램을 삽입할 수 있습니다. 사용자는 채널 구성 패널에서 채널을 검색하고 홈 UI에 표시할 채널을 선택할 수 있습니다. 이 Codelab에서는 각 미디어 컬렉션의 채널을 만듭니다.

  • 역사 장편 영화
  • 1910년대 장편 영화
  • 찰리 채플린 컬렉션

다음 섹션에서는 데이터를 로드하여 채널에 사용하는 방법을 설명합니다.

TvMediaSynchronizersynchronize() 메서드는 다음을 처리합니다.

  1. 배경 이미지, 미디어 컬렉션, 동영상 메타데이터가 포함된 미디어 피드를 가져옵니다. 이 정보는 assets/media-feed.json에 정의되어 있습니다.
  2. 백그라운드 이미지, 미디어 컬렉션, 동영상 데이터를 각 객체에 저장하는 TvMediaDatabase 인스턴스를 업데이트합니다.
  3. TvLauncherUtils를 사용하여 채널과 프로그램을 만들거나 업데이트합니다.

이 Codelab의 데이터 로딩은 걱정하지 않아도 됩니다. 목표는 AndroidX 라이브러리를 사용하여 채널을 만드는 방법을 이해하는 것입니다. 이렇게 하려면 TvLauncherUtils 클래스의 일부 메서드에 코드를 추가합니다.

채널 만들기

미디어 데이터를 가져와 로컬 데이터베이스에 저장한 후에는 프로젝트 코드가 미디어 Collection을 채널로 변환합니다. 이 코드는 TvLauncherUtils 클래스의 upsertChannel() 메서드에서 채널을 만들고 업데이트합니다.

  1. PreviewChannel.Builder() 인스턴스를 생성합니다. 중복 채널을 피하기 위해 이 Codelab에서는 채널이 존재하는지 확인하고 채널이 있는 경우에만 업데이트합니다. 각 동영상 컬렉션에는 연결된 ID가 있으며, 이 ID를 채널의 internalProviderId로 사용할 수 있습니다. 기존 채널을 식별하려면 internalProviderId를 컬렉션 ID와 비교합니다. 다음 코드를 복사하여 upsertChannel()의 코드 주석 // TODO: Step 1 create or find an existing channel.에 붙여넣습니다.
val channelBuilder = if (existingChannel == null) {
   PreviewChannel.Builder()
} else {
   PreviewChannel.Builder(existingChannel)
}
  1. Builder에서 채널의 속성(예: 채널 이름, 로고/아이콘)을 설정합니다. 표시 이름은 홈 화면에서 채널 아이콘 바로 아래에 표시됩니다. Android TV에서는 사용자가 채널 아이콘을 클릭할 때 appLinkIntentUri를 사용하여 사용자를 안내합니다. 이 Codelab에서는 이 URI를 사용하여 사용자를 앱의 상응하는 컬렉션으로 안내합니다. 다음 코드를 복사하여 코드 주석 // TODO: Step 2 add collection metadata and build channel object에 붙여넣습니다.
val updatedChannel = channelBuilder
       .setInternalProviderId(collection.id)
       .setLogo(channelLogoUri)
       .setAppLinkIntentUri(appUri)
       .setDisplayName(collection.title)
       .setDescription(collection.description)
       .build()
  1. PreviewChannelHelper 클래스의 함수를 호출하여 채널을 TV 제공자에 삽입하거나 업데이트합니다. publishChannel()을 호출하면 채널의 콘텐츠 값이 TV 제공자에 삽입됩니다. updatePreviewChannel은 기존 채널을 업데이트합니다. 다음 코드를 코드 주석 // TODO: Step 3.1 update an existing channel에 삽입합니다.
PreviewChannelHelper(context)
       .updatePreviewChannel(existingChannel.id, updatedChannel)
Log.d(TAG, "Updated channel ${existingChannel.id}")

아래 코드를 코드 주석 // TODO: Step 3.2 publish a channel에 삽입하여 새 채널을 만듭니다.

val channelId = PreviewChannelHelper(context).publishChannel(updatedChannel)
Log.d(TAG, "Published channel $channelId")
channelId
  1. upsertChannel() 메서드를 검토하여 채널이 생성되거나 업데이트되는 방법을 알아봅니다.

기본 채널 표시

채널을 TV 제공자에 추가했을 때 채널은 표시되지 않습니다. 채널은 사용자가 요청할 때까지는 홈 화면에 표시되지 않습니다. 일반적으로 사용자가 각 채널을 선택하고 승인해야 채널이 홈 화면에 표시됩니다. 모든 앱에는 하나의 기본 채널을 만드는 옵션이 있습니다. 기본 채널은 자동으로 홈 화면에 표시되므로 특수하며, 사용자가 명시적으로 승인할 필요가 없습니다.

다음 코드를 upsertChannel() 메서드의 TODO: step 4 make default channel visible에 추가합니다.

if(allChannels.none { it.isBrowsable }) {
   TvContractCompat.requestChannelBrowsable(context, channelId)
}

기본이 아닌 채널의 requestChannelBrowsable()을 호출하면 사용자의 동의를 요청하는 대화상자가 표시됩니다.

채널 업데이트 예약

채널 생성/업데이트 코드를 추가한 후 개발자는 synchronize() 메서드를 호출하여 채널을 만들거나 업데이트해야 합니다.

앱의 채널을 만드는 최적의 시점은 사용자가 앱을 설치한 직후입니다. android.media.tv.action.INITIALIZE_PROGRAMS 브로드캐스트 메시지를 수신 대기할 broadcast receiver를 만들 수 있습니다. 이 브로드캐스트는 사용자가 TV 앱을 설치한 후에 전송되며, 개발자는 일부 프로그램을 초기화할 수 있습니다.

샘플 코드에서 AndroidManifest.xml 파일을 확인하고 broadcast receiver 섹션을 찾습니다. broadcast receiver의 올바른 클래스 이름을 찾습니다(다음 섹션에서 다룸).

<action
   android:name="android.media.tv.action.INITIALIZE_PROGRAMS" />

TvLauncherReceiver 클래스를 열고 다음 코드 블록을 살펴보고 샘플 앱이 홈 화면 채널을 만드는 방법을 확인합니다.

TvContractCompat.ACTION_INITIALIZE_PROGRAMS -> {
   Log.d(TAG, "Handling INITIALIZE_PROGRAMS broadcast")
   // Synchronizes all program and channel data
   WorkManager.getInstance(context).enqueue(
           OneTimeWorkRequestBuilder<TvMediaSynchronizer>().build())
}

채널을 정기적으로 업데이트해야 합니다. 이 Codelab에서는 WorkManager 라이브러리를 사용하여 백그라운드 작업을 만듭니다. MainActivity 클래스에서 TvMediaSynchronizer는 일반 채널 업데이트를 예약하는 데 사용됩니다.

// Syncs the home screen channels hourly
// NOTE: It's very important to keep our content fresh in the user's home screen
WorkManager.getInstance(baseContext).enqueue(
       PeriodicWorkRequestBuilder<TvMediaSynchronizer>(1, TimeUnit.HOURS)
               .setInitialDelay(1, TimeUnit.HOURS)
               .setConstraints(Constraints.Builder()
                       .setRequiredNetworkType(NetworkType.CONNECTED)
                       .build())
               .build())

앱 실행

앱을 실행하고 홈 화면으로 이동합니다. 기본(My TV App Default) 채널이 나타나지만 여기에 프로그램이 없습니다. 에뮬레이터가 아닌 실제 기기에서 코드를 실행하는 경우에는 채널이 표시되지 않을 수도 있습니다.

f14e903b0505a281.png

채널 추가

피드에 컬렉션 세 개가 포함되어 있습니다. TvMediaSynchronizer 클래스의 TODO: step 5 add more channels에 이 컬렉션에 관한 다른 채널을 추가합니다.

feed.collections.subList(1, feed.collections.size).forEach {
   TvLauncherUtils.upsertChannel(
           context, it, database.metadata().findByCollection(it.id))
}

앱 다시 실행

세 채널이 모두 만들어졌는지 확인합니다. Customize Channels 버튼을 클릭한 다음 TV Classics를 클릭합니다. 채널 패널에서 숨기기/표시 버튼을 전환하여 홈 화면에 채널을 숨기거나 표시합니다.

faac02714aa36ab6.png

채널 삭제

앱에서 더 이상 채널을 유지관리하지 않는 경우 홈 화면에서 채널을 삭제할 수 있습니다.

6단계를 검색한 후 removeChannel 함수를 찾습니다. 다음 섹션을 함수의 TODO: step 6 remove a channel에 추가합니다. 이 코드가 어떻게 작동하는지 확인하려면 media-feed.json에서 'Charlie Chaplin Collection'이라는 컬렉션을 삭제합니다(전체 컬렉션을 삭제해야 함). 앱을 다시 실행하면 몇 초 후에 채널이 삭제된 것을 확인할 수 있습니다.

// First, get all the channels added to the home screen
val allChannels = PreviewChannelHelper(context).allChannels

// Now find the channel with the matching content ID for our collection
val foundChannel = allChannels.find { it.internalProviderId == collection.id }
if (foundChannel == null) Log.e(TAG, "No channel with ID ${collection.id}")

// Use the found channel's ID to delete it from the content resolver
return foundChannel?.let {
   PreviewChannelHelper(context).deletePreviewChannel(it.id)
   Log.d(TAG, "Channel successfully removed from home screen")

   // Remove all of the channel programs as well
   val channelPrograms =
           TvContractCompat.buildPreviewProgramsUriForChannel(it.id)
   context.contentResolver.delete(channelPrograms, null, null)

   // Return the ID of the channel removed
   it.id
}

위의 안내대로 모두 완료한 후에는 앱 코드를 step_2와 비교할 수 있습니다.

학습한 내용

  • 채널을 쿼리하는 방법
  • 홈 화면에 채널을 추가하거나 홈 화면에서 채널을 삭제하는 방법
  • 채널에 로고나 제목을 설정하는 방법
  • 기본 채널을 표시하는 방법
  • 채널을 업데이트하도록 WorkManager를 예약하는 방법

다음 단계

다음 섹션에서는 채널에 프로그램을 추가하는 방법을 알아봅니다.

채널에 프로그램을 추가하는 것은 채널을 만드는 것과 비슷합니다. PreviewChannel.Builder 대신 PreviewProgram.Builder를 사용합니다.

TvLauncherUtils 클래스의 upsertChannel() 메서드를 계속 사용합니다.

미리보기 프로그램 만들기

다음 섹션에서 step_2에 코드를 추가할 것입니다. Android 스튜디오 프로젝트에서 모듈의 소스 파일을 변경해야 합니다.

e096c4d12a3d0a01.png

채널이 표시된 것을 확인한 후에는 PreviewProgram.BuilderMetadata 객체를 사용하여 PreviewProgram 객체를 만듭니다. 이 경우에도 동일한 프로그램을 한 채널에 두 번 삽입하면 안 되므로 중복을 방지하기 위해 샘플은 metadata.idPreviewProgramcontentId에 할당합니다. 다음 코드를 TODO: Step 7 create or find an existing preview program에 추가합니다.

val existingProgram = existingProgramList.find { it.contentId == metadata.id }
val programBuilder = if (existingProgram == null) {
   PreviewProgram.Builder()
} else {
   PreviewProgram.Builder(existingProgram)
}

미디어 메타데이터가 포함된 빌더를 빌드하여 채널에 게시/업데이트합니다. (TODO: Step 8 build preview program and publish)

val updatedProgram = programBuilder.also { metadata.copyToBuilder(it) }
       // Set the same channel ID in all programs
       .setChannelId(channelId)
       // This must match the desired intent filter in the manifest for VIEW action
       .setIntentUri(Uri.parse("https://$host/program/${metadata.id}"))
       // Build the program at once
       .build()

여기서 다음을 주목하세요.

  1. 샘플 코드는 contentId를 통해 메타데이터를 미리보기 프로그램과 연결합니다.
  2. PreviewProgram.Builder()에서 setChannelId()를 호출하면 미리보기 프로그램이 채널에 삽입됩니다.
  3. 사용자가 채널에서 프로그램을 선택하면 Android TV 시스템에서 프로그램의 intentUri를 실행합니다. Uri에 프로그램 ID가 포함되어야 사용자가 프로그램을 선택하면 앱이 데이터베이스에서 미디어를 찾고 재생할 수 있습니다.

프로그램 추가

여기서는 이 Codelab이 AndroidX 라이브러리의 PreviewChannelHelper를 사용하여 채널에 프로그램을 삽입합니다.

PreviewChannelHelper.publishPreviewProgram() 또는 PreviewChannelHelper.updatePreviewProgram()을 사용하여 프로그램에 채널을 저장합니다(TODO: Step 9 add preview program to channel).

try {
   if (existingProgram == null) {
       PreviewChannelHelper(context).publishPreviewProgram(updatedProgram)
       Log.d(TAG, "Inserted program into channel: $updatedProgram")
   } else {
       PreviewChannelHelper(context)
               .updatePreviewProgram(existingProgram.id, updatedProgram)
       Log.d(TAG, "Updated program in channel: $updatedProgram")
   }
} catch (exc: IllegalArgumentException) {
   Log.e(TAG, "Unable to add program: $updatedProgram", exc)
}

좋습니다. 이제 앱이 채널에 프로그램을 추가합니다. 코드를 step_3과 비교할 수 있습니다.

앱 실행

구성에서 step_2를 선택하고 앱을 실행합니다.

200e69351ce6a530.png

앱이 실행되면 홈 화면 하단에서 채널 맞춤설정 버튼을 클릭하고 'TV Classics' 앱을 찾습니다. 세 채널을 전환하며 로그를 살펴보고 진행 상황을 확인합니다. 채널 및 프로그램 생성은 백그라운드에서 이루어지므로, 트리거된 이벤트를 추적하는 데 도움이 되는 로그 구문을 언제든지 추가할 수 있습니다.

학습한 내용

  • 채널에 프로그램을 추가하는 방법
  • 프로그램의 속성을 업데이트하는 방법

다음 단계

다음 볼만한 동영상 채널에 프로그램을 추가합니다.

다음 볼만한 동영상 채널은 홈 화면 상단에 있습니다. Apps 아래, 다른 모든 채널 위에 표시됩니다.

44b6a6f24e4420e3.png

개념

다음 볼만한 동영상 채널은 앱에서 사용자의 참여를 유도하는 방법을 제공합니다. 앱은 사용자가 관심 항목으로 표시한 프로그램, 사용자가 도중에 시청을 중단한 프로그램, 사용자가 시청하고 있는 콘텐츠와 관련된 프로그램(예: 시리즈의 다음 에피소드, 프로그램의 다음 시즌) 등을 다음 볼만한 동영상 채널에 추가할 수 있습니다. 다음 볼만한 동영상 채널의 사용 사례는 4가지입니다.

  • 사용자가 완료하지 않은 동영상을 계속 시청합니다.
  • 볼 만한 다음 동영상을 추천합니다. 예를 들어 사용자가 에피소드 1을 시청했다면 에피소드 2를 제안할 수 있습니다.
  • 새로운 콘텐츠를 표시하여 참여를 유도합니다.
  • 사용자가 추가한 흥미로운 동영상 관심 목록을 유지합니다.

이 과정에서는 다음 볼만한 동영상 채널을 사용하여 동영상을 계속 시청하는 방법, 특히 사용자가 일시중지한 경우 동영상을 다음 볼만한 동영상 채널에 포함하는 방법을 알아봅니다. 동영상이 끝까지 재생되면 다음 볼만한 동영상 채널에서 삭제되어야 합니다.

재생 위치 업데이트

다음과 같은 방법으로 콘텐츠의 재생 위치를 추적할 수 있습니다. 이 Codelab에서는 스레드를 사용하여 최근 재생 위치를 정기적으로 데이터베이스에 저장하고 다음 볼만한 동영상 프로그램의 메타데이터를 새로고침합니다. step_3을 열고 아래의 안내에 따라 이 코드를 추가하세요.

NowPlayingFragment에서 updateMetadataTask.run() 메서드(TODO: step 10 update progress)에 다음 코드를 추가합니다.

val contentDuration = player.duration
val contentPosition = player.currentPosition

// Updates metadata state
val metadata = args.metadata.apply {
   playbackPositionMillis = contentPosition
}

이 코드는 재생 위치가 총 길이의 95% 미만인 경우에만 메타데이터를 저장합니다.

다음 코드를 추가합니다(TODO: step 11 update metadata to database).

val programUri = TvLauncherUtils.upsertWatchNext(requireContext(), metadata)
lifecycleScope.launch(Dispatchers.IO) {
   database.metadata().update(
           metadata.apply { if (programUri != null) watchNext = true })
}

재생 위치가 동영상의 95%를 지난 경우에는 다른 콘텐츠가 우선순위가 될 수 있도록 다음 볼만한 동영상 프로그램이 삭제됩니다.

완료된 동영상을 다음 볼만한 동영상 행에서 삭제하도록 다음 코드를 NowPlayingFragmentTODO: step 12 remove 다음 볼만한 동영상에 추가합니다.

val programUri = TvLauncherUtils.removeFromWatchNext(requireContext(), metadata)
if (programUri != null) lifecycleScope.launch(Dispatchers.IO) {
   database.metadata().update(metadata.apply { watchNext = false })
}

최신 재생 위치를 추적할 수 있도록 updateMetadataTask는 10초에 한 번으로 예약됩니다. NowPlayingFragmentonResume()에서 예약되고 onPause()에서 중지되어, 사용자가 동영상을 시청할 때만 데이터가 업데이트됩니다.

다음 볼만한 동영상 프로그램 추가/업데이트

TvLauncherUtils는 TV 제공자와 상호작용합니다. 이전 단계에서 TvLauncherUtilsremoveFromWatchNextupsertWatchNext가 호출됩니다. 이제 이 두 메서드를 구현해야 합니다. AndroidX 라이브러리는 이 작업을 크게 간소화하는 PreviewChannelHelper 클래스를 제공합니다.

먼저 WatchNextProgram.Builder의 기존 인스턴스를 만들거나 찾은 다음 최신 재생 metadata로 객체를 업데이트합니다. 다음 코드를 upsertWatchNext() 메서드의 TODO: step 13 build watch next program에 추가합니다.

programBuilder.setLastEngagementTimeUtcMillis(System.currentTimeMillis())

programBuilder.setWatchNextType(metadata.playbackPositionMillis?.let { position ->
   if (position > 0 && metadata.playbackDurationMillis?.let { it > 0 } == true) {
       Log.d(TAG, "Inferred watch next type: CONTINUE")
       TvContractCompat.WatchNextPrograms.WATCH_NEXT_TYPE_CONTINUE
   } else {
       Log.d(TAG, "Inferred watch next type: UNKNOWN")
       WatchNextProgram.WATCH_NEXT_TYPE_UNKNOWN
   }
} ?: TvContractCompat.WatchNextPrograms.WATCH_NEXT_TYPE_NEXT)

// This must match the desired intent filter in the manifest for VIEW intent action
programBuilder.setIntentUri(Uri.parse(
       "https://${context.getString(R.string.host_name)}/program/${metadata.id}"))

// Build the program with all the metadata
val updatedProgram = programBuilder.build()

WatchNextProgram.Builder에서 build( 메서드를 호출하면 WatchNextProgam이 생성됩니다. PreviewChannelHelper를 사용하여 프로그램을 다음 볼만한 동영상 행에 게시할 수 있습니다.

다음 코드를 TODO: step 14.1 create watch next program에 추가합니다.

val programId = PreviewChannelHelper(context)
       .publishWatchNextProgram(updatedProgram)
Log.d(TAG, "Added program to watch next row: $updatedProgram")
programId

기존에 프로그램이 있는 경우에는 TODO: step 14.2 update watch next program에서 업데이트하면 됩니다.

PreviewChannelHelper(context)
       .updateWatchNextProgram(updatedProgram, existingProgram.id)
Log.d(TAG, "Updated program in watch next row: $updatedProgram")
existingProgram.id

다음 볼만한 동영상 프로그램 삭제

사용자의 동영상 재생이 완료되면 다음 볼만한 동영상 채널을 삭제해야 합니다. PreviewProgram을 삭제하는 것과 거의 같습니다.

buildWatchNextProgramUri()를 사용하여 삭제를 실행하는 Uri를 만듭니다. PreviewChannelHelper에는 다음 볼만한 동영상 프로그램을 삭제하는 데 사용할 수 있는 API가 없습니다.

TvLauncherUtils 클래스의 removeFromWatchNext()메서드에서(TODO: step 15 remove program) 기존 코드를 아래 문으로 바꿉니다.

val programUri = TvContractCompat.buildWatchNextProgramUri(it.id)
val deleteCount = context.contentResolver.delete(
       programUri, null, null)

앱 실행

구성에서 step_3을 선택하고 앱을 실행합니다.

6e43dc24a1ef0273.png

컬렉션의 동영상을 몇 초 동안 시청하다가 플레이어를 일시중지합니다(에뮬레이터를 사용하는 경우 스페이스바를 누름). 홈 화면으로 돌아가면 영화가 다음 볼만한 동영상 채널에 추가된 것을 볼 수 있습니다. 다음 볼만한 동영상 채널에서 같은 영화를 선택하면 일시중지된 위치에서 콘텐츠가 계속 재생됩니다. 전체 영화를 시청한 후에는 다음 볼만한 동영상 채널에서 삭제해야 합니다. 다양한 사용자 시나리오로 다음 볼만한 동영상 채널을 실험해 봅니다.

학습한 내용

  • 다음 볼만한 동영상 채널에 프로그램을 추가하여 참여를 유도하는 방법
  • 다음 볼만한 동영상 채널에서 프로그램을 업데이트하는 방법
  • 다음 볼만한 동영상 채널에서 프로그램을 삭제하는 방법

다음 단계

Codelab을 완료한 후에는 나만의 앱을 만들어 보세요. 미디어 피드 및 데이터 모델을 자체 피드와 모델로 바꾸고 TV 제공자의 채널 및 프로그램으로 변환합니다.

자세한 내용은 이 문서를 참고하세요.