Lorsque les utilisateurs interagissent avec des téléviseurs, ils préfèrent généralement fournir le moins d'informations possible avant de regarder un contenu. Pour de nombreux utilisateurs de téléviseurs, le scénario idéal est de s'asseoir, d'allumer l'appareil et de regarder. Le chemin qu'ils préfèrent généralement est celui qui leur permet d'accéder au contenu qu'ils apprécient en un minimum d'étapes.
Remarque : N'utilisez les API décrites ici que pour faire des recommandations dans les applications exécutées sur des versions d'Android allant jusqu'à Android 7.1 (niveau d'API 25) inclus. Pour fournir des recommandations pour les applications exécutées sur Android 8.0 (niveau d'API 26) et versions ultérieures, votre application doit utiliser des canaux de recommandations.
Le framework Android facilite l'interaction avec un minimum d'informations en fournissant une ligne de recommandations sur l'écran d'accueil. Les recommandations de contenu apparaissent comme la première ligne de l'écran d'accueil du téléviseur après la première utilisation de l'appareil. En contribuant aux recommandations à partir du catalogue de contenu de votre application, vous pouvez inciter les utilisateurs à revenir dans votre application.
Ce guide vous explique comment créer des recommandations et les fournir au framework Android afin que les utilisateurs puissent découvrir et apprécier le contenu de votre application. Consultez également l'exemple d'implémentation dans the l'exemple d'application Leanback .
Bonnes pratiques pour les recommandations
Les recommandations aident les utilisateurs à trouver rapidement le contenu et les applications qu'ils apprécient. La création de recommandations de haute qualité et pertinentes pour les utilisateurs est un facteur important pour offrir une expérience utilisateur optimale avec votre application TV. Pour cette raison, vous devez examiner attentivement les recommandations que vous présentez à l'utilisateur et les gérer de près.
Types de recommandations
Lorsque vous créez des recommandations, vous devez rediriger les utilisateurs vers des activités de visionnage incomplètes ou suggérer des activités qui les étendent à des contenus associés. Voici quelques types de recommandations spécifiques à prendre en compte :
- Recommandations de contenu de continuation pour que les utilisateurs puissent reprendre le visionnage d'une série à l'épisode suivant. Vous pouvez également utiliser des recommandations de continuation pour les films, les séries TV ou les podcasts mis en pause afin que les utilisateurs puissent reprendre le visionnage en quelques clics.
- Recommandations de nouveaux contenus, par exemple pour un nouvel épisode en première diffusion, si l'utilisateur a terminé de regarder une autre série. De plus, si votre application permet aux utilisateurs de s'abonner à des contenus, de les suivre ou de les surveiller, utilisez des recommandations de nouveaux contenus pour les éléments non regardés de leur liste de contenus suivis.
- Recommandations de contenus associés basées sur l'historique de visionnage des utilisateurs.
Pour en savoir plus sur la conception de fiches de recommandation afin d'offrir la meilleure expérience utilisateur possible, consultez la section Ligne de recommandations dans la spécification de conception d'Android TV.
Actualiser les recommandations
Lorsque vous actualisez les recommandations, ne vous contentez pas de les supprimer et de les republier, car cela les fait apparaître à la fin de la ligne de recommandations. Une fois qu'un élément de contenu, tel qu'un film, a été visionné, supprimez-le des recommandations.
Personnaliser les recommandations
Vous pouvez personnaliser les fiches de recommandation pour transmettre des informations sur la marque en définissant des éléments d'interface utilisateur tels que l'image de premier plan et l'image de fond de la fiche, sa couleur, l'icône d'application, le titre et le sous-titre. Pour en savoir plus, consultez la section Ligne de recommandations dans la spécification de conception d'Android TV.
Regrouper les recommandations
Vous pouvez également regrouper les recommandations en fonction de leur source. Par exemple, votre application peut fournir deux groupes de recommandations : des recommandations pour les contenus auxquels l'utilisateur est abonné et des recommandations pour les nouveaux contenus tendances que l'utilisateur ne connaît peut-être pas.
Le système classe et ordonne les recommandations de chaque groupe séparément lors de la création ou de la mise à jour de la ligne de recommandations. En fournissant des informations de groupe pour vos recommandations, vous pouvez vous assurer qu'elles ne sont pas classées sous des recommandations sans rapport.
Utilisez NotificationCompat.Builder.setGroup() pour définir la chaîne de clé de groupe d'une recommandation. Par exemple, pour marquer une recommandation comme appartenant à un groupe contenant de nouveaux contenus tendances, vous pouvez appeler setGroup("trending").
Créer un service de recommandations
Les recommandations de contenu sont créées avec un traitement en arrière-plan. Pour que votre application contribue aux recommandations, créez un service qui ajoute régulièrement des fiches du catalogue de votre application à la liste de recommandations du système.
L'exemple de code suivant montre comment étendre IntentService pour
créer un service de recommandations pour votre application :
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 } }
Java
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; } }
Pour que ce service soit reconnu par le système et s'exécute, enregistrez-le à l'aide du fichier manifeste de votre application. L'extrait de code suivant montre comment déclarer cette classe en tant que service :
<manifest ... > <application ... > ... <service android:name="com.example.android.tvleanback.UpdateRecommendationsService" android:enabled="true" /> </application> </manifest>
Créer des recommandations
Une fois que votre service de recommandations a démarré, il doit créer des recommandations et les transmettre au
framework Android. Le framework reçoit les recommandations en tant qu'objets Notification qui utilisent un modèle spécifique et sont marqués avec une catégorie
spécifique.
Définir les valeurs
Pour définir les valeurs des éléments d'interface utilisateur de la fiche de recommandation, créez une classe de compilateur qui suit le modèle de compilateur décrit ci-dessous. Tout d'abord, définissez les valeurs des éléments de la fiche de recommandation.
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 } ...
Java
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; } ...
Créer la notification
Une fois que vous avez défini les valeurs, créez la notification, en attribuant les valeurs de la classe de compilateur
à la notification et en appelant NotificationCompat.Builder.build().
Veillez également à appeler
setLocalOnly()
afin que la notification NotificationCompat.BigPictureStyle ne s'affiche pas
sur d'autres appareils.
L'exemple de code suivant montre comment créer une recommandation.
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 } }
Java
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; } }
Exécuter le service de recommandations
Le service de recommandations de votre application doit s'exécuter régulièrement pour créer des recommandations actuelles. Pour exécuter votre service, créez une classe qui exécute un minuteur et l'appelle
à intervalles réguliers. L'exemple de code suivant étend la classe BroadcastReceiver pour démarrer l'exécution périodique d'un service de recommandations
toutes les demi-heures :
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 } }
Java
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); } }
Cette implémentation de la classe BroadcastReceiver doit s'exécuter après le démarrage
de l'appareil TV sur lequel elle est installée. Pour ce faire, enregistrez cette classe dans le fichier manifeste
de votre application avec un filtre d'intent qui écoute la fin du processus de démarrage de l'appareil. L'exemple de code suivant montre comment ajouter cette configuration au fichier manifeste :
<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>
Important : Pour recevoir une notification de démarrage terminé, votre application doit
demander l'autorisation RECEIVE_BOOT_COMPLETED.
Pour en savoir plus, consultez ACTION_BOOT_COMPLETED.
Dans la méthode onHandleIntent() de la classe de votre service de recommandations, publiez la recommandation auprès du gestionnaire comme suit :
Kotlin
val notification = notificationBuilder.build() notificationManager.notify(id, notification)
Java
Notification notification = notificationBuilder.build(); notificationManager.notify(id, notification);