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

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

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

事前作業

始める前に、次の手順を完了します。1. この統合では、アプリが API レベル 19 以降を対象にしていることを確認してください。

  1. アプリに com.google.android.engage ライブラリを追加します。

    統合で使用する SDK は、モバイルアプリ用とテレビアプリ用の 2 つに分かれています。

    モバイルの場合

    
      dependencies {
        implementation 'com.google.android.engage:engage-core:1.5.9
      }
    

    テレビ

    
      dependencies {
        implementation 'com.google.android.engage:engage-tv:1.0.5
      }
    
  2. AndroidManifest.xml ファイルで Engage サービスの環境を本番環境に設定します。

    モバイル APK の場合

    
    <meta-data
          android:name="com.google.android.engage.service.ENV"
          android:value="PRODUCTION">
    </meta-data>
    

    テレビ用 APK

    
    <meta-data
        android:name="com.google.android.engage.service.ENV"
        android:value="PRODUCTION">
    </meta-data>
    
  3. フォアグラウンド サービスで公開を実行します。

  4. 次のいずれかの条件を満たす場合に、1 日に 1 回まで推奨事項データを公開します。

    1. ユーザーがその日に初めてログインした時間。(または
    2. ユーザーがアプリの操作を開始したとき。

統合

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

isServiceAvailable()2 を使用して、サービスを統合できるかどうかを確認します。

val client = AppEngagePublishClient(context)

client.isServiceAvailable().addOnCompleteListener { task ->
  if (task.isSuccessful) {
  // Handle IPC call success
    if(task.result) {
      // Service is available on the device, proceed with content publish
      // calls.
      client.publishRecommendationClusters(recommendationRequest)
    } else {
      // Service is not available
    }
  } else {
    // The IPC call itself fails, proceed with error handling logic here,
    // such as retry.
  }
}

おすすめコンテンツ クラスタと公開リクエスト

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

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

アカウント プロファイルを作成する

Google TV でパーソナライズされたエクスペリエンスを利用するには、アカウントとプロファイルの情報を提供します。AccountProfile を使用して、次の情報を指定します。

  1. アカウント ID: アプリケーション内のユーザーのアカウントを表す一意の識別子。実際のアカウント ID または適切に難読化されたバージョンを指定できます。
  2. プロフィール ID(省略可): アプリケーションが 1 つのアカウント内で複数のプロフィールをサポートしている場合は、特定のユーザー プロフィールの固有の識別子を指定します。
  3. ロケール(省略可): ユーザーの優先言語を指定できます。このフィールドは、RecommendationRequestMediaActionFeedEntity を送信する場合に便利です。
// If app only supports account
val accountProfile = AccountProfile.Builder()
  .setAccountId("account_id")
  .build();

// If app supports both account and profile
val accountProfile = AccountProfile.Builder()
  .setAccountId("account_id")
  .setProfileId("profile_id")
  .build();

// set Locale
val accountProfile = AccountProfile.Builder()
  .setAccountId("account_id")
  .setProfileId("profile_id")
  .setLocale("en-US")
  .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 を含む MediaActionFeed エンティティを作成できます。この ID は一意である必要があり、メディア アクション フィードの ID と一致している必要があります。これは、取り込まれたフィード コンテンツを識別し、メディア コンテンツのルックアップを実行するのに役立ちます。

val id = "dataFeedEleemntId"

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")
  .setChanelId("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 Desccription")
  .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()

これらの手順を実装することで、デベロッパーは動画コンテンツのレコメンデーションを Google TV に統合し、ユーザーのコンテンツ発見とエンゲージメントを促進し、すべてのデバイスで一貫性のあるパーソナライズされた視聴体験をユーザーに提供できます。