このガイドでは、Engage SDK を使用して Android TV アプリに「続きを見る」を統合する方法について説明します。
事前作業
スタートガイドの事前準備の手順を完了します。
統合
エンティティを作成する
この SDK では、各アイテムタイプを表すさまざまなエンティティを定義しています。継続クラスタは、次のエンティティをサポートしています。
これらのエンティティのプラットフォーム固有の URI とポスター画像を指定します。
また、Android TV、Android、iOS などのプラットフォームごとに再生 URI を作成します(まだ作成していない場合)。そのため、ユーザーが各プラットフォームで視聴を続けると、アプリはターゲット再生 URI を使用して動画コンテンツを再生します。
// Required. Set this when you want continue watching entities to show up on
// Google TV
val playbackUriTv = PlatformSpecificUri.Builder()
.setPlatformType(PlatformType.TYPE_ANDROID_TV)
.setActionUri(Uri.parse("https://www.example.com/entity_uri_for_tv"))
.build()
// Required. Set this when you want continue watching entities to show up on
// Google TV Android app, Entertainment Space, Playstore Widget
val playbackUriAndroid = PlatformSpecificUri.Builder()
.setPlatformType(PlatformType.TYPE_ANDROID_MOBILE)
.setActionUri(Uri.parse("https://www.example.com/entity_uri_for_android"))
.build()
// Optional. Set this when you want continue watching entities to show up on
// Google TV iOS app
val playbackUriIos = PlatformSpecificUri.Builder()
.setPlatformType(PlatformType.TYPE_IOS)
.setActionUri(Uri.parse("https://www.example.com/entity_uri_for_ios"))
.build()
val platformSpecificPlaybackUris =
Arrays.asList(playbackUriTv, playbackUriAndroid, playbackUriIos)
ポスター画像には、URI とピクセル単位のサイズ(高さと幅)が必要です。複数のポスター画像を提供することで、さまざまなフォーム ファクタをターゲットに設定できます。ただし、すべての画像のアスペクト比が 16:9 で、高さが 200 ピクセル以上であることを確認してください。これは、「続きを見る」エンティティを正しく表示するために必要です。特に Google のエンターテイメント スペースでは、この要件を満たす必要があります。高さが 200 ピクセル未満の画像は表示されない場合があります。
val images = Arrays.asList(
Image.Builder()
.setImageUri(Uri.parse("http://www.example.com/entity_image1.png"))
.setImageHeightInPixel(300)
.setImageWidthInPixel(169)
.build(),
Image.Builder()
.setImageUri(Uri.parse("http://www.example.com/entity_image2.png"))
.setImageHeightInPixel(640)
.setImageWidthInPixel(360)
.build()
// Consider adding other images for different form factors
)
MovieEntity
次の例は、すべての必須フィールドを含む MovieEntity を作成する方法を示しています。
val movieEntity = MovieEntity.Builder()
.setWatchNextType(WatchNextType.TYPE_CONTINUE)
.setName("Movie name")
.addPlatformSpecificPlaybackUris(platformSpecificPlaybackUris)
.addPosterImages(images)
// Timestamp in millis for sample last engagement time 12/1/2023 00:00:00
.setLastEngagementTimeMillis(1701388800000)
// Suppose the duration is 2 hours, it is 72000000 in milliseconds
.setDurationMillis(72000000)
// Suppose last playback offset is 1 hour, 36000000 in milliseconds
.setLastPlayBackPositionTimeMillis(36000000)
.setCallToActionText("Resume")
.addTag("Action")
.build()
ジャンルやコンテンツのレーティングなどの詳細情報を提供することで、Google TV はコンテンツをよりダイナミックに紹介し、適切な視聴者と結び付けることができます。
val genres = Arrays.asList("Action", "Science fiction")
val rating1 = RatingSystem.Builder().setAgencyName("MPAA").setRating("PG-13").build()
val contentRatings = Arrays.asList(rating1)
val movieEntity = MovieEntity.Builder()
...
.addGenres(genres)
.addContentRatings(contentRatings)
.build()
より短い有効期限を指定しない限り、エンティティは 60 日間自動的に利用可能な状態を維持します。このデフォルト期間よりも前にエンティティを削除する必要がある場合にのみ、カスタムの有効期限を設定してください。
// Set the expiration time to be now plus 30 days in milliseconds
val expirationTime = DisplayTimeWindow.Builder()
.setEndTimestampMillis(now().toMillis()+2592000000).build()
val movieEntity = MovieEntity.Builder()
...
.addAvailabilityTimeWindow(expirationTime)
.build()
TvEpisodeEntity
次の例は、すべての必須フィールドを含む TvEpisodeEntity を作成する方法を示しています。
val tvEpisodeEntity = TvEpisodeEntity.Builder()
.setWatchNextType(WatchNextType.TYPE_CONTINUE)
.setName("Episode name")
.addPlatformSpecificPlaybackUris(platformSpecificPlaybackUris)
.addPosterImages(images)
// Timestamp in millis for sample last engagement time 12/1/2023 00:00:00
.setLastEngagementTimeMillis(1701388800000)
.setDurationMillis(72000000) // 2 hours in milliseconds
// 45 minutes and 15 seconds in milliseconds is 2715000
.setLastPlayBackPositionTimeMillis(2715000)
.setEpisodeNumber("2")
.setSeasonNumber("1")
.setShowTitle("Title of the show")
.setCallToActionText("Resume")
.addTag("Comedy")
.build()
エピソード番号の文字列("2" など)とシーズン番号の文字列("1" など)は、[続きを見る] カードに表示される前に適切な形式に展開されます。これらは数字の文字列にする必要があります。「e2」、「episode 2」、「s1」、「season 1」などは指定しないでください。
特定のテレビ番組にシーズンが 1 つしかない場合は、シーズン番号を 1 に設定します。
視聴者が Google TV でコンテンツを見つけやすくするには、ジャンル、コンテンツのレーティング、視聴可能な期間などの追加データを提供することを検討してください。これらの詳細情報により、表示やフィルタリングのオプションを強化できます。
val genres = Arrays.asList("Action", "Science fiction")
val rating1 = RatingSystem.Builder().setAgencyName("MPAA").setRating("PG-13").build()
val contentRatings = Arrays.asList(rating1)
val tvEpisodeEntity = TvEpisodeEntity.Builder()
...
.addGenres(genres)
.addContentRatings(contentRatings)
.setSeasonTitle("Season Title")
.setShowTitle("Show Title")
.build()
VideoClipEntity
すべての必須フィールドを含む VideoClipEntity を作成する例を次に示します。
VideoClipEntity は、YouTube 動画などのユーザー作成クリップを表します。
val videoClipEntity = VideoClipEntity.Builder()
.setPlayBackUri(Uri.parse("https://www.example.com/uri_for_current_platform"))
.setWatchNextType(WatchNextType.TYPE_CONTINUE)
.setName("Video clip name")
.addPlatformSpecificPlaybackUris(platformSpecificPlaybackUris)
.addPosterImages(images)
// Timestamp in millis for sample last engagement time 12/1/2023 00:00:00
.setLastEngagementTimeMillis(1701388800000)
.setDurationMillis(600000) //10 minutes in milliseconds
.setLastPlayBackPositionTimeMillis(300000) //5 minutes in milliseconds
.setCallToActionText("Resume")
.addTag("Vlog")
.build()
必要に応じて、作成者、作成者の画像、作成日時(ミリ秒単位)、利用可能な期間を設定できます。
LiveStreamingVideoEntity
以下に、すべての必須フィールドを含む LiveStreamingVideoEntity を作成する例を示します。
val liveStreamingVideoEntity = LiveStreamingVideoEntity.Builder()
.setPlayBackUri(Uri.parse("https://www.example.com/uri_for_current_platform"))
.setWatchNextType(WatchNextType.TYPE_CONTINUE)
.setName("Live streaming name")
.addPlatformSpecificPlaybackUris(platformSpecificPlaybackUris)
.addPosterImages(images)
// Timestamp in millis for sample last engagement time 12/1/2023 00:00:00
.setLastEngagementTimeMillis(1701388800000)
.setLastPlayBackPositionTimeMillis(36000000) //1 hour in milliseconds
.addContentRating(contentRating)
.setCallToActionText("Resume")
.addTag("Live")
.build()
必要に応じて、ライブ ストリーミング エンティティの開始時間、ブロードキャスター、ブロードキャスター アイコン、利用可能な時間枠を設定できます。
属性と要件の詳細については、API リファレンスをご覧ください。
継続クラスタのデータを提供する
AppEngagePublishClient は、連続性クラスタの公開を行います。
publishContinuationCluster メソッドを使用して ContinuationCluster オブジェクトを公開します。
スタートガイドの説明に沿って、クライアントを初期化し、サービスの可用性を確認してください。
client.publishContinuationCluster(
PublishContinuationClusterRequest
.Builder()
.setContinuationCluster(
ContinuationCluster.Builder()
.setAccountProfile(accountProfile)
.addEntity(movieEntity1)
.addEntity(movieEntity2)
.addEntity(tvEpisodeEntity1)
.addEntity(tvEpisodeEntity2)
.setSyncAcrossDevices(true)
.build()
)
.build()
)
サービスがリクエストを受信すると、1 つのトランザクション内で次のアクションが行われます。
- デベロッパー パートナーが提供した既存の
ContinuationClusterデータが削除されます。 - リクエストのデータが解析されて、更新された
ContinuationClusterに保存されます。
エラーが発生した場合は、リクエスト全体が拒否され、それまでの状態が維持されます。
publish API は既存のコンテンツを置き換える upsert API です。継続クラスタ内の特定のエンティティを更新する必要がある場合は、すべてのエンティティを再度公開する必要があります。
継続クラスタデータは、成人アカウントにのみ提供する必要があります。アカウント プロフィールが成人のものである場合にのみ公開します。
クロスデバイスの同期
setSyncAcrossDevices は、ユーザーの ContinuationCluster データをテレビ、スマートフォン、タブレットなどのデバイス間で同期するかどうかを制御します。クロスデバイス同期はデフォルトで無効になっています。
値:
true: 継続クラスタデータは、シームレスな視聴エクスペリエンスを実現するために、ユーザーのすべてのデバイスで共有されます。クロスデバイス エクスペリエンスを最適化するため、このオプションを使用することを強くおすすめします。false: 継続クラスタのデータは現在のデバイスに制限されます。
また、デバイス間でコンテンツを同期するには、アカウント ID を含む AccountProfile を指定する必要があります。アカウント プロファイルを作成するをご覧ください。
同意を得る
メディア アプリケーションは、クロスデバイス同期を有効または無効にする明確な設定を提供する必要があります。ユーザーにメリットを説明し、ユーザーの設定を一度保存して、それに応じて publishContinuationCluster に適用します。
// Example to allow cross device syncing.
client.publishContinuationCluster(
PublishContinuationClusterRequest
.Builder()
.setContinuationCluster(
ContinuationCluster.Builder()
.setAccountProfile(accountProfile)
.setSyncAcrossDevices(true)
.build()
)
.build()
)
クロスデバイス機能を最大限に活用するには、アプリがユーザーの同意を得ていることを確認し、SyncAcrossDevices から true を有効にします。これにより、コンテンツをデバイス間でシームレスに同期できるため、ユーザー エクスペリエンスが向上し、エンゲージメントが高まります。たとえば、この機能を実装したパートナーは、コンテンツが複数のデバイスに表示されるようになったため、「続きを見る」のクリック数が 40% 増加しました。
Engage データを削除する
標準の 60 日間の保持期間が経過する前に、Google TV サーバーからユーザーのデータを手動で削除するには、deleteClusters メソッドを使用します。リクエストを受信すると、サービスはアカウント プロファイルまたはアカウント全体の既存の Engage データをすべて削除します。
DeleteReason 列挙型は、データ削除の理由を定義します。次のコードは、ログアウト時に「続きを見る」データを削除します。
// If the user logs out from your media app, you must make the following call
// to remove continue watching data from the current google TV device,
// otherwise, the continue watching data will persist on the current
// google TV device until 60 days later.
client.deleteClusters(
DeleteClustersRequest.Builder()
.setAccountProfile(accountProfile)
.setDeleteReason(DeleteReason.DELETE_REASON_USER_LOG_OUT)
.setSyncAcrossDevices(true)
.build()
)
テスト
検証用アプリを使用して、Engage SDK の統合が正しく機能していることを確認します。
publish API を呼び出したら、検証アプリをチェックして、データが正しく公開されていることを確認します。継続クラスタは、アプリのインターフェース内で個別の行として表示されます。
- アプリで次のアクションをテストします。
- ログインします。
- プロフィールを切り替えます(該当する場合)。
- 動画を開始してから一時停止するか、ホームページに戻ります。
- 動画の再生中にアプリを閉じます。
- [続きを見る] 行からアイテムを削除する(サポートされている場合)。
- 各アクションの後、アプリが
publishContinuationClustersAPI を呼び出し、検証アプリにデータが正しく表示されていることを確認します。 検証アプリでは、正しく実装されたエンティティに緑色の「All Good」チェックマークが表示されます。
図 1. 確認アプリの成功 検証アプリは、問題のあるエンティティを報告します。
図 2. 確認アプリのエラー エラーのあるエンティティのトラブルシューティングを行うには、テレビのリモコンを使用して、検証アプリでエンティティを選択してクリックします。特定の問題が表示され、赤色でハイライト表示されます(以下の例を参照)。
図 3. 確認アプリのエラーの詳細