홈 화면 채널

Android TV 홈 화면 또는 간단히 홈 화면은 추천 콘텐츠를 채널프로그램의 표로 표시하는 UI를 제공합니다. 각 행이 채널입니다. 채널에는 이 채널에서 볼 수 있는 모든 프로그램의 카드가 포함되어 있습니다.

TV 홈 화면

이 페이지에서는 채널과 프로그램을 홈 화면에 추가하고, 콘텐츠를 업데이트하고, 사용자 작업을 처리하고, 사용자에게 최고의 환경을 제공하는 방법을 보여줍니다. (API를 자세히 살펴보려면 홈 화면 Codelab을 사용해 보고 I/O 2017 Android TV 세션을 시청하세요.)

참고: 추천 채널은 Android 8.0 (API 수준 26) 이상에서만 사용할 수 있습니다. Android 8.0 (API 수준 26) 이상에서 실행되는 앱을 위한 추천을 제공하는 데 사용해야 합니다. 이전 버전의 Android에서 실행되는 앱에 추천을 제공하려면 대신 앱에서 추천 행을 사용해야 합니다.

홈 화면 UI

앱은 새 채널을 만들고 프로그램을 채널에 추가, 삭제 및 업데이트하며 채널의 프로그램 순서를 제어할 수 있습니다. 예를 들어, 앱에서 '새로운 기능'이라는 채널을 만들고 새로 공개된 프로그램의 카드를 표시할 수 있습니다.

앱은 채널이 홈 화면에 나타나는 순서를 제어할 수 없습니다. 앱에서 새 채널을 만들면 이 채널이 홈 화면에서 채널 목록의 하단에 추가됩니다. 사용자가 채널을 재정렬하고 숨기고 표시할 수 있습니다.

다음 볼만한 동영상 채널

다음 볼만한 동영상 채널은 홈 화면에서 앱 행 다음에 표시되는 두 번째 행입니다. 시스템에서 이 채널을 만들고 유지합니다. 앱은 다음 볼만한 동영상 채널에 프로그램을 추가할 수 있습니다. 자세한 내용은 다음 볼만한 동영상 채널에 프로그램 추가를 참고하세요.

앱 채널

앱에서 만드는 채널은 모두 다음 수명 주기를 따릅니다.

  1. 사용자가 앱에서 채널을 탐색하여 홈 화면에 추가하도록 요청합니다.
  2. 앱에서 채널을 만들어 TvProvider에 추가합니다(이 시점에는 이 채널이 표시되지 않음).
  3. 앱이 시스템에 이 채널을 표시하도록 요청합니다.
  4. 시스템이 사용자에게 새 채널을 승인하도록 요청합니다.
  5. 새 채널이 홈 화면의 마지막 행에 표시됩니다.

기본 채널

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

기본 요건

Android TV 홈 화면에서는 Android의 TvProvider API를 사용하여 앱에서 만드는 채널과 프로그램을 관리합니다. 제공자의 데이터에 액세스하려면 앱의 매니페스트에 다음 권한을 추가하세요.

<uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA" />

TvProvider 지원 라이브러리를 통해 제공자를 더욱 쉽게 사용할 수 있습니다. 이 라이브러리를 build.gradle 파일의 종속 항목에 추가하세요.

Groovy

implementation 'androidx.tvprovider:tvprovider:1.0.0'

Kotlin

implementation("androidx.tvprovider:tvprovider:1.0.0")

채널 및 프로그램 작업을 실행하려면 이러한 지원 라이브러리 가져오기를 프로그램에 포함해야 합니다.

Kotlin

import android.support.media.tv.Channel
import android.support.media.tv.TvContractCompat
import android.support.media.tv.ChannelLogoUtils
import android.support.media.tv.PreviewProgram
import android.support.media.tv.WatchNextProgram

Java

import android.support.media.tv.Channel;
import android.support.media.tv.TvContractCompat;
import android.support.media.tv.ChannelLogoUtils;
import android.support.media.tv.PreviewProgram;
import android.support.media.tv.WatchNextProgram;

채널

앱에서 만든 첫 번째 채널이 기본 채널이 됩니다. 기본 채널은 홈 화면에 자동으로 표시됩니다. 사용자가 만든 다른 모든 채널은 사용자가 선택하고 승인해야 홈 화면에 표시될 수 있습니다.

채널 만들기

앱이 포그라운드에서 실행되는 경우에만 새로 추가된 채널을 표시하도록 시스템에 요청해야 합니다. 이렇게 하면 사용자가 다른 앱을 실행하는 동안 앱에서 채널 추가 승인을 요청하는 대화상자를 표시하지 않습니다. 백그라운드에서 실행하는 동안 채널을 추가하려고 하면 활동의 onActivityResult() 메서드가 상태 코드 RESULT_CANCELED를 반환합니다.

채널을 만들려면 다음 단계를 따르세요.

  1. 채널 빌더를 만들고 속성을 설정합니다. 채널 유형은 TYPE_PREVIEW여야 합니다. 필요에 따라 속성을 더 추가합니다.

    Kotlin

    val builder = Channel.Builder()
    // Every channel you create must have the type TYPE_PREVIEW
    builder.setType(TvContractCompat.Channels.TYPE_PREVIEW)
            .setDisplayName("Channel Name")
            .setAppLinkIntentUri(uri)
    

    Java

    Channel.Builder builder = new Channel.Builder();
    // Every channel you create must have the type TYPE_PREVIEW
    builder.setType(TvContractCompat.Channels.TYPE_PREVIEW)
            .setDisplayName("Channel Name")
            .setAppLinkIntentUri(uri);
    
  2. 채널을 제공자에 삽입합니다.

    Kotlin

    var channelUri = context.contentResolver.insert(
            TvContractCompat.Channels.CONTENT_URI, builder.build().toContentValues())
    

    Java

    Uri channelUri = context.getContentResolver().insert(
            TvContractCompat.Channels.CONTENT_URI, builder.build().toContentValues());
    
  3. 나중에 프로그램을 채널에 추가하려면 채널 ID를 저장해야 합니다. 반환된 URI에서 채널 ID를 추출합니다.

    Kotlin

    var channelId = ContentUris.parseId(channelUri)
    

    Java

    long channelId = ContentUris.parseId(channelUri);
    
  4. 채널의 로고를 추가해야 합니다. Uri 또는 Bitmap을 사용하세요. 로고 아이콘은 80dp x 80dp이고 불투명해야 합니다. 원형 마스크 아래에 표시됩니다.

    TV 홈 화면 아이콘 마스크

    Kotlin

    // Choose one or the other
    storeChannelLogo(context: Context, channelId: Long, logoUri: Uri) // also works if logoUri is a URL
    storeChannelLogo(context: Context, channelId: Long, logo: Bitmap)
    

    Java

    // Choose one or the other
    storeChannelLogo(Context context, long channelId, Uri logoUri); // also works if logoUri is a URL
    storeChannelLogo(Context context, long channelId, Bitmap logo);
    
  5. 기본 채널 만들기 (선택사항): 앱에서 첫 번째 채널을 만들 때 사용자 작업 없이 즉시 홈 화면에 표시되도록 이 채널을 기본 채널로 만들 수 있습니다. 생성된 다른 모든 채널은 사용자가 명시적으로 선택할 때까지 표시되지 않습니다.

    Kotlin

    TvContractCompat.requestChannelBrowsable(context, channelId)
    

    Java

    TvContractCompat.requestChannelBrowsable(context, channelId);
    

  6. 앱을 열기 전에 기본 채널이 표시되도록 합니다. 앱이 설치된 후 홈 화면에서 전송하는 android.media.tv.action.INITIALIZE_PROGRAMS 작업을 수신 대기하는 BroadcastReceiver를 추가하여 이 동작을 실행할 수 있습니다.
    <receiver
      android:name=".RunOnInstallReceiver"
      android:exported="true">
        <intent-filter>
          <action android:name="android.media.tv.action.INITIALIZE_PROGRAMS" />
          <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </receiver>
    
    개발 중에 앱을 사이드로드할 때 adb를 통해 인텐트를 트리거하여 이 단계를 테스트할 수 있습니다. 여기서 your.package.name/.YourReceiverName는 앱의 BroadcastReceiver입니다.

    adb shell am broadcast -a android.media.tv.action.INITIALIZE_PROGRAMS -n \
        your.package.name/.YourReceiverName
    

    드물지만 사용자가 앱을 시작하는 동시에 앱이 브로드캐스트를 수신할 수 있습니다. 코드에서 기본 채널을 두 번 이상 추가하려고 시도하지 않도록 하세요.

채널 업데이트

채널 업데이트는 채널을 만드는 것과 매우 유사합니다.

다른 Channel.Builder를 사용하여 변경해야 하는 속성을 설정하세요.

채널을 업데이트하려면 ContentResolver를 사용합니다. 채널이 처음에 추가될 때 저장한 채널 ID를 사용하세요.

Kotlin

context.contentResolver.update(
        TvContractCompat.buildChannelUri(channelId),
        builder.build().toContentValues(),
        null,
        null
)

Java

context.getContentResolver().update(TvContractCompat.buildChannelUri(channelId),
    builder.build().toContentValues(), null, null);

채널의 로고를 업데이트하려면 storeChannelLogo()를 사용합니다.

채널 삭제

Kotlin

context.contentResolver.delete(TvContractCompat.buildChannelUri(channelId), null, null)

Java

context.getContentResolver().delete(TvContractCompat.buildChannelUri(channelId), null, null);

프로그램

앱 채널에 프로그램 추가

PreviewProgram.Builder를 만들고 속성을 설정합니다.

Kotlin

val builder = PreviewProgram.Builder()
builder.setChannelId(channelId)
        .setType(TvContractCompat.PreviewPrograms.TYPE_CLIP)
        .setTitle("Title")
        .setDescription("Program description")
        .setPosterArtUri(uri)
        .setIntentUri(uri)
        .setInternalProviderId(appProgramId)

Java

PreviewProgram.Builder builder = new PreviewProgram.Builder();
builder.setChannelId(channelId)
        .setType(TvContractCompat.PreviewPrograms.TYPE_CLIP)
        .setTitle("Title")
        .setDescription("Program description")
        .setPosterArtUri(uri)
        .setIntentUri(uri)
        .setInternalProviderId(appProgramId);

프로그램의 유형에 따라 속성을 더 추가하세요. 각 프로그램 유형에 사용할 수 있는 속성을 보려면 아래 를 참고하세요.

프로그램을 제공자에 삽입하세요.

Kotlin

var programUri = context.contentResolver.insert(TvContractCompat.PreviewPrograms.CONTENT_URI,
        builder.build().toContentValues())

Java

Uri programUri = context.getContentResolver().insert(TvContractCompat.PreviewPrograms.CONTENT_URI,
      builder.build().toContentValues());

나중에 참조할 수 있도록 프로그램 ID를 검색하세요.

Kotlin

val programId = ContentUris.parseId(programUri)

Java

long programId = ContentUris.parseId(programUri);

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

다음 볼만한 동영상 채널에 프로그램을 삽입하려면 다음 볼만한 동영상 채널에 프로그램 추가를 참고하세요.

프로그램 업데이트

프로그램 정보를 변경할 수 있습니다. 예를 들어, 영화의 대여료를 업데이트하거나 사용자가 시청한 프로그램의 양을 표시하는 진행률 표시줄을 업데이트할 수 있습니다.

PreviewProgram.Builder를 사용하여 변경해야 하는 속성을 설정하고 getContentResolver().update를 호출하여 프로그램을 업데이트합니다. 처음에 프로그램을 추가할 때 저장한 프로그램 ID를 지정하세요.

Kotlin

context.contentResolver.update(
        TvContractCompat.buildPreviewProgramUri(programId),
                builder.build().toContentValues(), null, null
)

Java

context.getContentResolver().update(TvContractCompat.buildPreviewProgramUri(programId),
    builder.build().toContentValues(), null, null);

프로그램 삭제

Kotlin

context.contentResolver
        .delete(TvContractCompat.buildPreviewProgramUri(programId), null, null)

Java

context.getContentResolver().delete(TvContractCompat.buildPreviewProgramUri(programId), null, null);

사용자 작업 처리

앱은 채널을 표시하고 추가할 수 있는 UI를 제공하여 사용자가 콘텐츠를 탐색하는 데 도움을 줄 수 있습니다. 또한 채널이 홈 화면에 표시된 후 앱이 채널과의 상호작용을 처리해야 합니다.

채널 탐색 및 추가

앱은 사용자가 채널을 선택하고 추가할 수 있는 UI 요소를 제공할 수 있습니다(예: 채널을 추가하도록 요청하는 버튼).

사용자가 특정 채널을 요청한 후 다음 코드를 실행하여 채널을 홈 화면 UI에 추가할 수 있는 사용자의 권한을 얻으세요.

Kotlin

val intent = Intent(TvContractCompat.ACTION_REQUEST_CHANNEL_BROWSABLE)
intent.putExtra(TvContractCompat.EXTRA_CHANNEL_ID, channelId)
try {
  activity.startActivityForResult(intent, 0)
} catch (e: ActivityNotFoundException) {
  // handle error
}

Java

Intent intent = new Intent(TvContractCompat.ACTION_REQUEST_CHANNEL_BROWSABLE);
intent.putExtra(TvContractCompat.EXTRA_CHANNEL_ID, channelId);
try {
   activity.startActivityForResult(intent, 0);
} catch (ActivityNotFoundException e) {
  // handle error
}

시스템에서 사용자에게 채널을 승인하도록 요청하는 대화상자를 표시합니다. 활동(Activity.RESULT_CANCELED 또는 Activity.RESULT_OK)의 onActivityResult 메서드에 있는 요청 결과를 처리합니다.

Android TV 홈 화면 이벤트

사용자가 앱에서 게시한 프로그램/채널과 상호작용할 때 홈 화면에서 앱에 인텐트를 보냅니다.

  • 사용자가 채널의 로고를 선택하면 홈 화면에서 채널의 APP_LINK_INTENT_URI 속성에 저장된 Uri를 앱에 보냅니다. 앱에서는 기본 UI 또는 선택한 채널과 관련된 뷰를 시작하기만 하면 됩니다.
  • 사용자가 프로그램을 선택하면 홈 화면에서 프로그램의 INTENT_URI 속성에 저장된 Uri를 앱에 보냅니다. 앱에서는 선택한 콘텐츠를 재생하기만 하면 됩니다.
  • 사용자는 프로그램에 더 이상 관심이 없으며 홈 화면의 UI에서 프로그램을 삭제하려고 함을 나타낼 수 있습니다. 시스템이 UI에서 프로그램을 삭제하고 프로그램을 소유한 앱에 프로그램 ID와 함께 인텐트 (android.media.tv.ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED 또는 android.media.tv.ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED)를 보냅니다. 앱은 제공업체에서 프로그램을 삭제해야 하며 다시 삽입하면 안 됩니다.

홈 화면에서 사용자 상호작용을 위해 보내는 모든 Uris에 관한 인텐트 필터를 만들어야 합니다. 예를 들면 다음과 같습니다.

<receiver
   android:name=".WatchNextProgramRemoved"
   android:enabled="true"
   android:exported="true">
   <intent-filter>
       <action android:name="android.media.tv.ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED" />
   </intent-filter>
</receiver>

권장사항

  • 대부분 TV 앱을 사용하려면 사용자가 로그인해야 합니다. 이 경우 android.media.tv.action.INITIALIZE_PROGRAMS를 수신 대기하는 BroadcastReceiver는 인증되지 않은 사용자에게 채널 콘텐츠를 추천해야 합니다.예를 들어 앱이 처음에 최고의 콘텐츠 또는 현재 인기 있는 콘텐츠를 표시할 수 있습니다. 사용자가 로그인하면 맞춤설정된 콘텐츠를 표시할 수 있습니다. 이는 사용자가 로그인하기 전에 앱에서 사용자에게 업셀링할 수 있는 좋은 기회입니다.
  • 앱이 포그라운드에 있지 않고 채널이나 프로그램을 업데이트해야 하는 경우 JobScheduler를 사용하여 작업을 예약합니다 (JobSchedulerJobService 참고).
  • 앱이 오작동하면 시스템이 앱의 제공자 권한을 취소할 수 있습니다(예: 지속적으로 제공업체에 데이터를 스팸 전송). 보안 예외를 처리하려면 try-catch 절을 사용하여 제공자에 액세스하는 코드를 래핑해야 합니다.
  • 프로그램 및 채널을 업데이트하기 전에 제공자에 업데이트해야 하는 데이터를 쿼리하고 데이터를 조정합니다. 예를 들어 사용자가 UI에서 삭제하려는 프로그램을 업데이트할 필요가 없습니다. 기존 데이터를 쿼리하고 채널 승인을 요청한 후 데이터를 제공자에 삽입하거나 업데이트하는 백그라운드 작업을 사용합니다. 앱이 시작될 때와 앱이 데이터를 업데이트해야 할 때마다 이 작업을 실행할 수 있습니다.

    Kotlin

    context.contentResolver
      .query(
          TvContractCompat.buildChannelUri(channelId),
              null, null, null, null).use({
                  cursor-> if (cursor != null and cursor.moveToNext()) {
                               val channel = Channel.fromCursor(cursor)
                               if (channel.isBrowsable()) {
                                   //update channel's programs
                               }
                           }
              })
    

    Java

    try (Cursor cursor = context.getContentResolver()
          .query(
              TvContractCompat.buildChannelUri(channelId),
              null,
              null,
              null,
              null)) {
                  if (cursor != null && cursor.moveToNext()) {
                      Channel channel = Channel.fromCursor(cursor);
                      if (channel.isBrowsable()) {
                          //update channel's programs
                      }
                  }
              }
    
  • 모든 이미지(로고, 아이콘, 콘텐츠 이미지)에 고유한 Uri를 사용하세요. 이미지를 업데이트하는 경우 다른 Uri를 사용해야 합니다. 모든 이미지는 캐시됩니다. 이미지를 변경할 때 Uri를 변경하지 않으면 이전 이미지가 계속 표시됩니다.

  • WHERE 절은 허용되지 않으며 WHERE 절을 사용하여 제공자를 호출하면 보안 예외가 발생합니다.

속성

이 섹션에서는 채널 및 프로그램 속성을 별도로 설명합니다.

채널 속성

모든 채널에 다음 속성을 지정해야 합니다.

속성 Notes
TYPE TYPE_PREVIEW로 설정합니다.
DISPLAY_NAME 채널의 이름으로 설정합니다.
APP_LINK_INTENT_URI 사용자가 채널의 로고를 선택하면 시스템에서 채널과 관련된 콘텐츠를 제공하는 활동을 시작하기 위해 인텐트를 보냅니다. 이 속성을 해당하는 활동의 인텐트 필터에서 사용된 Uri로 설정하세요.

또한 채널에는 내부 앱 사용을 위해 예약된 여섯 개의 필드가 있습니다. 이러한 필드는 앱이 채널을 내부 데이터 구조에 매핑할 때 도움이 될 수 있는 키 또는 다른 값을 저장하는 데 사용될 수 있습니다.

  • INTERNAL_PROVIDER_ID
  • INTERNAL_PROVIDER_DATA
  • INTERNAL_PROVIDER_FLAG1
  • INTERNAL_PROVIDER_FLAG2
  • INTERNAL_PROVIDER_FLAG3
  • INTERNAL_PROVIDER_FLAG4

프로그램 속성

각 프로그램 유형의 속성은 개별 페이지를 참조하세요.

샘플 코드

홈 화면과 상호작용하고 채널 및 프로그램을 Android TV 홈 화면에 추가하는 앱을 빌드하는 방법을 자세히 알아보려면 홈 화면 Codelab을 참조하세요.