Améliorer l'engagement des utilisateurs pour les films/épisodes de séries TV disponibles dans "Ma sélection" sur Android TV

1. Introduction

Ma sélection

La chaîne "Ma sélection" est la ligne qui s'affiche sur l'écran d'accueil de l'Android TV, proposant à l'utilisateur d'autres vidéos à regarder. En fonction de la version du système, la ligne "Ma sélection" peut s'intituler "À regarder ensuite" ou "Continuer à regarder".

b0ca4ea7c72ba8f6.png

Le système crée et gère cette chaîne. Chaque élément de ce canal est appelé un programme. Votre application peut ajouter/mettre à jour/supprimer des programmes sur la chaîne "Ma sélection", comme des contenus que l'utilisateur a mis en pause ou avec lesquels il a interagi (le prochain épisode ou la prochaine saison d'une série par exemple).

Concepts

La chaîne "Ma sélection" vous permet d'inciter l'utilisateur à interagir à nouveau avec votre application.

Vous pouvez ajouter/mettre à jour/supprimer des contenus sur la chaîne "Ma sélection", avec lesquels l'utilisateur a déjà interagi. Il peut s'agir d'une vidéo mise en pause ou d'une suggestion pour un autre épisode/série, etc.

Les applications peuvent également supprimer l'épisode une fois qu'il a été regardé et ajouter le prochain épisode de la nouvelle saison.

Il existe quatre types de cas d'utilisation de la chaîne "Ma sélection" :

  • Reprendre la lecture d'une vidéo que l'utilisateur n'a pas terminée.
  • Suggérer la vidéo suivante à regarder. Par exemple, si l'utilisateur a fini de regarder l'épisode 1, vous pouvez suggérer l'épisode 2.
  • Afficher les nouveaux épisodes d'une série que l'utilisateur a regardée.
  • Conserver une liste de vidéos intéressantes ajoutées par l'utilisateur.

Cet atelier de programmation vous explique comment inclure une vidéo mise en pause par l'utilisateur dans la chaîne "Ma sélection". Il explique également comment supprimer une vidéo de "Ma sélection" une fois regardée en entier, et comment ajouter l'épisode suivant lorsqu'il est disponible.

Cet atelier ne traite pas des cas d'utilisation de la chaîne "Ma sélection" pour les nouveaux épisodes ni pour la liste de vidéos intéressantes.

Ma sélection de films et d'épisodes de séries TV

La chaîne "Ma sélection" est une fonctionnalité très importante que l'on retrouve sur l'écran d'accueil d'Android TV. Elle permet à l'utilisateur de terminer les films et séries TV mis en pause. Cet aspect est particulièrement important pour les utilisateurs qui regardent une série TV, qui comportent souvent de nombreux épisodes, puisqu'ils pourront reprendre leurs séries là où ils s'étaient arrêtés.

Imaginez que l'utilisateur s'assoit devant sa télévision et qu'il cherche quoi regarder. Grâce à "Ma sélection", votre application leur permet de reprendre des épisodes de séries TV là où ils les avaient laissés, et ce, directement depuis l'écran d'accueil. Cela permet d'accroître le réengagement des utilisateurs, ce qui profite tant à votre application qu'à l'utilisateur.

Dans cet atelier de programmation, vous découvrirez l'application TV de référence, comment traiter les différentes situations que vous pourrez rencontrer concernant la chaîne "Ma sélection" et quelles sont les consignes Google relatives à la qualité concernant la fonctionnalité "Ma sélection". Cet atelier de programmation porte plus spécifiquement sur la gestion des épisodes de séries TV, mais les mêmes règles peuvent aussi s'appliquer pour les films.

Disponibilité

Le code de cet atelier de programmation fonctionne sur les appareils Android TV, y compris ceux qui utilisent l'expérience Google TV…

Objectifs de l'atelier

Dans cet atelier de programmation, vous allez ajouter, supprimer et mettre à jour les films et épisodes de séries TV d'une chaîne "Ma sélection". Cette application pourra :

  • implémenter différents cas d'utilisation pour la gestion des films ;
  • implémenter différents cas d'utilisation pour la gestion des épisodes de séries TV.

Points abordés

  • Consignes Google relatives à la qualité pour "Ma sélection"

Ce dont vous avez besoin

  • Connaissances de base en développement d'applications Android
  • Android Studio 4.1+, en téléchargement ici.

2. Configuration

Cloner le projet de démarrage

Son code source est disponible sur le dépôt GitHub :

git clone https://github.com/android/codelab-watchnext-for-movie-tv-episodes.git

Vous pouvez également télécharger l'application directement à partir du lien ci-dessous.

Ouvrez Android Studio, puis cliquez sur Fichier > Ouvrir dans la barre de menu, ou Ouvrir un projet Android Studio existant sur l'écran d'accueil, puis sélectionnez le dossier cloné récemment.

8271a7b581390845.png

Comprendre le projet de démarrage

34641bc2c9f71f0f.png

Ce projet comporte quatre étapes. À chaque étape, vous ajouterez du code en suivant les instructions de la section applicable. Une fois une section terminée, vous pouvez comparer votre code à celui de step_x_completed.

Pour plus de simplicité, nous avons ajouté du code de base à la liste des vidéos et à ExoPlayer, afin de pouvoir regarder du contenu depuis l'application. Ce faisant, vous allez créer le squelette de base d'une application TV. Ceci n'est pas abordé dans cet atelier de programmation.

Notre objectif ici est d'apprendre à ajouter/supprimer/mettre à jour les vidéos mises en pause ou terminées sur la chaîne "Ma sélection" afin de susciter à nouveau de l'engagement pour notre application.

Les principaux composants de l'application sont les suivants :

  • FileVideoRepository est la classe pour charger et interroger les métadonnées vidéo.
  • PlaybackFragment est le fragment de la lecture vidéo.
  • WatchNextPlaybackStateListener est un écouteur de changement d'état de lecture. Il écoute les événements de lecture et déclenche les opérations associées.
  • WatchNextWorker est un nœud de calcul chargé de mettre à jour la chaîne "Ma sélection".
  • WatchNextHelper est une classe d'assistance qui simplifie l'utilisation de la chaîne "Ma sélection".

Cet atelier de programmation utilise des données multimédias au format res/raw/api.json pour remplir les entrées de "Ma sélection".

Exécuter le projet de démarrage

Exécutez step_1. Si vous rencontrez des problèmes, consultez nos documents de référence pour découvrir comment procéder.

  1. Connectez votre Android TV ou démarrez l'émulateur.
  1. Sélectionnez la configuration step_1, puis votre appareil Android. Appuyez sur le bouton run dans la barre de menu. 249ea91a556fbd61.png
  2. Vous devriez voir un exemple d'application TV basique avec quatre collections de vidéos semblables à la capture d'écran ci-dessous.
  3. Parcourez l'écran principal de l'application et familiarisez-vous avec l'application TV de référence. Il existe quatre catégories de vidéos :
  4. Supercharged Clips (extraits surchargés)
  5. Misc clips (extraits divers)
  6. Beverly Hillbillies : quelques épisodes de séries TV de deux saisons différentes
  7. Charlie Chaplin Movies (films de Charlie Chaplin)
  8. Cliquez sur l'un des épisodes de la catégorie Beverly Hillbillies et regardez-le. Dans cet atelier de programmation, vous apprendrez à ajouter ces programmes à "Ma sélection".

d7b51de54f4a1199.png

Connaissances acquises

Dans cette introduction, vous avez acquis des connaissances sur les aspects suivants :

  • La structure du code et les principales classes utilisées dans cet atelier de programmation.
  • La configuration et l'exécution de l'application exemple.

Et maintenant ?

Consignes relatives à la qualité de "Ma sélection"

3. Comprendre les consignes relatives à la qualité de "Ma sélection"

Pour offrir une meilleure expérience sur l'écran d'accueil, toutes les applications qui ajoutent du contenu à "Ma sélection" doivent se comporter de manière cohérente.

Il existe d'ailleurs des scénarios que les développeurs doivent aborder pour les épisodes de séries TV. Google a résumé des consignes relatives à la qualité de "Ma sélection", qui doivent être suivies afin de garantir la qualité de cette chaîne.

Comment créer votre fonctionnalité "Ma sélection" pour répondre aux normes de Google en matière de qualité ?

Lorsque Google évalue la fonctionnalité "Ma sélection", les points suivants sont vérifiés :

  1. Le programme est ajouté à "Ma sélection" lorsqu'il est mis en pause/arrêté.
  2. L'application peut reprendre la lecture à partir de "Ma sélection".
  3. L'application met à jour rapidement la position de lecture dans "Ma sélection".
  4. Le programme est supprimé de "Ma sélection" une fois la lecture terminée.
  5. L'épisode suivant est ajouté lorsque l'épisode en cours de lecture est terminé.
  6. L'application n'ajoute aucun contenu avec lequel l'utilisateur n'a pas interagi à "Ma sélection".
  7. L'application ajoute tous les contenus mis en pause dans "Ma sélection".
  8. L'application définit des métadonnées complètes et correctes, comme le numéro des saisons et épisodes.
  9. L'application n'ajoute pas plusieurs épisodes pour la même série TV.

Explications concernant chaque exigence en termes de qualité

  1. Le programme est ajouté à "Ma sélection" lorsqu'il est mis en pause/arrêté.
  • Les applications doivent ajouter les films et séries TV traditionnels à la catégorie "Ma sélection" lorsque la lecture n'est pas terminée
  1. L'application peut reprendre la lecture à partir de "Ma sélection".
  • Le contenu ajouté à la chaîne "Ma sélection" reprend la lecture où celle-ci s'était arrêtée. La lecture de la vidéo doit commencer immédiatement après le chargement du contenu
  1. L'application met à jour rapidement la position de lecture dans "Ma sélection".
  • L'application doit suivre la progression de la lecture et mettre à jour le programme "Ma sélection" avec la dernière position de lecture de l'utilisateur
  1. Le programme est supprimé de "Ma sélection" une fois la lecture terminée.
  • Une application est comme un bon citoyen, elle doit nettoyer derrière elle. La ligne "Ma sélection" est une ligne partagée pour toutes les applications. Nous voulons nous assurer que le contenu de cette ligne est juste afin de garder la confiance des utilisateurs.
  1. L'épisode suivant est ajouté lorsque l'épisode en cours de lecture est terminé.
  • Lorsque les utilisateurs regardent une série TV, l'application doit leur permettre de continuer à la regarder plus facilement en ajoutant l'épisode suivant à la ligne "Ma sélection".
  1. L'application n'ajoute aucun contenu avec lequel l'utilisateur n'a pas interagi à "Ma sélection".
  • Conformément aux consignes relatives à "Ma sélection", l'application ne doit ajouter un film ou un épisode de série TV à cette chaîne que si l'utilisateur a commencé à regarder ce contenu.
  • Il est déconseillé d'ajouter des bandes-annonces ou de courts extraits vidéo à la chaîne "Ma sélection" puisqu'il n'est pas réellement question de réengagement ici
  1. Ajoutez tous les contenus mis en pause dans "Ma sélection".
  • Les fournisseurs ne doivent pas limiter artificiellement le nombre de fiches qu'ils ajoutent à "Ma sélection". Si un utilisateur n'a pas terminé la lecture d'un contenu, les fournisseurs doivent l'ajouter à la ligne "Ma sélection"
  1. L'application définit des métadonnées complètes et correctes.
  • Assurez-vous que les métadonnées associées à l'épisode sont correctes.
  • Le numéro de l'épisode, le numéro de la saison et le titre doivent être corrects.
  • La barre de progression doit être proportionnelle à la durée de visionnage.
  • L'image de l'épisode ou de la série doit apparaître dans la tuile.
  1. L'application doit éviter d'ajouter plusieurs épisodes pour la même série TV.
  • L'application ne doit conserver qu'une seule entrée "Ma sélection" pour chaque série TV. Si un utilisateur regarde la moitié de deux épisodes différents, seul le dernier visionné doit apparaître dans "Ma sélection"

Ces exigences de qualité permettront à votre application d'offrir une expérience utilisateur optimale sur "Ma sélection".

C'est parti ! Commençons à développer des fonctionnalités pour "Ma sélection" en suivant ces guides de qualité.

Connaissances acquises

Dans cette section, vous avez acquis des connaissances sur les aspects suivants :

  • Exigences en termes de qualité pour "Ma sélection".

Et maintenant ?

Ajouter un épisode mis en pause à la chaîne "Ma sélection"

4. Ajouter des contenus mis en pause à "Ma sélection"

Commençons par la fonctionnalité de base : ajouter un épisode mis en pause à "Ma sélection".

L'atelier de programmation vous expliquera comment créer un WatchNextProgram, indiquer les bonnes métadonnées pour l'épisode, telles que le numéro de l'épisode et de la saison, le type de vidéo, etc. L'entrée "Ma sélection" peut être mise à jour pour s'assurer qu'elle affiche bien les dernières positions de lecture, afin de permettre aux utilisateurs de reprendre leur lecture en cliquant sur le programme.

Cette section traite des sujets suivants :

  • Le programme est ajouté à "Ma sélection" lorsqu'il est mis en pause/arrêté.
  • L'application peut reprendre la lecture à partir de "Ma sélection".
  • L'application met à jour rapidement la position de lecture dans "Ma sélection".
  • L'application définit des métadonnées complètes et correctes.

Ajouter une vidéo mise en pause : différence entre les films et les épisodes

La procédure pour ajouter un film et un épisode à la chaîne "Ma sélection" est très similaire. La seule différence réside dans les métadonnées de chacun.

Par exemple, pour les épisodes, des méthodes de métadonnées spécifiques sont disponibles dans WatchNextProgram.Builder, comme setEpisodeNumber, setSeasonNumber(), setSeasonTitle() et setEpisodeTitle()

Ajouter une vidéo mise en pause (film/épisode de série) à la chaîne "Ma sélection"

Pour ajouter une vidéo mise en pause à la chaîne "Ma sélection", les développeurs peuvent utiliser WatchNextProgram.Builder afin de créer une instance WatchNextProgram et appeler PreviewChannelHelper.publishWatchNextProgram pour la publier sur la chaîne "Ma sélection".

Commencez par créer une instance de compilateur de WatchNextProgram, puis définissez toutes les métadonnées pour décrire la vidéo.

En recherchant la méthode setBuilderMetadata dans PlayNextHelper.kt dans step_1, copiez et collez le code suivant entre les commentaires "Step 1.1 - Set video metadata for WatchNextProgram.".

WatchNextHelper.kt

builder.setType(type)
   .setWatchNextType(watchNextType)
   .setLastPlaybackPositionMillis(watchPosition)
   .setLastEngagementTimeUtcMillis(System.currentTimeMillis())
   .setTitle(video.name)
   .setDurationMillis(duration.toMillis().toInt())
   .setPreviewVideoUri(Uri.parse(video.videoUri))
   .setDescription(video.description)
   .setPosterArtUri(Uri.parse(video.thumbnailUri))
   // Intent uri used to deep link video when the user clicks on watch next item.
   .setIntentUri(Uri.parse(video.uri))
   .setInternalProviderId(video.id)
   // Use the contentId to recognize the same content across different channels.
   .setContentId(video.id)

if (type == TYPE_TV_EPISODE) {
   builder.setEpisodeNumber(video.episodeNumber.toInt())
       .setSeasonNumber(video.seasonNumber.toInt())
       // User TV series name and season number to generate a fake season name.
       .setSeasonTitle(context.getString(
           R.string.season, video.category, video.seasonNumber))
       // Use the name of the video as the episode name.
       .setEpisodeTitle(video.name)
       // Use TV series name as the tile, in this sample,
       // we use category as a fake TV series.
       .setTitle(video.category)
}

Lisez le code à l'étape 1.1 et essayez de comprendre pourquoi nous définissons ces métadonnées.

  1. setLastPlaybackPositionMillis() et setDurationMillis() permettent d'afficher la progression de la lecture et de la mettre à jour lorsque l'utilisateur interagit avec la vidéo.
  2. setLastEngagementTimeUtcMillis() définit le code temporel correspondant au moment où l'utilisateur a regardé cette vidéo. La chaîne "Ma sélection" peut ainsi prioriser les entrées.

Ajouter un film mis en pause à "Ma sélection"

Nous pouvons utiliser WATCH_NEXT_TYPE_NEXT pour ajouter un film mis en pause à la chaîne "Ma sélection".

Définir les métadonnées d'un film : titre et description

Pour les films, définissez le titre et la description, ainsi que d'autres attributs, afin que les utilisateurs sachent qu'ils regardent le bon contenu sans avoir à cliquer jusqu'à atteindre la vidéo.

builder.setType(type)
   .setWatchNextType(watchNextType)
   .setLastPlaybackPositionMillis(watchPosition)
   .setLastEngagementTimeUtcMillis(System.currentTimeMillis())
   .setTitle(video.name)
   .setDurationMillis(duration.toMillis().toInt())
   .setPreviewVideoUri(Uri.parse(video.videoUri))
   .setDescription(video.description)
   .setPosterArtUri(Uri.parse(video.thumbnailUri))
...

Exemple d'un capture d'écran pour un film.

99a21ecd22268f2d.png

Ajouter un épisode mis en pause à "Ma sélection"

Vous disposez de quatre types pour setWatchNextType(), utilisez WATCH_NEXT_TYPE_CONTINUE pour lire les épisodes mis en pause et WATCH_NEXT_TYPE_NEXT pour lire l'épisode suivant.

Définir les métadonnées d'un épisode : numéro/titre de l'épisode et de la saison

Pour les épisodes de séries TV, définissez le numéro de l'épisode et de la saison afin que les utilisateurs sachent qu'ils regardent le bon épisode sans avoir à cliquer jusqu'à la vidéo.

if (type == TYPE_TV_EPISODE) {
   Builder.setType(PreviewPrograms.TYPE_EPISODE)
       .setEpisodeNumber(video.episodeNumber.toInt())
       .setSeasonNumber(video.seasonNumber.toInt())
       // Use TV series name and season number to generate a fake season name.
       .setSeasonTitle(context.getString(
           R.string.season, video.category, video.seasonNumber))
       // Use the name of the video as the episode name.
       .setEpisodeTitle(video.name)
       // Use TV series name as the tile, in this sample,
       // we use category as a fake TV series.
       .setTitle(video.category)
}

SeasonTitle, EpisodeTitle et Title doivent être correctement définis. Chaque épisode a son propre titre pour décrire le contenu de l'épisode. Nous pouvons l'utiliser pour EpisodeTitle. Utilisez le titre de la série TV pour l'attribut titre de la série TV afin que les utilisateurs sachent à quoi renvoient les épisodes. Si la saison possède un titre, utilisez-le pour SeasonTitle. Si tel n'est pas le cas, vous pouvez combiner le nom de la série et le numéro de la saison, par exemple <Nom de la série> saison <numéro de la saison>.

Exemple d'une capture d'écran pour un épisode.

658c430b13bcb3a6.png

Reprendre la lecture

setLastPlaybackPositionMillis(watchPosition) permet de transmettre l'heure à laquelle l'utilisateur a arrêté le film ou l'épisode. Cette progression s'affiche sur la carte "Ma sélection". Dans l'application TV de référence, le code utilise WatchProgressDatabase pour suivre la progression de la lecture de chaque vidéo. Les utilisateurs peuvent ainsi reprendre la lecture là où ils l'avaient laissée, quelle que soit la façon dont ils accèdent à la vidéo.

Conformément aux consignes de lecture des actions de visionnage, la lecture de l'épisode doit commencer immédiatement après le chargement du contenu vidéo. Vous n'avez pas besoin d'afficher les informations du programme à nouveau, car les utilisateurs ont déjà commencé à le regarder.

Ensuite, appelez PreviewChannelHelper.publishWatchNextProgram pour la publier sur la chaîne "Ma sélection". Recherchez "Step 1.2" dans le même fichier et collez le code suivant :

WatchNextHelper.kt

try {
   programId = PreviewChannelHelper(context)
       .publishWatchNextProgram(updatedProgram)
   Timber.v("Added New program to Watch Next row: ${updatedProgram.title}")
} catch (exc: IllegalArgumentException) {
   Timber.e(
       exc, "Unable to add program to Watch Next row. ${exc.localizedMessage}"
   )
   exc.printStackTrace()
}

Actualiser la progression de la lecture

Si une carte "Ma sélection" existe déjà sur la chaîne du même nom, l'application doit la maintenir à jour si l'utilisateur continue le visionnage de la vidéo, pour qu'elle reflète sa progression de lecture.

Lorsque vous mettez à jour un WatchNextProgram, utilisez la même classe de compilateur pour créer un WatchNextProgram et appelez updateWatchNextProgram de PreviewChannelHelper pour mettre à jour une entrée existante. Collez le code suivant dans "Step 1.3", dans WatchNextHelper.kt.

WatchNextHelper.kt

programId = existingProgram.id
PreviewChannelHelper(context).updateWatchNextProgram(updatedProgram, programId)

Vérifier votre résultat

Parcourez le code, comparez vos modifications à la source dans step_1_completed, exécutez step_1_completed et commencez à regarder un épisode. Vérifiez ensuite si l'épisode a été ajouté à la chaîne "Ma sélection".

Validations

  • ✅ RÉUSSITE : le programme est ajouté à "Ma sélection" lorsqu'il est mis en pause/arrêté.
  • ✅ RÉUSSITE : l'application peut reprendre la lecture à partir de "Ma sélection".
  • ✅ RÉUSSITE : l'application met à jour rapidement la position de lecture dans "Ma sélection".
  • ✅ RÉUSSITE : l'application définit des métadonnées complètes et correctes.
  • ✅ RÉUSSITE : tous les contenus mis en pause sont ajoutés à "Ma sélection".
  • ❗ ÉCHEC : le programme est supprimé de "Ma sélection" une fois la lecture terminée.
  • ❗ ÉCHEC : l'épisode suivant est ajouté lorsque l'épisode en cours de lecture est terminé.
  • ❗ ÉCHEC : l'application n'ajoute aucun contenu avec lequel l'utilisateur n'a pas interagi à "Ma sélection".
  • ❗ ÉCHEC : l'application n'ajoute pas plusieurs épisodes pour la même série TV.

Connaissances acquises

Dans cette section, vous avez appris à :

  • créer un WatchNextProgram ;
  • insérer ou mettre à jour le programme WatchNextProgram dans la chaîne "Ma sélection" ;
  • mettre à jour la progression de la lecture ;
  • reprendre la lecture ;
  • définir les bonnes métadonnées pour un épisode de série TV.

Et maintenant ?

Ajouter un épisode mis en pause à la chaîne "Ma sélection"

5. Supprimer le contenu (films/épisodes) de "Ma sélection" une fois la lecture terminée

Les cartes de la chaîne "Ma sélection" sont classées en fonction de la date et de l'heure de la dernière interaction. La dernière vidéo visionnée est placée au début de la chaîne. L'application doit supprimer le programme de la chaîne "Ma sélection" une fois celui-ci totalement visionné et proposer du contenu plus pertinent à l'utilisateur.

Les développeurs doivent surveiller la progression de la lecture d'une vidéo. Une fois qu'un utilisateur a terminé de regarder une vidéo, l'application doit la supprimer de la chaîne "Ma sélection"

Remarque : vous pouvez utiliser la même logique pour supprimer un film ou un épisode de la chaîne "Ma sélection".

Supprimer WatchNextProgram

Pour supprimer une entrée de la chaîne "Ma sélection", les développeurs doivent trouver le WatchNextProgram correct et utiliser l'URI du programme pour le supprimer du fournisseur de contenu. Pour ce faire, les développeurs doivent faire correspondre WatchNextProgram avec les entités vidéo de leur propre base de données. Nous pouvons exploiter le champ "internalProviderId", définir un identifiant vidéo unique et l'associer à l'une des entités de la base de données du développeur.

Tout d'abord, trouvez le WatchNextProgram approprié en recherchant l'ID de la vidéo. Vous pouvez accéder à internalProviderId à partir de WatchNextProgram. getInternalProviderId ou y accéder via le fournisseur de contenu WatchNextProgram, puis le supprimer de la chaîne "Ma sélection" avec l'URI.

Recherchez "Step 2.1" et copiez et collez les éléments suivants :

WatchNextHelper.kt

val foundProgram = getWatchNextProgramByVideoId(video.id, context)
if (foundProgram == null) {
   Timber.e(
       "Unable to delete. No program found with videoID ${video.id}"
   )
   return null
}

// Use the found program's URI to delete it from the content resolver
return foundProgram.let {
   val programUri = TvContractCompat.buildWatchNextProgramUri(it.id)
   // delete returns the number of rows deleted.
   val deleteCount = context.contentResolver.delete(
       programUri, null, null
   )

   if (deleteCount == 1) {
       Timber.v("Content successfully removed from Watch Next")
       programUri
   } else {
       Timber.e("Content failed to be removed from Watch Next, delete count $deleteCount")
       null
   }
}

Si vous souhaitez supprimer plusieurs WatchNextProgram à la fois, nous vous recommandons d'utiliser une requête d'opération groupée afin d'optimiser les visites chez le fournisseur de contenu de votre téléviseur. Recherchez "Step 2.2", puis copiez et collez l'extrait de code suivant dans WatchNextHelper.kt.

WatchNextHelper.kt

val foundPrograms = getWatchNextProgramByVideoIds(videos.map { it.id }, context)
val operations = foundPrograms.map {
   val programUri = TvContractCompat.buildWatchNextProgramUri(it.id)
   ContentProviderOperation.newDelete(programUri).build()
} as ArrayList<ContentProviderOperation>

val results = context.contentResolver.applyBatch(TvContractCompat.AUTHORITY, operations)

results.forEach { result ->
   if (result.count != 1) {
       Timber.e("Content failed to be removed from Watch Next: ${result.uri}")
   }
}

Conformément aux consignes relatives à "Ma sélection", un épisode doit être supprimé si l'utilisateur l'a terminé. L'utilisateur a terminé un épisode si le générique de fin commence. Dans ce cas, ne l'ajoutez pas à la chaîne "Ma sélection" (ou ne le supprimez pas s'il a déjà été ajouté). Vous pouvez déterminer cet état à l'aide d'une fonctionnalité permettant de détecter automatiquement les génériques de fin. Vous pouvez aussi définir approximativement le début du générique de fin en fonction de la durée du contenu (par exemple, à moins de 3 minutes de la fin d'un épisode).

En examinant la méthode handleWatchNextForEpisodes() dans WatchNextHelper.kt, vous pouvez trouver l'extrait suivant :

WatchNextHelper.kt

video.isAfterEndCreditsPosition(watchPosition.toLong()) -> {
   removeVideoFromWatchNext(context, video)

   ...
}

Dans cet atelier de programmation, nous utilisons VIDEO_COMPLETED_DURATION_MAX_PERCENTAGE pour simuler la position du générique de fin. Vous pouvez remplacer le code dans isAfterEndCreditsPosition() en utilisant votre propre logique.

Vérifier votre résultat

Parcourez le code, comparez vos modifications avec la source dans step_2_completed, exécutez step_2_completed et regardez un épisode. Vérifiez ensuite si l'épisode a été supprimé de la chaîne "Ma sélection" une fois la lecture terminée.

Validation

  • ✅ RÉUSSITE : le programme est ajouté à "Ma sélection" lorsqu'il est mis en pause/arrêté.
  • ✅ RÉUSSITE : l'application peut reprendre la lecture à partir de "Ma sélection".
  • ✅ RÉUSSITE : l'application met à jour rapidement la position de lecture dans "Ma sélection".
  • ✅ RÉUSSITE : l'application définit des métadonnées complètes et correctes.
  • ✅ RÉUSSITE : tous les contenus mis en pause sont ajoutés à "Ma sélection".
  • ✅ RÉUSSITE : le programme est supprimé de "Ma sélection" une fois la lecture terminée.
  • ❗ ÉCHEC : l'épisode suivant est ajouté lorsque l'épisode en cours de lecture est terminé.
  • ❗ ÉCHEC : l'application n'ajoute aucun contenu avec lequel l'utilisateur n'a pas interagi à "Ma sélection".
  • ❗ ÉCHEC : l'application n'ajoute pas plusieurs épisodes pour la même série TV.

Connaissances acquises

Dans cette introduction, vous avez appris à :

  • identifier le générique de fin des épisodes de série TV ;
  • utiliser l'ID de la vidéo pour trouver WatchNextProgram ;
  • supprimer un seul WatchNextProgram ;
  • supprimer plusieurs WatchNextProgram.

Et maintenant ?

Ajouter l'épisode suivant à la chaîne "Ma sélection"

6. Ajouter l'épisode suivant

Contrairement aux films, les séries TV comportent plusieurs saisons composées de nombreux épisodes. Si un utilisateur regarde un épisode dans son intégralité, au lieu de simplement le supprimer de la chaîne "Ma sélection", il est recommandé de le remplacer par l'épisode suivant. L'épisode suivant peut être l'épisode qui suit celui qui vient d'être visionné, ou bien, si la saison est terminée, le premier épisode de la saison suivante.

Lorsque vous ajoutez l'épisode suivant à la chaîne "Ma sélection", définissez le type sur WATCH_NEXT_TYPE_NEXT. Cela indique que cet épisode ne provient pas d'un programme visionné par le passé, mais qu'il s'agit d'un nouvel épisode qui pourrait plaire à l'utilisateur. Les applications doivent permettre à l'utilisateur de regarder le prochain épisode depuis le début. Recherchez "TODO: Step 3.1 - Add next episode from TV series.", puis copiez et collez le code suivant à l'étape 3.1 :

WatchNextHelper.kt

videoRepository.getNextEpisodeInSeries(video)?.let {
       insertOrUpdateVideoToWatchNext(
           it,
           0,
           WATCH_NEXT_TYPE_NEXT,
           context
       )
       newWatchNextVideo = it
   }

L'épisode suivant est défini par la méthode getNextEpisodeInSeries().

Épisode suivant de la même saison

Si la saison en cours n'est pas terminée, les applications doivent sélectionner le prochain épisode disponible et le définir comme épisode suivant.

Premier épisode de la saison suivante

Si l'utilisateur a terminé de regarder la saison en cours, mais qu'une nouvelle saison est disponible, les applications doivent sélectionner le premier épisode de la saison suivante et le définir comme épisode suivant.

Nouvel épisode disponible

S'il n'y a plus d'épisode, vous n'avez pas besoin d'en ajouter un autre. Cependant, lorsqu'un nouvel épisode est disponible, il est préférable de l'envoyer côté client et de l'ajouter à la chaîne "Ma sélection". Les nouveaux épisodes doivent utiliser WATCH_NEXT_TYPE_NEW comme type pour WatchNextProgram. Cette solution nécessite des notifications push du serveur, qui ne sont pas abordées dans le cadre de cet atelier de programmation.

Vérifier votre résultat

Parcourez le code, comparez vos modifications avec la source dans step_3_completed, exécutez step_3_completed et regardez un épisode. Vérifiez ensuite si l'épisode suivant a été ajouté à la chaîne "Ma sélection" une fois le visionnage terminé.

Validation

  • ✅ RÉUSSITE : le programme est ajouté à "Ma sélection" lorsqu'il est mis en pause/arrêté.
  • ✅ RÉUSSITE : l'application peut reprendre la lecture à partir de "Ma sélection".
  • ✅ RÉUSSITE : l'application met à jour rapidement la position de lecture dans "Ma sélection".
  • ✅ RÉUSSITE : l'application définit des métadonnées complètes et correctes.
  • ✅ RÉUSSITE : tous les contenus mis en pause sont ajoutés à "Ma sélection".
  • ✅ RÉUSSITE : le programme est supprimé de "Ma sélection" une fois la lecture terminée.
  • ✅ RÉUSSITE : l'épisode suivant est ajouté lorsque l'épisode en cours de lecture est terminé.
  • ❗ ÉCHEC : l'application n'ajoute aucun contenu avec lequel l'utilisateur n'a pas interagi à "Ma sélection".
  • ❗ ÉCHEC : l'application n'ajoute pas plusieurs épisodes pour la même série TV.

Connaissances acquises

Dans cette section, vous avez appris à :

  • sélectionner l'épisode suivant ;
  • ajouter l'épisode suivant de séries TV.

Et maintenant ?

Comprendre l'intérêt de l'utilisateur

7. Comprendre l'intérêt de l'utilisateur

L'application doit prendre en compte plusieurs paramètres afin que les utilisateurs choisissent le contenu le plus pertinent lorsqu'ils ajoutent ou suppriment un épisode de série TV à la chaîne "Ma sélection".

Plusieurs épisodes de la même série

Un utilisateur peut avoir plusieurs épisodes en cours en même temps, et ce pour plusieurs raisons. Par exemple :

  1. la série TV est disponible sur plusieurs applications ou en direct ;
  2. l'utilisateur souhaite accélérer et ignore certains contenus.

La chaîne "Ma sélection" a très peu d'entrées sur l'écran d'accueil. Google conseille aux applications de garder un seul épisode de chaque série TV dans "Ma sélection". Il doit s'agir du dernier épisode regardé par l'utilisateur.

Dans la classe WatchNextHelper, nous le traitons dans handlePlayNextForEpisode(). Recherchez "Step 4.1", puis copiez et collez le code suivant dans la zone vide de l'étape 4.1 :

WatchNextHelper.kt

newWatchNextVideo?.let { videoToKeep ->
   videoRepository.getAllVideosFromSeries(videoToKeep.seriesUri)?.let { allEpisodes ->
           filterWatchNextVideos(allEpisodes, context)
               ?.let { watchedEpisodes ->
                   removeVideosFromWatchNext(
                       context, watchedEpisodes.filter { it.id != videoToKeep.id })
               }
       }
}

À l'étape 4.1, nous gardons le dernier épisode regardé par un utilisateur, et supprimons tous les autres épisodes de la même série TV. Étant donné que cette étape supprime plusieurs épisodes à la fois, nous avons créé une nouvelle méthode removeVideosFromWatchNext() pour utiliser l'opération groupée du fournisseur de contenu Android.

Contenu le moins sollicité

Conformément aux consignes relatives à "Ma sélection", un épisode ne doit être ajouté à la chaîne "Ma sélection" que si l'utilisateur a commencé à regarder le contenu. Un contenu a commencé à être visionné si l'utilisateur en a regardé plus de 2 minutes. Recherchez "Step 4.2", puis copiez et collez le code suivant dans la zone de l'étape 4.2 :

WatchNextHelper.kt

val durationInMilliSeconds = duration.toMillis().toInt()
// Return true if either X minutes or Y % have passed
// Following formatting spans over multiple lines to accommodate max 100 limit
val watchNextMinStartedMillis = TimeUnit.MINUTES.toMillis(WATCH_NEXT_STARTED_MIN_MINUTES)
// Check if either X minutes or Y% has passed
val hasVideoStarted =
   (currentPosition >= (durationInMilliSeconds * WATCH_NEXT_STARTED_MIN_PERCENTAGE)) or
           (currentPosition >= watchNextMinStartedMillis)
val hasVideoStartedWithValidPosition =
   ((currentPosition <= durationInMilliSeconds) and hasVideoStarted)
Timber.v(
   "Has video started: %s, duration: %s, watchPosition: %s",
   hasVideoStartedWithValidPosition,
   duration,
   currentPosition
)
return hasVideoStartedWithValidPosition

Vérifier votre résultat

Parcourez le code, comparez vos modifications avec la source dans step_4_completed, exécutez step_4_completed et regardez un épisode. Vérifiez ensuite si :

  1. le code supprime un épisode supplémentaire de la série TV ;
  2. le contenu est ajouté à la chaîne "Ma sélection" seulement si un utilisateur a commencé à regarder la vidéo.

Validation

  • ✅ RÉUSSITE : le programme est ajouté à "Ma sélection" lorsqu'il est mis en pause/arrêté.
  • ✅ RÉUSSITE : l'application peut reprendre la lecture à partir de "Ma sélection".
  • ✅ RÉUSSITE : l'application met à jour rapidement la position de lecture dans "Ma sélection".
  • ✅ RÉUSSITE : l'application définit des métadonnées complètes et correctes.
  • ✅ RÉUSSITE : tous les contenus mis en pause sont ajoutés à "Ma sélection".
  • ✅ RÉUSSITE : le programme est supprimé de "Ma sélection" une fois la lecture terminée.
  • ✅ RÉUSSITE : l'épisode suivant est ajouté lorsque l'épisode en cours de lecture est terminé.
  • ✅ RÉUSSITE : l'application n'ajoute aucun contenu avec lequel l'utilisateur n'a pas interagi à "Ma sélection".
  • ✅ RÉUSSITE : l'application n'ajoute pas plusieurs épisodes pour la même série TV.

Connaissances acquises

Dans cette section, vous avez appris à :

  • éviter d'ajouter plusieurs épisodes de la même série TV ;
  • éviter d'ajouter du contenu moins sollicité.

Et maintenant ?

Félicitations

8. Félicitations

Félicitations, vous avez créé "Ma sélection" pour vos épisodes de série TV et avez appris toutes les exigences de qualité la concernant.

Bravo !

Complément d'information

Documents de référence