動画のおすすめに Engage SDK を使用する

book_path: /distribute/other-docs/_book.yaml project_path: /distribute/other-docs/_project.yaml

このガイドでは、Engage SDK を使用しておすすめの動画コンテンツを統合し、テレビ、モバイル、タブレットなどの Google サーフェス全体でおすすめのコンテンツを表示する手順を説明します。

おすすめコンテンツでは、おすすめコンテンツ クラスタを活用して、複数のアプリの映画やテレビ番組を 1 つの UI グループに表示します。各デベロッパー パートナーは、各レコメンデーション クラスタ内で最大 25 個のエンティティをブロードキャストできます。リクエストごとに最大 7 個のレコメンデーション クラスタを設定できます。

事前作業

スタートガイドの事前準備の手順を完了していること。

  1. フォアグラウンド サービスで公開を実行します。
  2. 推奨事項データは、次のいずれかの条件を満たす場合に、1 日に 1 回まで公開します。
    • ユーザーがその日に初めてログインした時間。(または
    • ユーザーがアプリケーションの操作を開始したとき。

統合

AppEngagePublishClient はおすすめコンテンツ クラスタを公開します。publishRecommendationClusters メソッドを使用して、推奨事項オブジェクトを公開します。

スタートガイドの説明に沿って、クライアントを初期化し、サービスの可用性を確認してください。

client.publishRecommendationClusters(recommendationRequest)

おすすめコンテンツ クラスタの upsert

クラスタはエンティティの論理グループです。次のコード例では、ユーザーの好みに基づいてクラスタを構築する方法、公開リクエストを作成してすべてのクラスタを upsert する方法について説明します。

RecommendationClusterType は、クラスタの表示方法を決定します。

// cluster for popular movies
val recommendationCluster1 = RecommendationCluster
  .Builder()
  .addEntity(movie1)
  .addEntity(movie2)
  .addEntity(movie3)
  .addEntity(movie4)
  .addEntity(tvShow)
  // This cluster is meant to be used as an individual provider row
  .setRecommendationClusterType(TYPE_PROVIDER_ROW)
  .setTitle("Popular Movies")
  .build()

// cluster for live TV programs
val recommendationCluster2 = RecommendationCluster
  .Builder()
  .addEntity(liveTvProgramEntity1)
  .addEntity(liveTvProgramEntity2)
  .addEntity(liveTvProgramEntity3)
  .addEntity(liveTvProgramEntity4)
  .addEntity(liveTvProgramEntity5)
 // This cluster is meant to be used as an individual provider row
  .setRecommendationClusterType(TYPE_PROVIDER_ROW)
  .setTitle("Popular Live TV Programs")
  .build()

// creating a publishing request
val recommendationRequest = PublishRecommendationClustersRequest
  .Builder()
  .setSyncAcrossDevices(true)
  .setAccountProfile(accountProfile)
  .addRecommendationCluster(recommendationCluster1)
  .addRecommendationCluster(recommendationCluster2)
  .build()

サービスがリクエストを受信すると、1 つのトランザクション内で次のアクションが行われます。

  • デベロッパー パートナーが提供した既存の RecommendationsCluster データが削除されます。
  • リクエストのデータが解析されて、更新された RecommendationsCluster に保存されます。エラーが発生した場合は、リクエスト全体が拒否され、それまでの状態が維持されます。

クロスデバイスの同期

SyncAcrossDevices フラグは、ユーザーのおすすめクラスタ データが Google TV と共有され、テレビ、スマートフォン、タブレットなどのデバイスで利用可能になるかどうかを制御します。推奨事項を有効にするには、true に設定する必要があります。

メディア アプリは、デバイス間の同期を有効または無効にするための明確な設定を提供する必要があります。ユーザーにメリットを説明し、ユーザーの選択を一度保存して、それに応じて publishRecommendations リクエストに適用します。クロスデバイス機能を最大限に活用するには、アプリがユーザーの同意を取得し、SyncAcrossDevicestrue に設定していることを確認します。

動画の検出データを削除する

標準の 60 日間の保持期間より前に Google TV サーバーからユーザーのデータを手動で削除するには、client.deleteClusters() メソッドを使用します。リクエストを受け取ると、サービスはアカウント プロファイルまたはアカウント全体の既存の動画検出データをすべて削除します。

DeleteReason 列挙型は、データ削除の理由を定義します。次のコードは、ログアウト時にレコメンデーションを削除します。

// If the user logs out from your media app, you must make the following call
// to remove recommendations data from the current Google TV device, otherwise,
// the recommendations data persists on the current Google TV device until 60
// days later.
client.deleteClusters(
  new DeleteClustersRequest.Builder()
    .setAccountProfile(AccountProfile())
    .setReason(DeleteReason.DELETE_REASON_USER_LOG_OUT)
    .build()
)

// If the user revokes the consent to share data with Google TV, you must make
// the following call to remove recommendations data from all current Google TV
// devices. Otherwise, the recommendations data persists until 60 days later.
client.deleteClusters(
  new DeleteClustersRequest.Builder()
    .setAccountProfile(AccountProfile())
    .setReason(DeleteReason.DELETE_REASON_LOSS_OF_CONSENT)
    .build()
)

エンティティを作成する

この SDK では、各アイテムタイプを表すさまざまなエンティティを定義しています。Recommendation クラスタでは、次のエンティティがサポートされています。

  1. MediaActionFeedEntity
  2. MovieEntity
  3. TvShowEntity
  4. LiveTvChannelEntity
  5. LiveTvProgramEntity

説明を提供する

各エンティティの簡単な説明を入力します。この説明は、ユーザーがエンティティにカーソルを合わせたときに表示され、追加の詳細情報が提供されます。

プラットフォーム固有の再生 URI

サポートされている各プラットフォーム(Android TV、Android、iOS)の再生 URI を作成します。これにより、システムは各プラットフォームで動画を再生するための適切な URI を選択できます。

すべてのプラットフォームで再生 URI が同一であるまれなケースでは、プラットフォームごとに繰り返します。

// Required. Set this when you want recommended 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()

// Optional. Set this when you want recommended entities to show up on
// Google TV Android app
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 recommended 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)

// Provide appropriate rating for the system.
val contentRating = new RatingSystem
  .Builder()
  .setAgencyName("MPAA")
  .setRating("PG-13")
  .build()

ポスター画像

ポスター画像には、URI とピクセル サイズ(高さと幅)が必要です。複数のポスター画像を提供してさまざまなフォーム ファクタをターゲットに設定しますが、すべての画像が 16:9 のアスペクト比と 200 ピクセルの最小の高さを維持していることを確認して、特に Google のエンターテイメント スペース内で「おすすめ」エンティティが正しく表示されるようにします。高さが 200 ピクセル未満の画像は表示されないことがあります。

Image image1 = new Image.Builder()
  .setImageUri(Uri.parse("http://www.example.com/entity_image1.png");)
  .setImageHeightInPixel(300)
  .setImageWidthInPixel(169)
  .build()

Image image2 = new Image.Builder()
  .setImageUri(Uri.parse("http://www.example.com/entity_image2.png");)
  .setImageHeightInPixel(640)
  .setImageWidthInPixel(360)
  .build()

// And other images for different form factors.
val images = Arrays.asList(image1, image2)

推奨される理由

必要に応じて、Google TV が特定の映画やテレビ番組をユーザーにすすめる理由を構築するために使用できるレコメンデーションの理由を指定します。

//Allows us to construct reason: "Because it is top 10 on your Channel"
val topOnPartner = RecommendationReasonTopOnPartner
  .Builder()
  .setNum(10) //any valid integer value
  .build()

//Allows us to construct reason: "Because it is popular on your Channel"
val popularOnPartner = RecommendationReasonPopularOnPartner
  .Builder()
  .build()

//Allows us to construct reason: "New to your channel, or Just added"
val newOnPartner = RecommendationReasonNewOnPartner
  .Builder()
  .build()

//Allows us to construct reason: "Because you watched Star Wars"
val watchedSimilarTitles = RecommendationReasonWatchedSimilarTitles
  .addSimilarWatchedTitleName("Movie or TV Show Title")
  .addSimilarWatchedTitleName("Movie or TV Show Title")
  .Builder()
  .build()

//Allows us to construct reason: "Recommended for you by ChannelName"
val recommendedForUser = RecommendationReasonRecommendedForUser
  .Builder()
  .build()

val watchAgain = RecommendationReasonWatchAgain
  .Builder()
  .build()

val fromUserWatchList = RecommendationReasonFromUserWatchlist
  .Builder()
  .build()

val userLikedOnPartner = RecommendationReasonUserLikedOnPartner
  .Builder()
  .setTitleName("Movie or TV Show Title")
  .build()

val generic = RecommendationReasonGeneric.Builder().build()

表示期間

エンティティを期間限定で利用可能にする場合は、カスタムの有効期限を設定します。有効期限を明示的に指定しない場合、エンティティは 60 日後に自動的に期限切れになり、削除されます。そのため、エンティティを早めに期限切れにする必要がある場合にのみ、有効期限を設定します。このような利用可能な時間帯を複数指定します。

val window1 = DisplayTimeWindow
  .Builder()
  .setStartTimeStampMillis(now()+ 1.days.toMillis())
  .setEndTimeStampMillis(now()+ 30.days.toMillis())

val window2 = DisplayTimeWindow
  .Builder()
  .setEndTimeStampMillis(now()+ 30.days.toMillis())

val availabilityTimeWindows: List<DisplayTimeWindow> = listof(window1,window2)

DataFeedElementId

メディア カタログまたはメディア アクション フィードを Google TV と統合している場合は、映画やテレビ番組用に個別のエンティティを作成する必要はありません。代わりに、必須フィールド DataFeedElementId を含む MediaActionFeedEntity を作成できます。この ID は一意である必要があり、メディア アクション フィードの ID と一致している必要があります。これは、取り込まれたフィード コンテンツを識別し、メディア コンテンツのルックアップを実行するのに役立ちます。

val id = "dataFeedElementId"

MovieEntity

次に、すべての必須フィールドを含む MovieEntity を作成する例を示します。


val movieEntity = MovieEntity.Builder()
  .setName("Movie name")
  .setDescription("A sentence describing movie.")
  .addPlatformSpecificPlaybackUri(platformSpecificPlaybackUris)
  .addPosterImages(images)
  // Suppose the duration is 2 hours, it is 72000000 in milliseconds
  .setDurationMills(72000000)
  .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);
//Suppose release date is 11-02-2025
val releaseDate  = 1739233800000L
val movieEntity = MovieEntity.Builder()
  ...
  .addGenres(genres)
  .setReleaseDateEpochMillis(releaseDate)
  .addContentRatings(contentRatings)
  .setRecommendationReason(topOnPartner or watchedSimilarTitles)
  .addAllAvailabilityTimeWindows(availabilityTimeWindows)
  .build()

TvShowEntity

次に、すべての必須フィールドを含む TvShowEntity を作成する例を示します。

val tvShowEntity = TvShowEntity.Builder()
  .setName("Show title")
  .setDescription("A sentence describing TV Show.")
  .addPlatformSpecificPlaybackUri(platformSpecificPlaybackUris)
  .addPosterImages(images)
  .build();

ジャンル、コンテンツのレーティング、おすすめの理由、特典の価格、シーズンの数、利用可能な期間などの追加データを任意で提供します。これらのデータは、Google TV での表示の強化やフィルタリングの目的で使用される場合があります。

val genres = Arrays.asList("Action", "Science fiction");
val rating1 = RatingSystem.Builder()
  .setAgencyName("MPAA")
  .setRating("pg-13")
  .build();
val price = Price.Builder()
  .setCurrentPrice("$14.99")
  .setStrikethroughPrice("$16.99")
  .build();
val contentRatings = Arrays.asList(rating1);
val seasonCount = 5;
val tvShowEntity = TvShowEntity.Builder()
  ...
  .addGenres(genres)
  .addContentRatings(contentRatings)
  .setRecommendationReason(topOnPartner or watchedSimilarTitles)
  .addAllAvailabilityTimeWindows(availabilityTimeWindows)
  .setSeasonCount(seasonCount)
  .setPrice(price)
  .build()

MediaActionFeedEntity

次に、すべての必須フィールドを含む MediaActionFeedEntity を作成する例を示します。


val mediaActionFeedEntity = MediaActionFeedEntity.Builder()
  .setDataFeedElementId(id)
  .build()

必要に応じて、説明、推奨理由、表示期間などの追加データを提供します。これらのデータは、Google TV で表示の強化やフィルタリングの目的で使用されることがあります。

val mediaActionFeedEntity = MediaActionFeedEntity.Builder()
  .setName("Movie name or TV Show name")
  .setDescription("A sentence describing an entity")
  .setRecommendationReason(topOnPartner or watchedSimilarTitles)
  .addPosterImages(images)
  .build()

LiveTvChannelEntity

これはライブテレビ チャンネルを表します。次に、すべての必須フィールドを含む LiveTvChannelEntity を作成する例を示します。

val liveTvChannelEntity = LiveTvChannelEntity.Builder()
  .setName("Channel Name")
  // ID of the live TV channel
  .setEntityId("https://www.example.com/channel/12345")
  .setDescription("A sentence describing this live TV channel.")
  // channel playback uri must contain at least PlatformType.TYPE_ANDROID_TV
  .addPlatformSpecificPlaybackUri(channelPlaybackUris)
  .addLogoImage(logoImage)
  .build()

必要に応じて、コンテンツのレーティングやおすすめの理由などの追加データを提供します。

val rating1 = RatingSystem.Builder()
  .setAgencyName("MPAA")
  .setRating("pg-13")
  .build()
val contentRatings = Arrays.asList(rating1)

val liveTvChannelEntity = LiveTvChannelEntity.Builder()
  ...
  .addContentRatings(contentRatings)
  .setRecommendationReason(topOnPartner)
  .build()

LiveTvProgramEntity

これは、ライブテレビ チャンネルで放送中または放送予定のライブテレビ番組カードを表します。次に、すべての必須フィールドを含む LiveTvProgramEntity を作成する例を示します。

val liveTvProgramEntity = LiveTvProgramEntity.Builder()
  // First set the channel information
  .setChannelName("Channel Name")
  .setChannelId("https://www.example.com/channel/12345")
  // channel playback uri must contain at least PlatformType.TYPE_ANDROID_TV
  .addPlatformSpecificPlaybackUri(channelPlaybackUris)
  .setChannelLogoImage(channelLogoImage)
  // Then set the program or card specific information.
  .setName("Program Name")
  .setEntityId("https://www.example.com/schedule/123")
  .setDescription("Program Description")
  .addAvailabilityTimeWindow(
      DisplayTimeWindow.Builder()
        .setStartTimestampMillis(1756713600000L)// 2025-09-01T07:30:00+0000
        .setEndTimestampMillis(1756715400000L))// 2025-09-01T08:00:00+0000
  .addPosterImage(programImage)
  .build()

必要に応じて、コンテンツのレーティング、ジャンル、おすすめの理由などの追加データを提供します。

val rating1 = RatingSystem.Builder()
  .setAgencyName("MPAA")
  .setRating("pg-13")
  .build()
val contentRatings = Arrays.asList(rating1)
val genres = Arrays.asList("Action", "Science fiction")

val liveTvProgramEntity = LiveTvProgramEntity.Builder()
  ...
  .addContentRatings(contentRatings)
  .addGenres(genres)
  .setRecommendationReason(topOnPartner)
  .build()