Android N 및 이전 버전의 권장사항

TV와 상호작용할 때 일반적으로 사용자는 시청하기 전에 최소한의 입력만 하는 것을 선호합니다. 있습니다. 많은 TV 사용자에게 이상적인 시나리오는 앉아서 TV를 켜고 시청하는 것입니다. 최소 단계 사용자가 좋아하는 콘텐츠로 유도하는 것은 일반적으로 사용자가 선호하는 경로입니다.

참고: 여기에 설명된 API를 사용하여 추천을 생성하세요. Android 7.1 (API 수준 25) 이하의 Android 버전에서 실행되는 앱에만 적용됩니다. 공급 권장사항에 따라 Android 8.0 (API 레벨 26) 이상에서 실행되는 앱의 경우, 앱은 추천 채널을 선택합니다.

Android 프레임워크는 추천 행을 제공하여 최소 입력 상호작용을 지원합니다. 을 클릭합니다. 다음 날짜 이후에 콘텐츠 추천이 TV 홈 화면의 첫 번째 행에 표시됩니다. 발생할 수 있습니다. 앱 콘텐츠 카탈로그의 추천 참여가 도움이 될 수 있습니다. 사용자가 앱을 다시 이용하도록 유도할 수 있습니다

그림 1. 추천 행의 예

이 가이드에서는 추천을 만들어 Android 프레임워크에 제공하는 방법을 설명합니다. 그래야 사용자가 앱 콘텐츠를 쉽게 찾고 즐길 수 있습니다. 샘플 구현도 참조: <ph type="x-smartling-placeholder"></ph> Leanback 샘플 앱 에서 자세한 내용을 확인하실 수 있습니다.

추천 권장사항

추천을 통해 사용자는 자신이 즐기는 콘텐츠와 앱을 빠르게 찾을 수 있습니다. 생성 중 사용자와 관련성 있는 고품질의 추천사항은 훌륭한 사용자 환경을 제공하는 것입니다. 이러한 이유에서 면밀하게 관리해야 합니다.

추천 유형

맞춤 동영상을 만들 때 완료되지 않은 시청 활동 또는 동영상 시청 페이지로 사용자를 다시 연결해야 합니다. 관련 콘텐츠로 확장하는 활동을 제안합니다. 몇 가지 구체적인 유형은 다음과 같습니다. 고려해야 할 권장사항:

  • 사용자가 다시 시작할 수 있도록 다음 에피소드의 연속 콘텐츠 추천 시리즈를 시청하고 있습니다. 또는 일시중지된 영화, TV 프로그램, 팟캐스트의 연속 추천 사용 사용자가 클릭 몇 번만으로 일시중지된 콘텐츠를 다시 볼 수 있습니다.
  • 사용자가 새 콘텐츠를 추천하는 경우(예: 첫 실행 에피소드의 새 에피소드 등) 다른 시리즈를 시청한 것을 볼 수 있습니다 또한 앱에서 사용자가 구독, 팔로우, 추적 기능을 사용할 수 있는지 추적 중인 콘텐츠 목록에서 시청하지 않은 항목에 대해 새로운 콘텐츠 추천을 사용하세요.
  • 사용자의 과거 시청 행동에 기반한 관련 콘텐츠를 추천합니다.

최상의 사용자 환경을 위한 추천 카드를 디자인하는 방법에 관한 자세한 내용은 다음을 참고하세요. Android TV 디자인 사양의 추천 행

추천 새로고침

맞춤 동영상을 새로 고칠 때는 단순히 삭제했다가 다시 게시하는 것이 아니라 추천 행의 끝에 표시되는 추천입니다. 콘텐츠 항목(예: 영화가 재생되었습니다. 맞춤 동영상에서 삭제합니다.

추천 맞춤설정

사용자 인터페이스를 설정하여 브랜드 정보를 전달하도록 추천 카드를 맞춤설정할 수 있습니다. 요소(예: 카드의 전경 및 배경 이미지, 색상, 앱 아이콘, 제목, 부제목) 자세한 내용은 Android TV 디자인 사양의 추천 행

그룹 추천

추천 소스에 기반한 그룹 추천을 할 수 있습니다(선택사항). 예를 들어 앱이 두 가지 추천 그룹을 제공할 수 있습니다. 사용자가 구독 중인 콘텐츠 추천, 사용자가 모를 수 있는 새 인기 급상승 콘텐츠를 추천해 줍니다

시스템은 추천 항목을 만들거나 업데이트할 때 개별적으로 각 그룹에 대한 추천의 순위를 지정하고 순서를 지정합니다. 추천 행입니다. 추천에 대한 그룹 정보를 제공하면 맞춤 콘텐츠가 관련 없는 추천 아래에 정렬되지 않습니다.

사용 NotificationCompat.Builder.setGroup(): 추천의 그룹 키 문자열을 설정합니다. 대상 예를 들어 맞춤 동영상을 새로운 인기 콘텐츠가 포함된 그룹에 속하는 것으로 표시하려면 setGroup("trending")를 호출할 수 있습니다.

추천 서비스 만들기

콘텐츠 추천은 백그라운드 처리로 만들어집니다. 애플리케이션이 정기적으로 추천 항목을 추가하는 서비스를 만들 수 있습니다. 앱의 카탈로그를 시스템의 추천 목록에 추가합니다.

다음 코드 예는 IntentService를 다음과 같이 확장하는 방법을 보여줍니다. 애플리케이션을 위한 추천 서비스를 만듭니다.

Kotlin

class UpdateRecommendationsService : IntentService("RecommendationService") {
    override protected fun onHandleIntent(intent: Intent) {
        Log.d(TAG, "Updating recommendation cards")
        val recommendations = VideoProvider.getMovieList()
        if (recommendations == null) return

        var count = 0

        try {
            val builder = RecommendationBuilder()
                    .setContext(applicationContext)
                    .setSmallIcon(R.drawable.videos_by_google_icon)

            for (entry in recommendations.entrySet()) {
                for (movie in entry.getValue()) {
                    Log.d(TAG, "Recommendation - " + movie.getTitle())

                    builder.setBackground(movie.getCardImageUrl())
                            .setId(count + 1)
                            .setPriority(MAX_RECOMMENDATIONS - count)
                            .setTitle(movie.getTitle())
                            .setDescription(getString(R.string.popular_header))
                            .setImage(movie.getCardImageUrl())
                            .setIntent(buildPendingIntent(movie))
                            .build()
                    if (++count >= MAX_RECOMMENDATIONS) {
                        break
                    }
                }
                if (++count >= MAX_RECOMMENDATIONS) {
                    break
                }
            }
        } catch (e: IOException) {
            Log.e(TAG, "Unable to update recommendation", e)
        }
    }

    private fun buildPendingIntent(movie: Movie): PendingIntent {
        val detailsIntent = Intent(this, DetailsActivity::class.java)
        detailsIntent.putExtra("Movie", movie)

        val stackBuilder = TaskStackBuilder.create(this)
        stackBuilder.addParentStack(DetailsActivity::class.java)
        stackBuilder.addNextIntent(detailsIntent)

        // Ensure a unique PendingIntents, otherwise all
        // recommendations end up with the same PendingIntent
        detailsIntent.setAction(movie.getId().toString())

        val intent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)
        return intent
    }

    companion object {
        private val TAG = "UpdateRecommendationsService"
        private val MAX_RECOMMENDATIONS = 3
    }
}

자바

public class UpdateRecommendationsService extends IntentService {
    private static final String TAG = "UpdateRecommendationsService";
    private static final int MAX_RECOMMENDATIONS = 3;

    public UpdateRecommendationsService() {
        super("RecommendationService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        Log.d(TAG, "Updating recommendation cards");
        HashMap<String, List<Movie>> recommendations = VideoProvider.getMovieList();
        if (recommendations == null) return;

        int count = 0;

        try {
            RecommendationBuilder builder = new RecommendationBuilder()
                    .setContext(getApplicationContext())
                    .setSmallIcon(R.drawable.videos_by_google_icon);

            for (Map.Entry<String, List<Movie>> entry : recommendations.entrySet()) {
                for (Movie movie : entry.getValue()) {
                    Log.d(TAG, "Recommendation - " + movie.getTitle());

                    builder.setBackground(movie.getCardImageUrl())
                            .setId(count + 1)
                            .setPriority(MAX_RECOMMENDATIONS - count)
                            .setTitle(movie.getTitle())
                            .setDescription(getString(R.string.popular_header))
                            .setImage(movie.getCardImageUrl())
                            .setIntent(buildPendingIntent(movie))
                            .build();

                    if (++count >= MAX_RECOMMENDATIONS) {
                        break;
                    }
                }
                if (++count >= MAX_RECOMMENDATIONS) {
                    break;
                }
            }
        } catch (IOException e) {
            Log.e(TAG, "Unable to update recommendation", e);
        }
    }

    private PendingIntent buildPendingIntent(Movie movie) {
        Intent detailsIntent = new Intent(this, DetailsActivity.class);
        detailsIntent.putExtra("Movie", movie);

        TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
        stackBuilder.addParentStack(DetailsActivity.class);
        stackBuilder.addNextIntent(detailsIntent);
        // Ensure a unique PendingIntents, otherwise all
        // recommendations end up with the same PendingIntent
        detailsIntent.setAction(Long.toString(movie.getId()));

        PendingIntent intent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
        return intent;
    }
}

시스템에서 이 서비스를 인식하여 실행하려면 앱 매니페스트를 참조하세요. 다음 코드 스니펫은 이 클래스를 서비스로 선언하는 방법을 보여줍니다.

<manifest ... >
  <application ... >
    ...

    <service
            android:name="com.example.android.tvleanback.UpdateRecommendationsService"
            android:enabled="true" />
  </application>
</manifest>

추천 빌드

추천 서비스가 실행되기 시작하면 추천을 만들어 Android 프레임워크입니다. 프레임워크는 특정 템플릿을 사용하고 특정 샘플로 표시되는 Notification 객체로 추천을 수신합니다. 카테고리입니다.

값 설정

추천 카드의 UI 요소 값을 설정하려면 다음을 따르는 빌더 클래스를 만듭니다. 빌더 패턴을 설명합니다. 먼저 추천 카드의 값을 설정합니다. 요소

Kotlin

class RecommendationBuilder {
    ...

    fun setTitle(title: String): RecommendationBuilder {
        this.title = title
        return this
    }

    fun setDescription(description: String): RecommendationBuilder {
        this.description = description
        return this
    }

    fun setImage(uri: String): RecommendationBuilder {
        imageUri = uri
        return this
    }

    fun setBackground(uri: String): RecommendationBuilder {
        backgroundUri = uri
        return this
    }

...

자바

public class RecommendationBuilder {
    ...

    public RecommendationBuilder setTitle(String title) {
            this.title = title;
            return this;
        }

        public RecommendationBuilder setDescription(String description) {
            this.description = description;
            return this;
        }

        public RecommendationBuilder setImage(String uri) {
            imageUri = uri;
            return this;
        }

        public RecommendationBuilder setBackground(String uri) {
            backgroundUri = uri;
            return this;
        }
...

알림 만들기

값을 설정한 후 알림을 빌드하고 빌더에서 값을 할당합니다. 클래스를 알림에 추가하고 NotificationCompat.Builder.build()를 호출합니다.

또한 setLocalOnly() NotificationCompat.BigPictureStyle 알림이 표시되지 않습니다. 다른 기기에서 이용할 수 있습니다.

다음 코드 예에서는 추천을 빌드하는 방법을 보여줍니다.

Kotlin

class RecommendationBuilder {
    ...

    @Throws(IOException::class)
    fun build(): Notification {
        ...

        val notification = NotificationCompat.BigPictureStyle(
        NotificationCompat.Builder(context)
                .setContentTitle(title)
                .setContentText(description)
                .setPriority(priority)
                .setLocalOnly(true)
                .setOngoing(true)
                .setColor(context.resources.getColor(R.color.fastlane_background))
                .setCategory(Notification.CATEGORY_RECOMMENDATION)
                .setLargeIcon(image)
                .setSmallIcon(smallIcon)
                .setContentIntent(intent)
                .setExtras(extras))
                .build()

        return notification
    }
}

자바

public class RecommendationBuilder {
    ...

    public Notification build() throws IOException {
        ...

        Notification notification = new NotificationCompat.BigPictureStyle(
                new NotificationCompat.Builder(context)
                        .setContentTitle(title)
                        .setContentText(description)
                        .setPriority(priority)
                        .setLocalOnly(true)
                        .setOngoing(true)
                        .setColor(context.getResources().getColor(R.color.fastlane_background))
                        .setCategory(Notification.CATEGORY_RECOMMENDATION)
                        .setLargeIcon(image)
                        .setSmallIcon(smallIcon)
                        .setContentIntent(intent)
                        .setExtras(extras))
                .build();

        return notification;
    }
}

추천 서비스 실행

현재 추천 항목을 생성하려면 앱의 추천 서비스를 주기적으로 실행해야 합니다. 추천을 제공합니다 서비스를 실행하려면 타이머를 실행하고 주기적으로 점검합니다. 다음 코드 예에서는 BroadcastReceiver 클래스를 확장하여 추천 서비스의 주기적인 실행을 시작합니다. 30분마다:

Kotlin

class BootupActivity : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        Log.d(TAG, "BootupActivity initiated")
        if (intent.action.endsWith(Intent.ACTION_BOOT_COMPLETED)) {
            scheduleRecommendationUpdate(context)
        }
    }

    private fun scheduleRecommendationUpdate(context: Context) {
        Log.d(TAG, "Scheduling recommendations update")
        val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
        val recommendationIntent = Intent(context, UpdateRecommendationsService::class.java)
        val alarmIntent = PendingIntent.getService(context, 0, recommendationIntent, 0)
        alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                INITIAL_DELAY,
                AlarmManager.INTERVAL_HALF_HOUR,
                alarmIntent
        )
    }

    companion object {
        private val TAG = "BootupActivity"
        private val INITIAL_DELAY:Long = 5000
    }
}

자바

public class BootupActivity extends BroadcastReceiver {
    private static final String TAG = "BootupActivity";

    private static final long INITIAL_DELAY = 5000;

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(TAG, "BootupActivity initiated");
        if (intent.getAction().endsWith(Intent.ACTION_BOOT_COMPLETED)) {
            scheduleRecommendationUpdate(context);
        }
    }

    private void scheduleRecommendationUpdate(Context context) {
        Log.d(TAG, "Scheduling recommendations update");

        AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        Intent recommendationIntent = new Intent(context, UpdateRecommendationsService.class);
        PendingIntent alarmIntent = PendingIntent.getService(context, 0, recommendationIntent, 0);

        alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                INITIAL_DELAY,
                AlarmManager.INTERVAL_HALF_HOUR,
                alarmIntent);
    }
}

BroadcastReceiver 클래스의 이 구현은 시작 후에 실행되어야 합니다. TV 기기 위로 이동합니다. 이렇게 하려면 앱에 이 클래스를 등록하세요. 기기 부팅 프로세스의 완료를 수신 대기하는 인텐트 필터로 연결합니다. 이 다음 샘플 코드는 이 구성을 매니페스트에 추가하는 방법을 보여줍니다.

<manifest ... >
  <application ... >
    <receiver android:name="com.example.android.tvleanback.BootupActivity"
              android:enabled="true"
              android:exported="false">
      <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
      </intent-filter>
    </receiver>
  </application>
</manifest>

중요: 부팅 완료 알림을 받으려면 앱이 필요합니다. RECEIVE_BOOT_COMPLETED 권한을 요청합니다. 자세한 내용은 ACTION_BOOT_COMPLETED를 참고하세요.

추천 서비스 클래스에서 onHandleIntent() 메서드에서 다음과 같이 추천을 관리자에게 게시합니다.

Kotlin

val notification = notificationBuilder.build()
notificationManager.notify(id, notification)

Java

Notification notification = notificationBuilder.build();
notificationManager.notify(id, notification);