Android TV 홈 화면 또는 간단히 홈 화면은 추천 콘텐츠를 채널 및 프로그램의 표로 표시하는 UI를 제공합니다. 각 행이 채널입니다. 채널에는 이 채널에서 볼 수 있는 모든 프로그램의 카드가 포함되어 있습니다.
이 페이지에서는 채널과 프로그램을 홈 화면에 추가하고, 콘텐츠를 업데이트하고, 사용자 작업을 처리하고, 사용자에게 최고의 환경을 제공하는 방법을 보여줍니다. (API를 자세히 살펴보려면 홈 화면 Codelab을 사용해 보고 I/O 2017 Android TV 세션을 시청하세요.)
참고: 추천 채널은 Android 8.0(API 수준 26) 이상에서만 사용할 수 있습니다. Android 8.0(API 레벨 26) 이상에서 실행되는 앱을 위한 추천 항목을 제공하려면 추천 채널을 사용해야 합니다. 이전 버전의 Android에서 실행되는 앱을 위한 추천 항목을 제공하려면 앱에서 추천 행을 사용해야 합니다.
홈 화면 UI
앱은 새 채널을 만들고 프로그램을 채널에 추가, 삭제 및 업데이트하며 채널의 프로그램 순서를 제어할 수 있습니다. 예를 들어, 앱에서 '새로운 기능'이라는 채널을 만들고 새로 공개된 프로그램의 카드를 표시할 수 있습니다.
앱은 채널이 홈 화면에 나타나는 순서를 제어할 수 없습니다. 앱에서 새 채널을 만들면 이 채널이 홈 화면에서 채널 목록의 하단에 추가됩니다. 사용자가 채널을 재정렬하고 숨기고 표시할 수 있습니다.
다음 볼만한 동영상 채널
다음 볼만한 동영상 채널은 홈 화면에서 앱 행 다음에 있는 두 번째 행입니다. 시스템에서 이 채널을 만들고 유지합니다. 앱에서 다음 볼만한 동영상 채널에 프로그램을 추가할 수 있습니다. 자세한 내용은 다음 볼만한 동영상 채널에 프로그램 추가를 참조하세요.
앱 채널
앱에서 만드는 채널은 모두 다음 수명 주기를 따릅니다.
- 사용자가 앱에서 채널을 탐색하여 홈 화면에 추가하도록 요청합니다.
- 앱에서 채널을 만들어
TvProvider
에 추가합니다(이 시점에는 이 채널이 표시되지 않음). - 앱이 시스템에 이 채널을 표시하도록 요청합니다.
- 시스템이 사용자에게 새 채널을 승인하도록 요청합니다.
- 새 채널이 홈 화면의 마지막 행에 표시됩니다.
기본 채널
앱은 사용자가 홈 화면에 추가하는 여러 채널을 제공할 수 있습니다. 일반적으로 채널이 홈 화면에 표시되기 전에 사용자가 각 채널을 선택하고 승인해야 합니다. 모든 앱에는 하나의 기본 채널을 만드는 옵션이 있습니다. 기본 채널은 자동으로 홈 화면에 표시되므로 특수하며, 사용자가 명시적으로 요청할 필요가 없습니다.
기본 요건
Android TV 홈 화면에서는 Android의 TvProvider
API를 사용하여 앱에서 만드는 채널과 프로그램을 관리합니다.
제공자의 데이터에 액세스하려면 앱의 매니페스트에 다음 권한을 추가하세요.
<uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA" />
TvProvider
지원 라이브러리를 통해 제공자를 더욱 쉽게 사용할 수 있습니다. 이 라이브러리를 build.gradle
파일의 종속 항목에 추가하세요.
compile 'com.android.support:support-tv-provider:27.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
자바
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
를 반환합니다.
채널을 만들려면 다음 단계를 따르세요.
채널 빌더를 만들고 속성을 설정합니다. 채널 유형은
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)자바
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);채널을 제공자에 삽입합니다.
Kotlin
var channelUri = context.contentResolver.insert( TvContractCompat.Channels.CONTENT_URI, builder.build().toContentValues())
자바
Uri channelUri = context.getContentResolver().insert( TvContractCompat.Channels.CONTENT_URI, builder.build().toContentValues());
-
나중에 프로그램을 채널에 추가하기 위해 채널 ID를 저장해야 합니다. 반환된 URI에서 채널 ID를 추출합니다.
Kotlin
var channelId = ContentUris.parseId(channelUri)
자바
long channelId = ContentUris.parseId(channelUri);
채널의 로고를 추가해야 합니다.
Uri
또는Bitmap
을 사용하세요. 로고 아이콘은 80dp x 80dp이고 불투명해야 합니다. 로고 아이콘은 원형 마스크 아래에 표시됩니다.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)
자바
// 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);
기본 채널을 만듭니다(선택사항). 앱에서 첫 번째 채널을 만들 때 사용자 작업 없이 즉시 홈 화면에 표시되도록 이 채널을 기본 채널로 지정할 수 있습니다. 사용자가 만든 다른 모든 채널은 사용자가 명시적으로 선택할 때까지 표시되지 않습니다.
Kotlin
TvContractCompat.requestChannelBrowsable(context, channelId)
자바
TvContractCompat.requestChannelBrowsable(context, channelId);
- 앱을 열기 전에 기본 채널이 표시되도록 합니다. 이 동작이 발생하도록 하려면 앱이 설치된 후 홈 화면에서 보내는
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 )
자바
context.getContentResolver().update(TvContractCompat.buildChannelUri(channelId), builder.build().toContentValues(), null, null);
채널의 로고를 업데이트하려면 storeChannelLogo()
를 사용합니다.
채널 삭제
Kotlin
context.contentResolver.delete(TvContractCompat.buildChannelUri(channelId), null, null)
자바
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)
자바
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())
자바
Uri programUri = context.getContentResolver().insert(TvContractCompat.PreviewPrograms.CONTENT_URI, builder.build().toContentValues());
나중에 참조할 수 있도록 프로그램 ID를 검색하세요.
Kotlin
val programId = ContentUris.parseId(programUri)
자바
long programId = ContentUris.parseId(programUri);
다음 볼만한 동영상 채널에 프로그램 추가
다음 볼만한 동영상 채널에 프로그램을 삽입하려면 다음 볼만한 동영상 채널에 프로그램 추가를 참조하세요.
프로그램 업데이트
프로그램 정보를 변경할 수 있습니다. 예를 들어, 영화의 대여료를 업데이트하거나 사용자가 시청한 프로그램의 양을 표시하는 진행률 표시줄을 업데이트할 수 있습니다.
PreviewProgram.Builder
를 사용하여 변경해야 할 속성을 설정하고 getContentResolver().update
를 호출하여 프로그램을 업데이트합니다. 처음에 프로그램을 추가할 때 저장한 프로그램 ID를 지정하세요.
Kotlin
context.contentResolver.update( TvContractCompat.buildPreviewProgramUri(programId), builder.build().toContentValues(), null, null )
자바
context.getContentResolver().update(TvContractCompat.buildPreviewProgramUri(programId), builder.build().toContentValues(), null, null);
프로그램 삭제
Kotlin
context.contentResolver .delete(TvContractCompat.buildPreviewProgramUri(programId), null, null)
자바
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 }
자바
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에서 삭제하고 프로그램을 소유하는 앱에 인텐트(android.media.tv.ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED 또는 android.media.tv.ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED)를 프로그램의 ID와 함께 보냅니다. 앱이 프로그램을 제공자에서 삭제해야 하며 다시 삽입해서는 안 됩니다.
홈 화면에서 사용자 상호작용을 위해 보내는 모든 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
가 인증되지 않은 사용자에게 채널 콘텐츠를 추천해야 합니다.예를 들어 앱이 처음에 최고의 콘텐츠 또는 현재 인기 콘텐츠를 표시할 수 있습니다. 사용자가 로그인한 후에는 맞춤설정된 콘텐츠를 표시할 수 있습니다. 이는 사용자가 로그인하기 전에 앱에서 사용자에게 업셀(up-sell)할 수 있는 좋은 기회입니다. - 앱이 포그라운드에 있지 않고 채널 또는 프로그램을 업데이트해야 하는 경우
JobScheduler
를 사용하여 작업을 예약하세요(JobScheduler 및 JobService 참조). - 앱이 정상적으로 작동하지 않는 경우(예: 계속해서 제공자에게 데이터 스팸 발송) 시스템에서 앱 제공자 권한을 취소할 수 있습니다. 보안 예외를 처리하도록 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 } } })
자바
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 절을 사용하여 제공자를 호출하면 보안 예외가 발생합니다.
속성
이 섹션에서는 채널 및 프로그램 속성을 별도로 설명합니다.
채널 속성
모든 채널에 다음 속성을 지정해야 합니다.
속성 | 메모 |
---|---|
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을 참조하세요.