Android TV の映画 / テレビ エピソード用 Watch Next のエンゲージメントを向上させる

1. はじめに

Watch Next

Watch Next チャンネルはユーザーが次に視聴する動画といっしょに Android TV のホーム画面に表示されます。Watch Next 行はシステム バージョンによって「次のおすすめ」と呼ばれる場合と「続きを見る」と呼ばれる場合があります。

b0ca4ea7c72ba8f6.png

このチャンネルはシステムが作成し管理します。このチャンネルの各項目はプログラムと呼ばれます。アプリでは、ユーザーが途中で視聴を止めたコンテンツや、ユーザーが操作したコンテンツ(シリーズの次のエピソードや番組の次のシーズンなど)などのプログラムを Watch Next チャンネルに追加したり、このチャンネルから削除したり、このチャンネルにあるプログラムを更新したりできます。

コンセプト

Watch Next チャンネルは、アプリでユーザーの再エンゲージメントを促進する手段を提供します。

ユーザーがすでに操作しているコンテンツを Watch Next チャンネルに追加したり、このチャンネルから削除したり、このチャンネルにあるコンテンツを更新したりできます。視聴途中の動画でも、次のエピソードやシリーズの提案でも構いません。

アプリから視聴後にエピソードを削除することも、シリーズの新しいシーズンの次のエピソードを追加することもできます。

Watch Next チャンネルには 4 種類のユースケースがあります。

  • ユーザーが視聴を終えていない動画の視聴を続行する。
  • に視聴する動画を提案する。たとえば、ユーザーがエピソード 1 の視聴を終了した場合に、エピソード 2 を提案できます。
  • ユーザーが視聴していたシリーズの新しいエピソードを表示する。
  • ユーザーが追加した興味がある動画の観たいものリストを維持する。

この Codelab では、ユーザーが動画を一時停止したときに Watch Next チャンネルに動画を追加する方法について説明します。また、最後まで再生されたときに動画を Watch Next から削除する方法と、次のエピソードを追加する方法(利用可能な場合)についても説明します。

この Codelab では、新しくリリースされたエピソードと観たいものリストに関する Watch Next のユースケースは扱いません。

映画とテレビ エピソード用の Watch Next

Watch Next チャンネルは、Android TV のホーム画面に備わる非常に重要な機能です。視聴途中の映画やテレビ番組をチェックするのに役立ちます。テレビ エピソードを視聴するユーザーにとって、この機能は特に重要です。なぜなら、テレビシリーズには多くのエピソードがあり、中断したところから視聴を再開することが何度もあるためです。

ユーザーが帰宅して、テレビの前に座り、何を観るか決めようとしているところを想像してみてください。Watch Next を使用すると、アプリではホーム画面から直接、再生を中断したところからテレビ エピソードの視聴を再開できます。これにより、ユーザーの再エンゲージメントを向上させ、アプリとユーザーの双方にメリットをもたらすことができます。

この Codelab では、テレビ リファレンス アプリについて詳しく見ていくほか、Watch Next チャンネルのさまざまなケースへの対応方法と、Google が定める Watch Next 機能の品質に関するガイドラインについて説明します。この Codelab では特にテレビ エピソードの取り扱いに焦点を当てていますが、同様のルールを映画にも適用できます。

対応状況

この Codelab のコードは、Android TV デバイスで動作します(これには Google TV エクスペリエンスを実行するものも含まれます)。

作成するアプリの概要

この Codelab では、テレビ映画 / エピソード用 Watch Next チャンネルの追加、削除、更新を行います。作成するアプリでは次を実現します。

  • 映画を扱うさまざまなユースケース
  • テレビ エピソードを扱うさまざまなユースケース

学習内容

  • Google が定める Watch Next の品質に関するガイドライン

必要なもの

  • Android アプリ開発の基本的な知識
  • Android Studio 4.1 以降(こちらからダウンロードできます)

2. 設定方法

スターター プロジェクトのクローンを作成する

GitHub リポジトリからソースコードをダウンロードできます。

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

下のリンクから直接ダウンロードすることもできます。

Android Studio を開き、メニューバーから [File] > [Open] をクリックするか、ウェルカム画面から [Open an Existing Android Studio Project] をクリックして、最近クローンを作成したフォルダを選択します。

8271a7b581390845.png

スターター プロジェクトについて

34641bc2c9f71f0f.png

プロジェクトには 4 つのステップがあります。各ステップで、該当するセクションの手順に沿ってコードを追加します。セクションを完了したら、step_x_completed のコードと自分のコードを比較できます。

簡単にするために、動画の一覧のための基本的なコードと、アプリ内でコンテンツを視聴するための ExoPlayer を追加しています。これが、この Codelab の範囲外であるテレビアプリの基本的なスケルトンとなります。

ここでの目的は、視聴途中と視聴済みの動画を Watch Next チャンネルに追加、削除、更新して、アプリの再エンゲージメントを生み出すことです。

アプリの主なコンポーネントは次のとおりです。

  • FileVideoRepository: 動画メタデータの読み込みとクエリを行うクラスです。
  • PlaybackFragment: 動画再生のフラグメントです。
  • WatchNextPlaybackStateListener: 再生状態変更のリスナーです。再生イベントをリッスンし、関連する操作をトリガーします。
  • WatchNextWorker: Watch Next チャンネルを更新する役目のワーカーです。
  • WatchNextHelper: Watch Next チャンネルの扱いを簡単にするヘルパークラスです。

この Codelab では、res/raw/api.json のメディアデータを使用して Watch Next エントリを設定します。

スターター プロジェクトを実行する

step_1 を実行します。問題がある場合は、開始方法についてのドキュメントをご覧ください。

  1. Android TV を接続するか、エミュレータを起動します。
  1. step_1 構成を選択し、Android デバイスを選択して、メニューバーの実行ボタンを押します。249ea91a556fbd61.png
  2. 以下のスクリーンショットのような、4 つの動画コレクションを含むシンプルなテレビアプリの概要が表示されます。
  3. アプリのメイン画面に移動し、テレビ リファレンス アプリを確認してください。4 つの動画カテゴリがあります。
  4. Supercharged Clips
  5. Misc Clips
  6. Beverly Hillbillies: 2 つのテレビシーズンのいくつかのテレビ エピソード
  7. Charlie Chaplin Movies
  8. [Beverly Hillbillies] のカテゴリにあるテレビ エピソードのうちのひとつをクリックして視聴します。この Codelab では、このようなテレビ エピソード用に Watch Next プログラムを追加する方法を説明します。

d7b51de54f4a1199.png

学習した内容

ここでは、次のことを学習しました。

  • この Codelab で使用されるコード構造と主なクラス
  • サンプルアプリをセットアップして実行する方法

次のステップ

Watch Next の品質に関するガイドライン

3.Watch Next の品質に関するガイドラインを理解する

ホーム画面の利便性を向上させるために、Watch Next にコンテンツを追加するすべてのアプリの動作に一貫性を持たせる必要があります。

具体的には、デベロッパーがテレビ エピソード向けに対応しなければならないシナリオがあります。Google は、Watch Next チャンネルの品質を保証するために守る必要のある、Watch Next の品質に関するガイドラインをまとめています。

Google の品質基準を満たす Watch Next 機能の作成方法

Google が Watch Next の機能を評価する際には、次の点が確認されます。

  1. プログラムが一時停止または停止されたときに Watch Next に追加される。
  2. Watch Next エントリから再生を再開できる。
  3. Watch Next での再生位置が適切なタイミングで更新される。
  4. プログラムの再生が完了すると、Watch Next から削除される。
  5. 現在のエピソードを視聴し終わると、次のエピソードが追加される。
  6. ユーザーが操作していないコンテンツは Watch Next に追加されない。
  7. 視聴途中のコンテンツは、すべて Watch Next に送られる。
  8. シーズン番号やエピソード番号など、正しく完全なメタデータが設定される。
  9. 同じテレビシリーズの複数のエピソードが追加されない。

各品質要件の説明

  1. プログラムが一時停止または停止されたときには Watch Next に追加されます。
  • 再生が完了していない従来の映画やテレビ番組は Watch Next の行に追加されます。
  1. Watch Next エントリから再生を再開できます。
  • Watch Next チャンネルに追加されたコンテンツは、前回の再生位置から再生が再開されます。動画は、コンテンツが読み込まれるとすぐに再生が開始されます。
  1. Watch Next での再生位置は適切なタイミングで更新されます。
  • 再生状況を常に把握するようにして、ユーザーが動画を離れた後には Watch Next プログラムを最新の再生位置に更新する必要があります。
  1. プログラムの再生が完了すると、Watch Next から削除されます。
  • アプリは、行儀よく振る舞い、自分で後始末をする必要があります。Watch Next の行はすべてのアプリで共有するため、ユーザーの信頼を維持するために、この行のコンテンツが正確である必要があります。
  1. 現在のエピソードを視聴し終わると、次のエピソードが追加されます。
  • ユーザーがテレビシリーズを視聴するとき、Watch Next の行にそのシリーズの次のエピソードを追加して続きの視聴が簡単になるようにする必要があります。
  1. ユーザーが操作していないコンテンツは Watch Next に追加されません。
  • Watch Next ガイドラインに従い、映画やテレビ エピソードは、ユーザーが視聴を開始した場合にのみ Watch Next チャンネルに追加する必要があります。
  • 予告編や短い動画クリップを Watch Next チャンネルに追加することはおすすめしません。再エンゲージメントがほとんどないためです。
  1. 視聴途中のコンテンツは、すべて Watch Next に送られます。
  • プロバイダは Watch Next に送るカードの枚数を人為的に制限してはなりません。視聴途中のコンテンツがある場合、Watch Next の行に送る必要があります。
  1. 正しく完全なメタデータが設定されます。
  • エピソードには正しいメタデータを関連付けてください。
  • エピソード番号、シーズン番号、タイトルは正確である必要があります。
  • 進行状況バーは視聴した量に比例している必要があります。
  • エピソードまたはシリーズの画像をタイル内に表示する必要があります。
  1. 同じテレビシリーズの複数のエピソードを追加しないようにする必要があります。
  • Watch Next エントリはテレビシリーズごとに最大 1 つにします。ユーザーが 2 つの別々のエピソードを半分ずつ視聴している場合、Watch Next には最後に視聴されたエピソードだけを表示する必要があります。

上記の品質要件は、Watch Next で優れたユーザー エクスペリエンスを実現するのに役立ちます。

それでは、品質ガイドを念頭に置いて Watch Next 機能の作成を開始しましょう。

学習した内容

ここでは、次のことを学習しました。

  • Watch Next の品質要件

次のステップ

視聴途中のエピソードを Watch Next チャンネルに追加する

4. 視聴途中のコンテンツを Watch Next に追加する

視聴途中のエピソードを Watch Next に追加するという、基本的な機能から始めましょう。

この Codelab では、WatchNextProgram の作成方法と、エピソード番号、シーズン番号、動画タイプなど、エピソードに正しいメタデータを設定する方法を説明します。Watch Next エントリは更新可能であり、最新の再生位置が常に把握されているので、プログラムをクリックして再生を再開できます。

このセクションでは、次のことに対応します。

  • プログラムが一時停止または停止されたときに Watch Next に追加される。
  • Watch Next エントリから再生を再開できる。
  • Watch Next での再生位置が適切なタイミングで更新される。
  • 正しく完全なメタデータが設定される。

視聴途中の動画を追加する - 映画とエピソードの違い

Watch Next チャンネルに映画を追加する手順と、エピソードを追加する手順は、非常によく似ています。唯一の違いは、それぞれメタデータが異なることです。

たとえば、エピソードの場合、WatchNextProgram.BuildersetEpisodeNumber, setSeasonNumber(), setSeasonTitle()setEpisodeTitle() などの専用のメタデータ メソッドがあります。

視聴途中の動画(映画 / エピソード)を Watch Next チャンネルに追加する

視聴途中の動画を Watch Next チャンネルに追加するには、WatchNextProgram.Builder を使用して WatchNextProgram インスタンスを作成し、PreviewChannelHelper.publishWatchNextProgram を呼び出して Watch Next チャンネルにパブリッシュします。

まず、WatchNextProgram の Builder インスタンスを作成し、動画を記述するメタデータをすべて設定します。

step_1PlayNextHelper.ktsetBuilderMetadata メソッドを探し、次のコードをコピーして「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)
}

ステップ 1.1 のコードを読んで、このメタデータを設定する理由を理解してください。

  1. setLastPlaybackPositionMillis()setDurationMillis() により、正確な再生状況が表示され、ユーザーが動画を操作したときに更新されます。
  2. setLastEngagementTimeUtcMillis() により、この動画を視聴したときのタイムスタンプが設定されます。これは、Watch Next チャンネルでエントリの優先度を決めるのに使用されます。

視聴途中の映画を Watch Next に追加する

WATCH_NEXT_TYPE_NEXT を使用すると、視聴途中の映画を Watch Next チャンネルに追加できます。

映画にメタデータを設定する: タイトルと説明

映画の場合は、ユーザーが動画をクリックしなくても正しいコンテンツを視聴していることがわかるように、タイトルや説明などの属性を設定します。

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))
...

映画のスクリーンショットの例

99a21ecd22268f2d.png

視聴途中のエピソードを Watch Next に追加する

setWatchNextType() に使用できるタイプは 4 種類あります。視聴途中のテレビ エピソードには WATCH_NEXT_TYPE_CONTINUE を使用し、次のエピソードには WATCH_NEXT_TYPE_NEXT を使用します。

エピソードのメタデータを設定する: エピソードとシーズンの番号 / タイトル

テレビ エピソードの場合は、ユーザーが動画をクリックしなくても正しいエピソードを視聴していることがわかるように、エピソード番号とシーズン番号を設定します。

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、Title が正しく設定されている必要があります。各エピソードにはそのエピソードの内容を表す独自のタイトルがあり、それを EpisodeTitle に使用できます。テレビ番組のタイトル属性にはテレビシリーズのタイトルを使用して、何のエピソードかわかるようにします。シーズン タイトルがある場合はそれを SeasonTitle に使用しますが、代わりにシリーズ名とシーズン番号を組み合わせて使用することもできます(例: <テレビシリーズ名> シーズン <シーズン番号>)。

エピソードのスクリーンショットの例。

658c430b13bcb3a6.png

再生を再開する

setLastPlaybackPositionMillis(watchPosition) はユーザーが映画 / エピソードから離れた時刻を渡すために使用されます。この再生状況は Watch Next カードに表示されます。テレビ リファレンス アプリのコードでは、WatchProgressDatabase を使用して各動画の再生状況を追跡しています。これにより、ユーザーがどのように動画に移動しても、前の時点から視聴を再開できます。

Watch Action の再生ガイドラインに従い、動画コンテンツが読み込まれるとすぐにエピソードの再生が開始されます。すでに視聴を開始しているため、再度テレビシリーズ情報を表示する必要はありません。

次に、PreviewChannelHelper.publishWatchNextProgram を呼び出して、Watch Next チャンネルにパブリッシュします。同じファイルで「Step 1.2」を探し、次のコードを貼り付けます。

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()
}

再生状況を更新する

Watch Next カードがすでに Watch Next チャンネルに存在している場合、最新の視聴状況が反映されるように、さらに動画が視聴されたときに更新されるようにします。

WatchNextProgram を更新するときには、同じビルダークラスを使用して WatchNextProgram を作成し、PreviewChannelHelperupdateWatchNextProgram を呼び出して既存のエントリを更新します。次のコードを WatchNextHelper.kt の「Step 1.3」に貼り付けます。

WatchNextHelper.kt

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

結果を確認する

コードを確認して変更点を step_1_completed のソースと比較し、step_1_completed を実行してエピソードの一部を視聴し、それが Watch Next チャンネルに追加されているかどうかを確認します。

確認事項

  • ✅ 合格: プログラムが一時停止または停止されたときに Watch Next に追加される。
  • ✅ 合格: Watch Next エントリから再生を再開できる。
  • ✅ 合格: Watch Next での再生位置が適切なタイミングで更新される。
  • ✅ 合格: 正しく完全なメタデータが設定される。
  • ✅ 合格: 視聴途中のコンテンツは、すべて Watch Next に送られる。
  • ❗ 不合格: プログラムの再生が完了すると、Watch Next から削除される。
  • ❗ 不合格: 現在のエピソードを視聴し終わると、次のエピソードが追加される。
  • ❗ 不合格: ユーザーが操作していないコンテンツは Watch Next に追加されない。
  • ❗ 不合格: 同じテレビシリーズの複数のエピソードが追加されない。

学習した内容

このセクションでは、次のことを行う方法について学習しました。

  • WatchNextProgram を作成する。
  • WatchNextProgram を Watch Next チャンネルに挿入、または更新する。
  • 再生状況を更新する。
  • 再生を再開する。
  • テレビ エピソードに正しいメタデータを設定する。

次のステップ

視聴途中のエピソードを Watch Next チャンネルに追加する

5. 再生が完了するとコンテンツ(映画 / エピソード)が Watch Next から削除される

Watch Next チャンネルのカードは、最後のエンゲージメント時間の順に並べられ、直近にエンゲージメントが発生した動画がチャンネルの先頭に表示されます。プログラムの視聴が終わった後には、Watch Next チャンネルから削除し、より関連性の高いコンテンツをユーザーにすすめる必要があります。

動画の再生状況を監視する必要があります。ユーザーが動画を視聴し終わったら、アプリはその動画を Watch Next チャンネルから削除する必要があります。

注: Watch Next チャンネルから映画やエピソードを削除する場合にも、同じロジックを使用できます。

WatchNextProgram を削除する

Watch Next チャンネルからエントリを削除するには、正しい WatchNextProgram を見つけ、プログラム URI を使用してコンテンツ プロバイダから削除する必要があります。そのためには、WatchNextProgram と独自のデータベースにある動画エンティティを照合する必要があります。internalProviderId フィールドを使用して固有の動画 ID を設定し、デベロッパー独自のデータベースにあるエンティティのいずれかにリンクできます。

まず、動画 ID を検索して正しい WatchNextProgram を見つけます。internalProviderId に WatchNextProgram. getInternalProviderId からアクセスするか、WatchNextProgram コンテンツ プロバイダを介してアクセスしてから、URI を使用して Watch Next チャンネルから削除します。

Step 2.1」を探し、次をコピーして貼り付けます。

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
   }
}

複数の WatchNextProgram を一度に削除する場合は、一括処理をリクエストしてテレビのコンテンツ プロバイダへのアクセスを最適化することをおすすめします。「Step 2.2」を探し、次のコード スニペットをコピーして 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}")
   }
}

Watch Next ガイドラインに従い、ユーザーが最後まで視聴したらエピソードを削除する必要があります。エンド クレジットが始まった場合、ユーザーはエピソードを「視聴完了」したことになります。この場合、Watch Next チャンネルには追加しないでください(すでに追加されている場合は削除してください)。この状態を判断するには、エンド クレジットを自動検出する技術や、コンテンツの長さ(エピソードの残りが 3 分未満など)に基づく概算を使用します。

WatchNextHelper.kthandleWatchNextForEpisodes() メソッドには、次のスニペットがあります。

WatchNextHelper.kt

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

   ...
}

この Codelab では、VIDEO_COMPLETED_DURATION_MAX_PERCENTAGE を使用して、クレジット シーンの位置をシミュレートします。isAfterEndCreditsPosition() のコードは独自のロジックに置き換えることができます。

結果を確認する

コードを確認して変更点を step_2_completed のソースと比較し、step_2_completed を実行してエピソードを視聴し、視聴が完了したら Watch Next チャンネルから削除されているかどうかを確認します。

確認事項

  • ✅ 合格: プログラムが一時停止または停止されたときに Watch Next に追加される。
  • ✅ 合格: Watch Next エントリから再生を再開できる。
  • ✅ 合格: Watch Next での再生位置が適切なタイミングで更新される。
  • ✅ 合格: 正しく完全なメタデータが設定される。
  • ✅ 合格: 視聴途中のコンテンツは、すべて Watch Next に送られる。
  • ✅ 合格: プログラムの再生が完了すると、Watch Next から削除される。
  • ❗ 不合格: 現在のエピソードを視聴し終わると、次のエピソードが追加される。
  • ❗ 不合格: ユーザーが操作していないコンテンツは Watch Next に追加されない。
  • ❗ 不合格: 同じテレビシリーズの複数のエピソードが追加されない。

学習した内容

ここでは、次のことを学習しました。

  • テレビ エピソードのクレジット シーンを特定する方法
  • 動画 ID で WatchNextProgram を見つける方法
  • 1 つの WatchNextProgram を削除する方法
  • 複数の WatchNextProgram を削除する方法

次のステップ

次のエピソードを Watch Next チャンネルに追加する

6. 次のエピソードを追加する

映画とは異なり、テレビ番組には複数のシーズンがあり、各シーズンには多数のエピソードがあります。ユーザーがエピソードを視聴し終わったら、それを Watch Next チャンネルから削除するだけでなく、次のエピソードに置き換えることをおすすめします。次のエピソードは、同じシーズン内で視聴したエピソードのすぐ後にあるエピソードとするか、視聴し終わったエピソードが現在のシーズンの最後のエピソードだった場合には次のシーズンの最初のエピソードとします。

次のエピソードを Watch Next チャンネルに追加するときは、Watch Next タイプを WATCH_NEXT_TYPE_NEXT に設定します。これは、このエピソードが以前に視聴されたプログラムではなく、視聴できる完全に新しいエピソードであることを示します。アプリはユーザーが次のエピソードを最初から視聴できるようにする必要があります。「TODO: Step 3.1 - Add next episode from TV series.」を探し、次のコードをコピーして step 3.1 に貼り付けます。

WatchNextHelper.kt

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

次のエピソードは、getNextEpisodeInSeries() メソッドで設定されます。

同じシーズンの次のエピソード

現在のシーズンにまだエピソードが複数残っている場合、アプリは視聴可能なエピソードの中から次のエピソードを選んで設定する必要があります。

次のシーズンの最初のエピソード

ユーザーが現在のシーズンを視聴し終わり、まだ視聴可能な新しいシーズンがある場合、アプリは次のエピソードとして次のシーズンの最初のエピソードを選ぶ必要があります。

リリースされた新しいエピソード

エピソードがそれ以上ない場合、次のエピソードを追加する必要はありません。しかし、新しいエピソードを視聴できる場合は、クライアント サイドにプッシュし、Watch Next チャンネルに追加することをおすすめします。新しいエピソードには WatchNextProgram タイプとして WATCH_NEXT_TYPE_NEW を使用する必要があります。このソリューションにはサーバー プッシュ通知が必要ですが、この Codelab では対応していません。

結果を確認する

コードを確認して変更点を step_3_completed のソースと比較し、step_3_completed を実行してエピソードを視聴し、視聴が完了したら次のエピソードが Watch Next チャンネルに追加されているかどうかを確認します。

確認事項

  • ✅ 合格: プログラムが一時停止または停止されたときに Watch Next に追加される。
  • ✅ 合格: Watch Next エントリから再生を再開できる。
  • ✅ 合格: Watch Next での再生位置が適切なタイミングで更新される。
  • ✅ 合格: 正しく完全なメタデータが設定される。
  • ✅ 合格: 視聴途中のコンテンツは、すべて Watch Next に送られる。
  • ✅ 合格: プログラムの再生が完了すると、Watch Next から削除される。
  • ✅ 合格: 現在のエピソードを視聴し終わると、次のエピソードが追加される。
  • ❗ 不合格: ユーザーが操作していないコンテンツは Watch Next に追加されない。
  • ❗ 不合格: 同じテレビシリーズの複数のエピソードが追加されない。

学習した内容

ここでは、次のことを学習しました。

  • 次のエピソードを選択する方法
  • テレビシリーズの次のエピソードの追加

次のステップ

ユーザーの関心を把握する

7. ユーザーの関心を把握する

Watch Next チャンネルで最も関連性の高いコンテンツにユーザーの関心が向けられた状態を保持するには、テレビ エピソードを Watch Next チャンネルに追加する、またはチャンネルから削除する際に、アプリが考慮しなければならない点があります。

同じシリーズの複数のエピソード

視聴途中のエピソードが同時に複数ある場合、その理由は複数あります。次に例を示します。

  1. そのテレビシリーズが複数のアプリやオンエアで視聴できる。
  2. 短時間で視聴するため、一部の内容を飛ばしたい。

Watch Next チャンネルのホーム画面に表示できるエントリの数は限られています。Google では、Watch Next チャンネルに表示するエピソードの数はテレビシリーズごとに 1 つまでとすることをおすすめしています。その 1 つは最後に視聴されたエピソードにしてください。

これを WatchNextHelper クラスの handlePlayNextForEpisode() で処理します。「Step 4.1」を探し、次のコードをコピーして step 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 })
               }
       }
}

step 4.1 では、直近の視聴されたエピソードを追跡し、同じテレビシリーズの他のエピソードをすべて削除します。このステップでは一度に複数のエピソードを削除するため、Android コンテンツ プロバイダの一括操作を利用する新しいメソッド removeVideosFromWatchNext() を作成しました。

あまり操作されないコンテンツ

Watch Next ガイドラインに従って、視聴が開始された場合にのみ、そのエピソードを Watch Next チャンネルに追加する必要があります。視聴した時間が 2 分を超えた場合に、ユーザーがエピソードを「視聴開始」したことになります。「Step 4.2」を探し、次のコードをコピーして step 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

結果を確認する

コードを確認して変更点を step_4_completed のソースと比較し、step_4_completed を実行してエピソードを視聴し、以下を確認します。

  1. コードによって、テレビシリーズから余分なエピソードが削除される。
  2. ユーザーが視聴を開始した場合にのみ、Watch Next チャンネルに追加される。

確認事項

  • ✅ 合格: プログラムが一時停止または停止されたときに Watch Next に追加される。
  • ✅ 合格: Watch Next エントリから再生を再開できる。
  • ✅ 合格: Watch Next での再生位置が適切なタイミングで更新される。
  • ✅ 合格: 正しく完全なメタデータが設定される。
  • ✅ 合格: 視聴途中のコンテンツは、すべて Watch Next に送られる。
  • ✅ 合格: プログラムの再生が完了すると、Watch Next から削除される。
  • ✅ 合格: 現在のエピソードを視聴し終わると、次のエピソードが追加される。
  • ✅ 合格: ユーザーが操作していないコンテンツは Watch Next に追加されない。
  • ✅ 合格: 同じテレビシリーズの複数のエピソードが追加されない。

学習した内容

ここでは、次のことを学習しました。

  • 同じテレビシリーズの複数のエピソードを追加しない。
  • あまり操作されないコンテンツを追加しない。

次のステップ

完了

8. 完了

テレビ エピソードの Watch Next を作成し、Watch Next の品質要件をすべて学習しました。

これで終了です。

参考資料

リファレンス ドキュメント