Engage SDK Watch: サードパーティの技術的統合手順

Google が構築しているオンデバイス サーフェスでは、ユーザーのアプリがカテゴリ別に整理され、パーソナライズされたアプリ コンテンツの使用や発見における没入感のある新しいエクスペリエンスが提供されます。デベロッパー パートナーは、この全画面エクスペリエンスを活用することで、アプリ外の専用チャネルで良質なリッチ コンテンツをアピールできます。

このガイドでは、Engage SDK を使用して動画コンテンツを統合し、この新しいサーフェス領域と既存の Google サーフェスの両方にコンテンツを表示する手順を説明します。

統合の詳細

用語

この統合には、おすすめコンテンツ連続性注目コンテンツの 3 種類のクラスタがあります。

  • おすすめコンテンツ クラスタには、個々のデベロッパー パートナーが提供する動画コンテンツについて、パーソナライズされたおすすめ情報が表示されます。

    おすすめコンテンツの構成は次のとおりです。

    • おすすめコンテンツ クラスタ: 同一のデベロッパー パートナーが提供するおすすめコンテンツのグループが表示される UI ビュー。

      図 1. 単一のパートナーが提供するおすすめコンテンツ クラスタが表示されているエンターテイメント スペースの UI。
    • エンティティ: クラスタ内の単一のアイテムを表すオブジェクト。エンティティには、映画、テレビ番組、テレビシリーズ、ライブ動画などがあります。サポートされているエンティティ タイプの一覧については、「エンティティ データを提供する」セクションをご覧ください。

      図 2. 単一のパートナーのおすすめコンテンツ クラスタ内のエンティティが 1 つ表示されているエンターテイメント スペースの UI。
  • 連続性クラスタでは、複数のデベロッパー パートナーが提供する未視聴の動画と新しくリリースされたエピソードが、1 つの UI グループに表示されます。各デベロッパー パートナーは、連続性クラスタ内で最大 10 個のエンティティをブロードキャストできます。調査から、パーソナライズされたおすすめコンテンツとパーソナライズされた連続性コンテンツを合わせて表示することで、最適なユーザー エンゲージメントが生み出されることがわかっています。

    図 3. 複数のパートナーが提供する未閲覧のおすすめコンテンツを含む連続性クラスタが表示されているエンターテイメント スペースの UI(現時点ではおすすめコンテンツが 1 つのみ表示されます)。
  • 注目コンテンツ クラスタでは、複数のデベロッパー パートナーが提供するエンティティのセレクションが 1 つの UI グループに表示されます。1 つの注目クラスタが UI の上部付近に、どのおすすめコンテンツ クラスタよりも優先されて表示されます。各デベロッパー パートナーは、注目コンテンツ クラスタ内で最大 10 個のエンティティをブロードキャストできます。

    図 4. 複数のパートナーが提供するおすすめコンテンツを含む注目コンテンツ クラスタが表示されているエンターテインメント スペースの UI(現時点ではおすすめコンテンツが 1 つのみ表示されます)。

事前作業

最小 API レベル: 19

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

dependencies {
    // Make sure you also include that repository in your project's build.gradle file.
    implementation 'com.google.android.engage:engage-core:1.4.0'
}

詳しくは、Android 11 のパッケージの公開設定をご覧ください。

まとめ

この設計は、バインドされたサービスの実装に基づいています。

クライアントが公開できるデータには、各種クラスタに関する次の上限が適用されます。

クラスタタイプ クラスタ数の上限 クラスタ内のエンティティ数の上限
おすすめコンテンツ クラスタ 最大 5 個 最大 50 個
継続クラスタ 最大 1 個 最大 10 個
注目コンテンツ クラスタ 最大 1 個 最大 10 個

ステップ 0: 既存の Media Home SDK の統合からの移行

既存の統合のデータモデルの対応表

既存の Media Home 統合から移行する場合は、次の表を参照してください。既存の SDK と新しい Engage SDK のデータモデルがどのように対応しているかをまとめています。

MediaHomeVideoContract の統合でのデータモデル Engage SDK の統合でのデータモデル
com.google.android.mediahome.video.PreviewChannel com.google.android.engage.common.datamodel.RecommendationCluster
com.google.android.mediahome.video.PreviewChannel.Builder com.google.android.engage.common.datamodel.RecommendationCluster.Builder
com.google.android.mediahome.video.PreviewChannelHelper com.google.android.engage.video.service.AppEngageVideoClient
com.google.android.mediahome.video.PreviewProgram クラス EventVideoLiveStreamingVideoMovieTvEpisodeTvSeasonTvShowVideoClipEntity に分割されています。
com.google.android.mediahome.video.PreviewProgram.Builder 別々のクラスのビルダー EventVideoLiveStreamingVideoMovieTvEpisodeTvSeasonTvShowVideoClipEntity に分割されています。
com.google.android.mediahome.video.VideoContract 不要になりました。
com.google.android.mediahome.video.WatchNextProgram 別々のクラスの属性 EventVideoEntityLiveStreamingVideoEntityMovieEntityTvEpisodeEntityTvSeasonEntityTvShowEntityVideoClipEntity に分割されています。
com.google.android.mediahome.video.WatchNextProgram.Builder 別々のクラスの属性 EventVideoEntityLiveStreamingVideoEntityMovieEntityTvEpisodeEntityTvSeasonEntityTvShowEntityVideoClipEntity に分割されています。

Media Home SDK と Engage SDK のクラスタ公開の違い

Media Home SDK では、クラスタとエンティティが別々の API で公開されていました。

// 1. Fetch existing channels
List<PreviewChannel> channels = PreviewChannelHelper.getAllChannels();

// 2. If there are no channels, publish new channels
long channelId = PreviewChannelHelper.publishChannel(builder.build());

// 3. If there are existing channels, decide whether to update channel contents
PreviewChannelHelper.updatePreviewChannel(channelId, builder.build());

// 4. Delete all programs in the channel
PreviewChannelHelper.deleteAllPreviewProgramsByChannelId(channelId);

// 5. publish new programs in the channel
PreviewChannelHelper.publishPreviewProgram(builder.build());

Engage SDK では、クラスタとエンティティの公開が 1 つの API 呼び出しに統合されます。1 つのクラスタに属するエンティティは、すべてそのクラスタとともに公開されます。

Kotlin


RecommendationCluster.Builder()
            .addEntity(MOVIE_ENTITY)
            .addEntity(MOVIE_ENTITY)
            .addEntity(MOVIE_ENTITY)
            .setTitle("Top Picks For You")
            .build()

Java


new RecommendationCluster.Builder()
                        .addEntity(MOVIE_ENTITY)
                        .addEntity(MOVIE_ENTITY)
                        .addEntity(MOVIE_ENTITY)
                        .setTitle("Top Picks For You")
                        .build();

ステップ 1: エンティティ データを提供する

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

  1. MovieEntity
  2. TvShowEntity
  3. TvSeasonEntity
  4. TvEpisodeEntity
  5. LiveStreamingVideoEntity
  6. VideoClipEntity

次の表は、各タイプの属性と要件の概要を示しています。

MovieEntity

属性 必須 / 任意 備考
名前 必須
ポスター画像 必須 少なくとも 1 つの画像が必要です。アスペクト比も指定する必要があります(横向きが推奨されますが、状況に応じて縦向きと横向きの両方の画像を渡すことをおすすめします)。

詳しくは、画像の仕様をご覧ください。

再生 URI 必須

映画を再生できる提供元のアプリへのディープリンク。

注: アトリビューションにはディープリンクを使用できます。よくある質問をご覧ください

情報ページ URI 任意

映画の詳細を確認できる提供元のアプリへのディープリンク。

注: アトリビューションにはディープリンクを使用できます。よくある質問をご覧ください

リリース日 必須 エポックミリ秒単位。
対象 必須

AVAILABLE: 追加操作の必要なしでユーザーが利用できるコンテンツ。

FREE_WITH_SUBSCRIPTION: サブスクリプションを購入したユーザーが利用できるコンテンツ。

PAID_CONTENT: 利用するにはユーザーが購入するかレンタルする必要があるコンテンツ。

PURCHASED: ユーザーが購入またはレンタルしたコンテンツ。

特典の価格 任意 自由形式のテキスト
所要時間 必須 ミリ秒単位。
ジャンル 必須 自由形式のテキスト
コンテンツのレーティング 必須 自由形式のテキストです。業界基準に即している必要があります()。
次のおすすめのタイプ 条件付きで必須

アイテムが連続性クラスタ内にある場合は指定する必要があります。また、次の 4 つのタイプのいずれかにする必要があります。

CONTINUE: ユーザーがすでに 1 分以上コンテンツを視聴している。

NEW: エピソード形式のコンテンツで、ユーザーが利用できるエピソードをすべて視聴している中で、新しいエピソードがリリースされ、未視聴のエピソードが 1 つある(テレビ番組のシリーズや、一連のサッカーの試合など)。

NEXT: ユーザーがエピソード形式のコンテンツのエピソードを視聴しているものの、未視聴のエピソードが 1 つまたは複数残っており、最後のエピソードが「NEW」ではなく、ユーザーがそのエピソード形式のコンテンツを視聴し始める前にリリースされている。

WATCHLIST: ユーザーが動画やイベント、シリーズをウォッチリストに明示的に追加し、次に視聴したいもののリストを手動で作成している。

前回のエンゲージメント時間 条件付きで必須 アイテムが連続性クラスタ内にある場合は指定する必要があります。エポックミリ秒単位。
前回の再生位置の時間 条件付きで必須 アイテムが連続性クラスタ内にあり、WatchNextType が CONTINUE の場合は指定する必要があります。エポックミリ秒単位。

TvShowEntity

属性 必須 / 任意 備考
名前 必須
ポスター画像 必須 少なくとも 1 つの画像が必要です。アスペクト比も指定する必要があります(横向きが推奨されますが、状況に応じて縦向きと横向きの両方の画像を渡すことをおすすめします)。

詳しくは、画像の仕様をご覧ください。

情報ページ URI 必須

テレビ番組の詳細を確認できる提供元のアプリへのディープリンク。

注: アトリビューションにはディープリンクを使用できます。よくある質問をご覧ください

再生 URI 任意

テレビ番組を再生できる提供元のアプリへのディープリンク。

注: アトリビューションにはディープリンクを使用できます。よくある質問をご覧ください

最初のエピソードの放送日 必須 エポックミリ秒単位。
最新エピソードの放送日 任意 エポックミリ秒単位。
対象 必須

AVAILABLE: 追加操作の必要なしでユーザーが利用できるコンテンツ。

FREE_WITH_SUBSCRIPTION: サブスクリプションを購入したユーザーが利用できるコンテンツ。

PAID_CONTENT: 利用するにはユーザーが購入するかレンタルする必要があるコンテンツ。

PURCHASED: ユーザーが購入またはレンタルしたコンテンツ。

特典の価格 任意 自由形式のテキスト
シーズンの数 必須 正の整数
ジャンル 必須 自由形式のテキスト
コンテンツのレーティング 必須 自由形式のテキストです。業界基準に即している必要があります()。
次のおすすめのタイプ 条件付きで必須

アイテムが連続性クラスタ内にある場合は指定する必要があります。また、次の 4 つのタイプのいずれかにする必要があります。

CONTINUE: ユーザーがすでに 1 分以上コンテンツを視聴している。

NEW: エピソード形式のコンテンツで、ユーザーが利用できるエピソードをすべて視聴している中で、新しいエピソードがリリースされ、未視聴のエピソードが 1 つある(テレビ番組のシリーズや、一連のサッカーの試合など)。

NEXT: ユーザーがエピソード形式のコンテンツのエピソードを視聴しているものの、未視聴のエピソードが 1 つまたは複数残っており、最後のエピソードが「NEW」ではなく、ユーザーがそのエピソード形式のコンテンツを視聴し始める前にリリースされている。

WATCHLIST: ユーザーが動画やイベント、シリーズをウォッチリストに明示的に追加し、次に視聴したいもののリストを手動で作成している。

前回のエンゲージメント時間 条件付きで必須 アイテムが連続性クラスタ内にある場合は指定する必要があります。エポックミリ秒単位。
前回の再生位置の時間 条件付きで必須 アイテムが連続性クラスタ内にあり、WatchNextType が CONTINUE の場合は指定する必要があります。エポックミリ秒単位。

TvSeasonEntity

属性 必須 / 任意 備考
名前 必須
ポスター画像 必須 少なくとも 1 つの画像が必要です。アスペクト比も指定する必要があります(横向きが推奨されますが、状況に応じて縦向きと横向きの両方の画像を渡すことをおすすめします)。

詳しくは、画像の仕様をご覧ください。

情報ページ URI 必須

テレビ番組のシーズンの詳細を確認できる提供元のアプリへのディープリンク。

注: アトリビューションにはディープリンクを使用できます。よくある質問をご覧ください

再生 URI 任意

テレビ番組のシーズンを再生できる提供元のアプリへのディープリンク。

注: アトリビューションにはディープリンクを使用できます。よくある質問をご覧ください

シーズン番号表示

任意

v1.3.1 で利用可能

文字列
最初のエピソードの放送日 必須 エポックミリ秒単位。
最新エピソードの放送日 任意 エポックミリ秒単位。
対象 必須

AVAILABLE: 追加操作の必要なしでユーザーが利用できるコンテンツ。

FREE_WITH_SUBSCRIPTION: サブスクリプションを購入したユーザーが利用できるコンテンツ。

PAID_CONTENT: 利用するにはユーザーが購入するかレンタルする必要があるコンテンツ。

PURCHASED: ユーザーが購入またはレンタルしたコンテンツ。

特典の価格 任意 自由形式のテキスト
エピソード数 必須 正の整数
ジャンル 必須 自由形式のテキスト
コンテンツのレーティング 必須 自由形式のテキストです。業界基準に即している必要があります()。
次のおすすめのタイプ 条件付きで必須

アイテムが連続性クラスタ内にある場合は指定する必要があります。また、次の 4 つのタイプのいずれかにする必要があります。

CONTINUE: ユーザーがすでに 1 分以上コンテンツを視聴している。

NEW: エピソード形式のコンテンツで、ユーザーが利用できるエピソードをすべて視聴している中で、新しいエピソードがリリースされ、未視聴のエピソードが 1 つある(テレビ番組のシリーズや、一連のサッカーの試合など)。

NEXT: ユーザーがエピソード形式のコンテンツのエピソードを視聴しているものの、未視聴のエピソードが 1 つまたは複数残っており、最後のエピソードが「NEW」ではなく、ユーザーがそのエピソード形式のコンテンツを視聴し始める前にリリースされている。

WATCHLIST: ユーザーが動画やイベント、シリーズをウォッチリストに明示的に追加し、次に視聴したいもののリストを手動で作成している。

前回のエンゲージメント時間 条件付きで必須 アイテムが連続性クラスタ内にある場合は指定する必要があります。エポックミリ秒単位。
前回の再生位置の時間 条件付きで必須 アイテムが連続性クラスタ内にあり、WatchNextType が CONTINUE の場合は指定する必要があります。エポックミリ秒単位。

TvEpisodeEntity

属性 必須 / 任意 備考
名前 必須
ポスター画像 必須 少なくとも 1 つの画像が必要です。アスペクト比も指定する必要があります(横向きが推奨されますが、状況に応じて縦向きと横向きの両方の画像を渡すことをおすすめします)。

詳しくは、画像の仕様をご覧ください。

再生 URI 必須

エピソードを再生できる提供元のアプリへのディープリンク。

注: アトリビューションにはディープリンクを使用できます。よくある質問をご覧ください

情報ページ URI 任意

テレビ番組のエピソードの詳細を確認できる提供元のアプリへのディープリンク。

注: アトリビューションにはディープリンクを使用できます。よくある質問をご覧ください

エピソード番号表示

任意

v1.3.1 で利用可能

文字列
放送日 必須 エポックミリ秒単位。
対象 必須

AVAILABLE: 追加操作の必要なしでユーザーが利用できるコンテンツ。

FREE_WITH_SUBSCRIPTION: サブスクリプションを購入したユーザーが利用できるコンテンツ。

PAID_CONTENT: 利用するにはユーザーが購入するかレンタルする必要があるコンテンツ。

PURCHASED: ユーザーが購入またはレンタルしたコンテンツ。

特典の価格 任意 自由形式のテキスト
所要時間 必須 ミリ秒単位で正の値を指定する必要があります。
ジャンル 必須 自由形式のテキスト
コンテンツのレーティング 必須 自由形式のテキストです。業界基準に即している必要があります()。
次のおすすめのタイプ 条件付きで必須

アイテムが連続性クラスタ内にある場合は指定する必要があります。また、次の 4 つのタイプのいずれかにする必要があります。

CONTINUE: ユーザーがすでに 1 分以上コンテンツを視聴している。

NEW: エピソード形式のコンテンツで、ユーザーが利用できるエピソードをすべて視聴している中で、新しいエピソードがリリースされ、未視聴のエピソードが 1 つある(テレビ番組のシリーズや、一連のサッカーの試合など)。

NEXT: ユーザーがエピソード形式のコンテンツのエピソードを視聴しているものの、未視聴のエピソードが 1 つまたは複数残っており、最後のエピソードが「NEW」ではなく、ユーザーがそのエピソード形式のコンテンツを視聴し始める前にリリースされている。

WATCHLIST: ユーザーが動画やイベント、シリーズをウォッチリストに明示的に追加し、次に視聴したいもののリストを手動で作成している。

前回のエンゲージメント時間 条件付きで必須 アイテムが連続性クラスタ内にある場合は指定する必要があります。エポックミリ秒単位。
前回の再生位置の時間 条件付きで必須 アイテムが連続性クラスタ内にあり、WatchNextType が CONTINUE の場合は指定する必要があります。エポックミリ秒単位。

LiveStreamingVideoEntity

属性 必須 / 任意 備考
名前 必須
ポスター画像 必須 少なくとも 1 つの画像が必要です。アスペクト比も指定する必要があります(横向きが推奨されますが、状況に応じて縦向きと横向きの両方の画像を渡すことをおすすめします)。

詳しくは、画像の仕様をご覧ください。

再生 URI 必須

動画を再生できる提供元のアプリへのディープリンク。

注: アトリビューションにはディープリンクを使用できます。よくある質問をご覧ください

放送局 必須 自由形式のテキスト
開始時間 任意 エポックミリ秒単位。
終了時間 任意 エポックミリ秒単位。
視聴回数 任意 自由形式のテキスト。ローカライズする必要があります。
次のおすすめのタイプ 条件付きで必須

アイテムが連続性クラスタ内にある場合は指定する必要があります。また、次の 4 つのタイプのいずれかにする必要があります。

CONTINUE: ユーザーがすでに 1 分以上コンテンツを視聴している。

NEW: エピソード形式のコンテンツで、ユーザーが利用できるエピソードをすべて視聴している中で、新しいエピソードがリリースされ、未視聴のエピソードが 1 つある(テレビ番組のシリーズや、一連のサッカーの試合など)。

NEXT: ユーザーがエピソード形式のコンテンツのエピソードを視聴しているものの、未視聴のエピソードが 1 つまたは複数残っており、最後のエピソードが「NEW」ではなく、ユーザーがそのエピソード形式のコンテンツを視聴し始める前にリリースされている。

WATCHLIST: ユーザーが動画やイベント、シリーズをウォッチリストに明示的に追加し、次に視聴したいもののリストを手動で作成している。

前回のエンゲージメント時間 条件付きで必須 アイテムが連続性クラスタ内にある場合は指定する必要があります。エポックミリ秒単位。
前回の再生位置の時間 条件付きで必須 アイテムが連続性クラスタ内にあり、WatchNextType が CONTINUE の場合は指定する必要があります。エポックミリ秒単位。

VideoClipEntity

VideoClipEntity オブジェクトは、TikTok や YouTube などのソーシャル メディアの動画エンティティを表します。

属性 必須 / 任意 備考
名前 必須
ポスター画像 必須 少なくとも 1 つの画像が必要です。アスペクト比も指定する必要があります(横向きが推奨されますが、状況に応じて縦向きと横向きの両方の画像を渡すことをおすすめします)。

詳しくは、画像の仕様をご覧ください。

再生 URI 必須

動画を再生できる提供元のアプリへのディープリンク。

注: アトリビューションにはディープリンクを使用できます。よくある質問をご覧ください

作成日時 必須 エポックミリ秒単位。
所要時間 必須 ミリ秒単位で正の値を指定する必要があります。
クリエイター 必須 自由形式のテキスト
クリエイター画像 任意 クリエイターのアバターの画像
視聴回数 任意 自由形式のテキスト。ローカライズする必要があります。
次のおすすめのタイプ 条件付きで必須

アイテムが連続性クラスタ内にある場合は指定する必要があります。また、次の 4 つのタイプのいずれかにする必要があります。

CONTINUE: ユーザーがすでに 1 分以上コンテンツを視聴している。

NEW: エピソード形式のコンテンツで、ユーザーが利用できるエピソードをすべて視聴している中で、新しいエピソードがリリースされ、未視聴のエピソードが 1 つある(テレビ番組のシリーズや、一連のサッカーの試合など)。

NEXT: ユーザーがエピソード形式のコンテンツのエピソードを視聴しているものの、未視聴のエピソードが 1 つまたは複数残っており、最後のエピソードが「NEW」ではなく、ユーザーがそのエピソード形式のコンテンツを視聴し始める前にリリースされている。

WATCHLIST: ユーザーが動画やイベント、シリーズをウォッチリストに明示的に追加し、次に視聴したいもののリストを手動で作成している。

前回のエンゲージメント時間 条件付きで必須 アイテムが連続性クラスタ内にある場合は指定する必要があります。エポックミリ秒単位。
前回の再生位置の時間 条件付きで必須 アイテムが連続性クラスタ内にあり、WatchNextType が CONTINUE の場合は指定する必要があります。エポックミリ秒単位。

画像の仕様

次のセクションでは、画像アセットに必要な仕様を示します。

ファイル形式

PNG、JPG、静止 GIF、WebP

最大ファイルサイズ

5120 KB

その他の推奨事項

  • 画像のセーフエリア: 重要なコンテンツは、画像の中央 80% の範囲内に配置してください。

Kotlin

var movie = MovieEntity.Builder()
    .setName("Avengers")
    .addPosterImage(Image.Builder()
                          .setImageUri(Uri.parse("http://www.x.com/image.png"))
                          .setImageHeightInPixel(960)
                          .setImageWidthInPixel(408)
                          .build())
    .setPlayBackUri(Uri.parse("http://tv.com/playback/1"))
    .setReleaseDateEpochMillis(1633032895L)
    .setAvailability(ContentAvailability.AVAILABILITY_AVAILABLE)
    .setDurationMillis(12345678L)
    .addGenre("action")
    .addContentRating("R")
    .setWatchNextType(WatchNextType.TYPE_NEW)
    .setLastEngagementTimeMillis(1664568895L)
    .build()

Java

MovieEntity movie = new MovieEntity.Builder()
                  .setName("Avengers")
                  .addPosterImage(
                      new Image.Builder()
                          .setImageUri(Uri.parse("http://www.x.com/image.png"))
                          .setImageHeightInPixel(960)
                          .setImageWidthInPixel(408)
                          .build())
                  .setPlayBackUri(Uri.parse("http://tv.com/playback/1"))
                  .setReleaseDateEpochMillis(1633032895L)
                  .setAvailability(ContentAvailability.AVAILABILITY_AVAILABLE)
                  .setDurationMillis(12345678L)
                  .addGenre("action")
                  .addContentRating("R")
                  .setWatchNextType(WatchNextType.TYPE_NEW)
                  .setLastEngagementTimeMillis(1664568895L)
                  .build();

ステップ 2: クラスタデータを提供する

WorkManager などを使用して、コンテンツ公開ジョブをバックグラウンドで実行し、定期的に、またはイベントごとに(ユーザーがアプリを開いたときや、カートに商品を追加したときなど)スケジュールを設定することをおすすめします。

AppEngagePublishClient はクラスタの公開を行います。クライアントでは、次の API を使用できます。

  • isServiceAvailable
  • publishRecommendationClusters
  • publishFeaturedCluster
  • publishContinuationCluster
  • publishUserAccountManagementRequest
  • updatePublishStatus
  • deleteRecommendationsClusters
  • deleteFeaturedCluster
  • deleteContinuationCluster
  • deleteUserManagementCluster
  • deleteClusters

isServiceAvailable

この API は、サービスを統合に使用できるかどうか、コンテンツをデバイスに表示できるかどうかを確認するために使用されます。

Kotlin


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.
        } else {
          // Service is not available, no further action is needed.
        }
    } else {
      // The IPC call itself fails, proceed with error handling logic here,
      // such as retry.
    }
}

Java


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

publishRecommendationClusters

この API は、RecommendationCluster オブジェクトのリストを公開するために使用されます。

Kotlin


client.publishRecommendationClusters(
      PublishRecommendationClustersRequest.Builder()
        .addRecommendationCluster(
          RecommendationCluster.Builder()
            .addEntity(entity1)
            .addEntity(entity2)
            .setTitle("Top Picks For You")
            .build()
        )
        .build()
    )

Java


client.publishRecommendationClusters(
            new PublishRecommendationClustersRequest.Builder()
                .addRecommendationCluster(
                    new RecommendationCluster.Builder()
                        .addEntity(entity1)
                        .addEntity(entity2)
                        .setTitle("Top Picks For You")
                        .build())
                .build());

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

  • デベロッパー パートナーが提供した既存の RecommendationCluster データが削除されます。
  • リクエストのデータが解析されて、更新されたおすすめコンテンツ クラスタに保存されます。

エラーが発生した場合は、リクエスト全体が拒否され、それまでの状態が維持されます。

publishFeaturedCluster

この API は、FeaturedCluster オブジェクトのリストを公開するために使用されます。

Kotlin


client.publishFeaturedCluster(
    PublishFeaturedClusterRequest.Builder()
      .setFeaturedCluster(
        FeaturedCluster.Builder()
          .addEntity(entity1)
          .addEntity(entity2)
          .build())
      .build())

Java


client.publishFeaturedCluster(
            new PublishFeaturedClustersRequest.Builder()
                .addFeaturedCluster(
                    new FeaturedCluster.Builder()
                        .addEntity(entity1)
                        .addEntity(entity2)
                        .build())
                .build());

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

  • デベロッパー パートナーが提供した既存の FeaturedCluster データが削除されます。
  • リクエストのデータが解析されて、更新された注目コンテンツ クラスタに保存されます。

エラーが発生した場合は、リクエスト全体が拒否され、それまでの状態が維持されます。

publishContinuationCluster

この API は、ContinuationCluster オブジェクトを公開するために使用されます。

Kotlin


client.publishContinuationCluster(
    PublishContinuationClusterRequest.Builder()
      .setContinuationCluster(
        ContinuationCluster.Builder()
          .addEntity(entity1)
          .addEntity(entity2)
          .build())
      .build())

Java


client.publishContinuationCluster(
            new PublishContinuationClusterRequest.Builder()
                .setContinuationCluster(
                    new ContinuationCluster.Builder()
                        .addEntity(entity1)
                        .addEntity(entity2)
                        .build())
                .build());

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

  • デベロッパー パートナーが提供した既存の ContinuationCluster データが削除されます。
  • リクエストのデータが解析されて、更新された継続クラスタに保存されます。

エラーが発生した場合は、リクエスト全体が拒否され、それまでの状態が維持されます。

publishUserAccountManagementRequest

この API は、ログインカードを公開するために使用されます。ログイン アクションにより、ユーザーをアプリのログインページに誘導し、アプリでコンテンツを公開(または、よりパーソナライズされたコンテンツを提供)できるようにします。

次のメタデータはログインカードの一部です。

属性 必須 / 任意 説明
アクション URI 必須 アクションへのディープリンク(アプリのログインページへの移動など)
画像 省略可 - 指定しない場合は、タイトルを指定する必要があります

カードに表示される画像

解像度 1264×712 でアスペクト比 16×9 の画像

タイトル 省略可 - 指定しない場合は、画像を指定する必要があります カード上のタイトル
アクション テキスト 任意 行動を促すフレーズ(ログインなど)で表示されるテキスト
字幕 任意 カードの字幕(省略可)

Kotlin


var SIGN_IN_CARD_ENTITY =
      SignInCardEntity.Builder()
          .addPosterImage(
              Image.Builder()
                  .setImageUri(Uri.parse("http://www.x.com/image.png"))
                  .setImageHeightInPixel(500)
                  .setImageWidthInPixel(500)
                  .build())
          .setActionText("Sign In")
          .setActionUri(Uri.parse("http://xx.com/signin"))
          .build()

client.publishUserAccountManagementRequest(
            PublishUserAccountManagementRequest.Builder()
                .setSignInCardEntity(SIGN_IN_CARD_ENTITY)
                .build());

Java


SignInCardEntity SIGN_IN_CARD_ENTITY =
      new SignInCardEntity.Builder()
          .addPosterImage(
              new Image.Builder()
                  .setImageUri(Uri.parse("http://www.x.com/image.png"))
                  .setImageHeightInPixel(500)
                  .setImageWidthInPixel(500)
                  .build())
          .setActionText("Sign In")
          .setActionUri(Uri.parse("http://xx.com/signin"))
          .build();

client.publishUserAccountManagementRequest(
            new PublishUserAccountManagementRequest.Builder()
                .setSignInCardEntity(SIGN_IN_CARD_ENTITY)
                .build());

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

  • デベロッパー パートナーが提供した既存の UserAccountManagementCluster データが削除されます。
  • リクエストのデータが解析されて、更新済みのユーザー アカウント管理クラスタに保存されます。

エラーが発生した場合は、リクエスト全体が拒否され、それまでの状態が維持されます。

updatePublishStatus

社内の業務上の理由でいずれのクラスタも公開されていない場合は、updatePublishStatus API を使用して公開ステータスを更新することを強くおすすめします。公開ステータスの更新が必要な理由は:

  • ダッシュボードではこのステータスの値に基づいて、統合の健全性などの指標が追加されるため、コンテンツが公開されている(STATUS == PUBLISHED)場合でも公開ステータスを明示する必要があります。
  • コンテンツは未公開でも統合ステータスが壊れていなければ(STATUS == NOT_PUBLISHED)、アプリの健全性ダッシュボードでアラートがトリガーされるのを回避できます。未公開ステータスを明示することで、プロバイダにとって想定済みの理由からコンテンツが非公開であるという確認がとれます。
  • デベロッパーは、データの公開状況に関する情報を提供できます。
  • Google が、ステータス コードを使用してアプリ内で特定のアクション(コンテンツの表示や制覇など)を行うようユーザーに促すことがあります。

利用可能な公開ステータス コードは、次のとおりです。

// Content is published
AppEngagePublishStatusCode.PUBLISHED,

// Content is not published as user is not signed in
AppEngagePublishStatusCode.NOT_PUBLISHED_REQUIRES_SIGN_IN,

// Content is not published as user is not subscribed
AppEngagePublishStatusCode.NOT_PUBLISHED_REQUIRES_SUBSCRIPTION,

// Content is not published as user location is ineligible
AppEngagePublishStatusCode.NOT_PUBLISHED_INELIGIBLE_LOCATION,

// Content is not published as there is no eligible content
AppEngagePublishStatusCode.NOT_PUBLISHED_NO_ELIGIBLE_CONTENT,

// Content is not published as the feature is disabled by the client
// Available in v1.3.1
AppEngagePublishStatusCode.NOT_PUBLISHED_FEATURE_DISABLED_BY_CLIENT,

// Content is not published as the feature due to a client error
// Available in v1.3.1
AppEngagePublishStatusCode.NOT_PUBLISHED_CLIENT_ERROR,

// Content is not published as the feature due to a service error
// Available in v1.3.1
AppEngagePublishStatusCode.NOT_PUBLISHED_SERVICE_ERROR,

// Content is not published due to some other reason
// Reach out to engage-developers@ before using this enum.
AppEngagePublishStatusCode.NOT_PUBLISHED_OTHER

ユーザーがログインしていないためにコンテンツが公開されていない場合、Google は、ログインカードを公開することをおすすめします。なんらかの理由でプロバイダがログインカードを公開できない場合は、ステータス コード NOT_PUBLISHED_REQUIRES_SIGN_IN を使用して、updatePublishStatus API を呼び出すことをおすすめします。

Kotlin


client.updatePublishStatus(
   PublishStatusRequest.Builder()
     .setStatusCode(AppEngagePublishStatusCode.NOT_PUBLISHED_REQUIRES_SIGN_IN)
     .build())

Java


client.updatePublishStatus(
    new PublishStatusRequest.Builder()
        .setStatusCode(AppEngagePublishStatusCode.NOT_PUBLISHED_REQUIRES_SIGN_IN)
        .build());

deleteRecommendationClusters

この API は、おすすめコンテンツ クラスタのコンテンツを削除するために使用されます。

Kotlin


client.deleteRecommendationClusters()

Java


client.deleteRecommendationClusters();

サービスがリクエストを受信すると、おすすめコンテンツ クラスタから既存のデータが削除されます。エラーが発生した場合は、リクエスト全体が拒否され、それまでの状態が維持されます。

deleteFeaturedCluster

この API は、注目コンテンツ クラスタのコンテンツを削除するために使用されます。

Kotlin


client.deleteFeaturedCluster()

Java


client.deleteFeaturedCluster();

サービスがリクエストを受信すると、注目コンテンツ クラスタから既存のデータが削除されます。エラーが発生した場合は、リクエスト全体が拒否され、それまでの状態が維持されます。

deleteContinuationCluster

この API は、継続クラスタのコンテンツを削除するために使用されます。

Kotlin


client.deleteContinuationCluster()

Java


client.deleteContinuationCluster();

サービスがリクエストを受信すると、継続クラスタから既存のデータが削除されます。エラーが発生した場合は、リクエスト全体が拒否され、それまでの状態が維持されます。

deleteUserManagementCluster

この API は、ユーザー アカウント管理クラスタのコンテンツを削除するために使用されます。

Kotlin


client.deleteUserManagementCluster()

Java


client.deleteUserManagementCluster();

サービスがリクエストを受信すると、ユーザー アカウント管理クラスタから既存のデータが削除されます。エラーが発生した場合は、リクエスト全体が拒否され、それまでの状態が維持されます。

deleteClusters

この API は、特定のクラスタタイプのコンテンツを削除するために使用されます。

Kotlin


client.deleteClusters(
    DeleteClustersRequest.Builder()
      .addClusterType(ClusterType.TYPE_CONTINUATION)
      .addClusterType(ClusterType.TYPE_FEATURED)
      .addClusterType(ClusterType.TYPE_RECOMMENDATION)
      .build())

Java


client.deleteClusters(
            new DeleteClustersRequest.Builder()
                .addClusterType(ClusterType.TYPE_CONTINUATION)
                .addClusterType(ClusterType.TYPE_FEATURED)
                .addClusterType(ClusterType.TYPE_RECOMMENDATION)
                .build());

サービスがリクエストを受信すると、指定したクラスタタイプに一致するすべてのクラスタから既存のデータが削除されます。クライアントは、1 つまたは複数のクラスタタイプを渡すこともできます。エラーが発生した場合は、リクエスト全体が拒否され、それまでの状態が維持されます。

エラー処理

公開 API のタスク結果をリッスンすることで、フォローアップの処理を実行し、正常なタスクを復元して再送信できるようにすることを強くおすすめします。

Kotlin


client.publishRecommendationClusters(
        PublishRecommendationClustersRequest.Builder()
          .addRecommendationCluster(..)
          .build())
      .addOnCompleteListener { task ->
        if (task.isSuccessful) {
          // do something
        } else {
          val exception = task.exception
          if (exception is AppEngageException) {
            @AppEngageErrorCode val errorCode = exception.errorCode
            if (errorCode == AppEngageErrorCode.SERVICE_NOT_FOUND) {
              // do something
            }
          }
        }
      }

Java


client.publishRecommendationClusters(
              new PublishRecommendationClustersRequest.Builder()
                  .addRecommendationCluster(...)
                  .build())
          .addOnCompleteListener(
              task -> {
                if (task.isSuccessful()) {
                  // do something
                } else {
                  Exception exception = task.getException();
                  if (exception instanceof AppEngageException) {
                    @AppEngageErrorCode
                    int errorCode = ((AppEngageException) exception).getErrorCode();
                    if (errorCode == AppEngageErrorCode.SERVICE_NOT_FOUND) {
                      // do something
                    }
                  }
                }
              });

エラーは AppEngageException として返され、その原因はエラーコードとして含まれます。

エラーコード
SERVICE_NOT_FOUND そのデバイスではこのサービスを利用できません。
SERVICE_NOT_AVAILABLE サービスをそのデバイスで利用することはできますが、呼び出し時には利用できません(明示的に無効になっている場合など)。
SERVICE_CALL_EXECUTION_FAILURE スレッドに関する問題が発生し、タスクを実行できませんでした。その場合は再試行できます。
SERVICE_CALL_PERMISSION_DENIED 呼び出し元がサービスの呼び出しを行うことができません。
SERVICE_CALL_INVALID_ARGUMENT リクエストに無効なデータが含まれています(クラスタ数が許容数を超えているなど)。
SERVICE_CALL_INTERNAL サービス側でエラーが発生しています。
SERVICE_CALL_RESOURCE_EXHAUSTED サービスの呼び出し頻度が高すぎます。

ステップ 3: ブロードキャスト インテントを処理する

ジョブを介してコンテンツ公開 API の呼び出しを行うだけでなく、コンテンツ公開のリクエストを受信するために BroadcastReceiver を設定する必要もあります。

ブロードキャスト インテントの主目的は、アプリの再有効化とデータ同期の強制です。ブロードキャスト インテントは、頻繁に送信されることを想定した設計にはなっていません。Engage のサービスが、コンテンツが古い可能性がある(1 週間前など)と判断した場合にのみトリガーされます。そうすることで、アプリが長時間実行されていない場合でも、より確実にユーザーに新しいコンテンツを提供できます。

BroadcastReceiver は、次の 2 つの方法で設定する必要があります。

  • Context.registerReceiver() を使用して、BroadcastReceiver クラスのインスタンスを動的に登録します。これにより、メモリ内でまだアクティブになっているアプリからの通信が可能になります。

Kotlin

class AppEngageBroadcastReceiver : BroadcastReceiver(){
  // Trigger recommendation cluster publish when PUBLISH_RECOMMENDATION broadcast
  // is received
  // Trigger featured cluster publish when PUBLISH_FEATURED broadcast is received
  // Trigger continuation cluster publish when PUBLISH_CONTINUATION broadcast is
  // received
}

fun registerBroadcastReceivers(context: Context){
  var  context = context
  context = context.applicationContext

// Register Recommendation Cluster Publish Intent
  context.registerReceiver(AppEngageBroadcastReceiver(),
                           IntentFilter(Intents.ACTION_PUBLISH_RECOMMENDATION))

// Register Featured Cluster Publish Intent
  context.registerReceiver(AppEngageBroadcastReceiver(),
                           IntentFilter(Intents.ACTION_PUBLISH_FEATURED))

// Register Continuation Cluster Publish Intent
  context.registerReceiver(AppEngageBroadcastReceiver(),
                           IntentFilter(Intents.ACTION_PUBLISH_CONTINUATION))
}

Java

class AppEngageBroadcastReceiver extends BroadcastReceiver {
// Trigger recommendation cluster publish when PUBLISH_RECOMMENDATION broadcast
// is received

// Trigger featured cluster publish when PUBLISH_FEATURED broadcast is received

// Trigger continuation cluster publish when PUBLISH_CONTINUATION broadcast is
// received
}

public static void registerBroadcastReceivers(Context context) {

context = context.getApplicationContext();

// Register Recommendation Cluster Publish Intent
context.registerReceiver(new AppEngageBroadcastReceiver(),
new IntentFilter(com.google.android.engage.service.Intents.ACTION_PUBLISH_RECOMMENDATION));

// Register Featured Cluster Publish Intent
context.registerReceiver(new AppEngageBroadcastReceiver(),
new IntentFilter(com.google.android.engage.service.Intents.ACTION_PUBLISH_FEATURED));

// Register Continuation Cluster Publish Intent
context.registerReceiver(new AppEngageBroadcastReceiver(),
new IntentFilter(com.google.android.engage.service.Intents.ACTION_PUBLISH_CONTINUATION));

}
  • AndroidManifest.xml ファイルで <receiver> タグを使用して、実装を静的に宣言します。これにより、アプリが実行されていないときでもブロードキャスト インテントを受信し、コンテンツを公開できるようになります。
<application>
   <receiver
      android:name=".AppEngageBroadcastReceiver"
      android:exported="true"
      android:enabled="true">
      <intent-filter>
         <action android:name="com.google.android.engage.action.PUBLISH_RECOMMENDATION" />
      </intent-filter>
      <intent-filter>
         <action android:name="com.google.android.engage.action.PUBLISH_FEATURED" />
      </intent-filter>
      <intent-filter>
         <action android:name="com.google.android.engage.action.PUBLISH_CONTINUATION" />
      </intent-filter>
   </receiver>
</application>

次のインテントがサービスによって送信されます。

  • com.google.android.engage.action.PUBLISH_RECOMMENDATION このインテントを受信したときに、publishRecommendationClusters の呼び出しを開始することをおすすめします。
  • com.google.android.engage.action.PUBLISH_FEATURED このインテントを受信したときに、publishFeaturedCluster の呼び出しを開始することをおすすめします。
  • com.google.android.engage.action.PUBLISH_CONTINUATION このインテントを受信したときに、publishContinuationCluster の呼び出しを開始することをおすすめします。

統合ワークフロー

統合完了後に検証を行う手順のガイドについては、デベロッパー向けの Engage 統合ワークフローをご覧ください。

よくある質問

よくある質問については、Engage SDK に関するよくある質問をご覧ください。

お問い合わせ

統合プロセスについてご不明な点がありましたら、engage-developers@google.com までお問い合わせください。

次のステップ

この統合が完了した後のステップは次のとおりです。

  • Google によるテストの準備が整った統合済みの APK を添付して、engage-developers@google.com にメールを送信します。
  • Google 内部で検証と審査を行い、想定どおりに統合が機能するかどうかを確認します。変更が必要な場合は、Google から必要な詳細事項をご連絡します。
  • テストが完了し、変更の必要もない場合は、更新された統合済みの APK を Google Play ストアに公開できるようになったことを Google からお知らせします。
  • 更新された APK が Google Play ストアに公開されていることを Google が確認したら、おすすめコンテンツ注目コンテンツ連続性の各クラスタが公開され、ユーザーに表示されます。