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

このガイドでは、デベロッパーが 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 に設定する必要があります。

メディア アプリケーションでは、クロスデバイスの同期を有効または無効にするための明確な設定を提供する必要があります。ユーザーにメリットを説明し、ユーザーの設定を 1 回保存して、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 では、各商品アイテム タイプを表すさまざまなエンティティを定義しています。おすすめコンテンツ クラスタでは、次のエンティティがサポートされています。

  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 とピクセル寸法(高さと幅)が必要です。複数のポスター画像を指定してさまざまなフォームファクタをターゲットにしますが、特に Google のエンターテイメント スペース内で「おすすめコンテンツ」エンティティが正しく表示されるように、すべての画像のアスペクト比が 16:9 で、高さが 200 ピクセル以上であることを確認してください。高さが 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 に統合している場合は、 映画やテレビ番組のエンティティを個別に作成する必要はありません。代わりに、 MediaActionFeedEntity を作成できます。これには、 必要なフィールド DataFeedElementId が含まれます。この 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)
  .setCallToActionText("Watch Now")
  .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);
//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)
  .setCallToActionText("Watch Now")
  .addTag("Drama")
  .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)
  .setCallToActionText("Watch Now")
  .addTag("Action")
  .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)
  .setCallToActionText("Watch Now")
  .addTag("News")
  .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)
  .setCallToActionText("Watch Now")
  .addTag("Sports")
  .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()