Engage SDK Watch:第三方技術整合操作說明

Google 正在建構的裝置端途徑會依產業別將使用者的應用程式分門別類,並提供全新沉浸式體驗,可供使用者取用及瀏覽個人化應用程式內容。開發合作夥伴可以利用這個全螢幕體驗,在應用程式以外的專屬管道展示最精彩的多媒體內容。

本指南適用對象為開發合作夥伴,提供透過 Engage SDK 填入新途徑區域和現有 Google 途徑,整合影片內容的操作說明。

整合詳情

術語

這項整合包含以下三個叢集類型:推薦接續精選

  • 「推薦」叢集會顯示個別開發合作夥伴針對影片內容提供的個人化建議。

    推薦內容採用以下結構:

    • 推薦叢集:此 UI 檢視畫面包含相同開發合作夥伴提供的一組推薦內容。

      圖 1. Entertainment Space UI 顯示單一合作夥伴提供的推薦叢集。
    • 實體:代表叢集中單一項目的物件。實體可以是電影、電視節目、電視影集和即時影像等等。如需支援的實體類型清單,請參閱「提供實體資料」一節。

      圖 2. Entertainment Space UI 顯示單一合作夥伴推薦叢集內的單一實體。
  • 「接續」叢集會在一個 UI 群組中,顯示多個開發合作夥伴提供的未播完影片以及新發布的相關劇集。每個開發合作夥伴最多可在接續叢集中播送 10 個實體。研究顯示,個人化推薦內容和個人化接續內容可帶來最佳使用者參與度。

    圖 3. Entertainment Space UI 顯示的接續叢集,內含多個合作夥伴提供的未播完推薦內容 (目前只能看到一則推薦內容)。
  • 「精選」叢集會在一個 UI 群組中展示多個開發合作夥伴提供的精選實體。這個單一精選叢集會顯示在靠近 UI 頂端的位置,並且優先放置在所有推薦叢集的上方。每個開發合作夥伴最多可在精選叢集中播送 10 個實體。

    圖 4. Entertainment Space UI 顯示的精選叢集,內含多個合作夥伴提供的推薦內容 (目前只能看到一則推薦內容)。

事前作業

最低 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 時,叢集和實體發布會合併為單一 API 呼叫。屬於某個叢集的所有實體會與該叢集一起發布:

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 定義了不同實體,用來代表各種項目類型。Watch 類別支援下列實體:

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

下方圖表列出各類型的屬性和必要性。

MovieEntity

屬性 必要性 附註
名稱 必要
代表圖片 必要 至少需要一張圖片,且必須提供顯示比例 (偏好使用橫向圖片,但建議您同時傳送直向和橫向圖片供不同情境使用)。

如需相關指南,請參閱「圖片規格」一節。

播放 URI 必要

供應商應用程式的深層連結,可開始播放電影。

注意:您可以使用深層連結追蹤歸因。請參閱這篇常見問題文章

資訊頁面 URI 選用

供應商應用程式的深層連結,可顯示電影相關詳細資訊。

注意:您可以使用深層連結追蹤歸因。請參閱這篇常見問題文章

發布日期 必要 以 Epoch 時間計算的毫秒為單位。
可用條件 必要

AVAILABLE:使用者無須採取進一步行動,即可使用內容。

FREE_WITH_SUBSCRIPTION:使用者購買訂閱項目後,即可使用內容。

PAID_CONTENT:使用者必須購買或租借內容。

PURCHASED:使用者已購買或租借內容。

優惠價格 選用 任意文字
時間長度 必要 以毫秒為單位。
類型 必要 任意文字
內容分級 必要 任意文字,請遵循業界標準 (範例)。
「接下來請看」類型 在特定情況下為必要

當項目屬於接續叢集時必須提供,且須為以下四種類型之一:

CONTINUE:使用者已觀看此內容超過 1 分鐘。

NEW:使用者已看過某部劇集內容的所有上架集數,但新集數已上架,而且剛好只有一集尚未觀看。這類型適用於電視節目、足球比賽系列影片錄影等等。

NEXT:使用者已看完某部劇集內容的一或多個完整集數,但還剩下多集或剛好一集尚未觀看,而且最後一集並不屬於「NEW」類型,在使用者開始觀看該部劇集內容之前已經發布。

WATCHLIST:使用者已明確選擇將電影、活動或影集加入待觀看影劇清單,手動收錄接下來想看的內容。

上次互動時間 在特定情況下為必要 當項目屬於接續叢集時必須提供。以 Epoch 紀元時間計算的毫秒為單位。
上次播放位置時間點 在特定情況下為必要 當項目屬於接續叢集且 WatchNextType 為 CONTINUE 時必須提供。以 Epoch 時間計算的毫秒為單位。

TvShowEntity

屬性 必要性 附註
名稱 必要
代表圖片 必要 至少需要一張圖片,且必須提供顯示比例 (偏好使用橫向圖片,但建議您同時傳送直向和橫向圖片供不同情境使用)。

如需相關指南,請參閱「圖片規格」一節。

資訊頁面 URI 必要

供應商應用程式的深層連結,可顯示電視節目的詳細資料。

注意:您可以使用深層連結追蹤歸因。請參閱這篇常見問題文章

播放 URI 選用

供應商應用程式的深層連結,可開始播放電視節目。

注意:您可以使用深層連結追蹤歸因。請參閱這篇常見問題文章

第一集播映日期 必要 以 Epoch 時間計算的毫秒為單位。
最新一集播映日期 選用 以 Epoch 時間計算的毫秒為單位。
可用條件 必要

AVAILABLE:使用者無須採取進一步行動,即可使用內容。

FREE_WITH_SUBSCRIPTION:使用者購買訂閱項目後,即可使用內容。

PAID_CONTENT:使用者必須購買或租借內容。

PURCHASED:使用者已購買或租借內容。

優惠價格 選用 任意文字
季數 必要 正整數
類型 必要 任意文字
內容分級 必要 任意文字,請遵循業界標準 (範例)。
「接下來請看」類型 在特定情況下為必要

當項目屬於接續叢集時必須提供,且須為以下四種類型之一:

CONTINUE:使用者已觀看此內容超過 1 分鐘。

NEW:使用者已看過某部劇集內容的所有上架集數,但新集數已上架,而且剛好只有一集尚未觀看。這類型適用於電視節目、足球比賽系列影片錄影等等。

NEXT:使用者已看完某部劇集內容的一或多個完整集數,但還剩下多集或剛好一集尚未觀看,而且最後一集並不屬於「NEW」類型,在使用者開始觀看該部劇集內容之前已經發布。

WATCHLIST:使用者已明確選擇將電影、活動或影集加入待觀看影劇清單,手動收錄接下來想看的內容。

上次互動時間 在特定情況下為必要 當項目屬於接續叢集時必須提供。以 Epoch 紀元時間計算的毫秒為單位。
上次播放位置時間點 在特定情況下為必要 當項目屬於接續叢集且 WatchNextType 為 CONTINUE 時必須提供。以 Epoch 時間計算的毫秒為單位。

TvSeasonEntity

屬性 必要性 附註
名稱 必要
代表圖片 必要 至少需要一張圖片,且必須提供顯示比例 (偏好使用橫向圖片,但建議您同時傳送直向和橫向圖片供不同情境使用)。

如需相關指南,請參閱「圖片規格」一節。

資訊頁面 URI 必要

供應商應用程式的深層連結,可顯示某季電視節目的詳細資料。

注意:您可以使用深層連結追蹤歸因。請參閱這篇常見問題文章

播放 URI 選用

供應商應用程式的深層連結,可開始播放某季電視節目。

注意:您可以使用深層連結追蹤歸因。請參閱這篇常見問題文章

顯示季別

選用

適用於 1.3.1 版

字串
第一集播映日期 必要 以 Epoch 時間計算的毫秒為單位。
最新一集播映日期 選用 以 Epoch 時間計算的毫秒為單位。
可用條件 必要

AVAILABLE:使用者無須採取進一步行動,即可使用內容。

FREE_WITH_SUBSCRIPTION:使用者購買訂閱項目後,即可使用內容。

PAID_CONTENT:使用者必須購買或租借內容。

PURCHASED:使用者已購買或租借內容。

優惠價格 選用 任意文字
集數 必要 正整數
類型 必要 任意文字
內容分級 必要 任意文字,請遵循業界標準 (範例)。
「接下來請看」類型 在特定情況下為必要

當項目屬於接續叢集時必須提供,且須為以下四種類型之一:

CONTINUE:使用者已觀看此內容超過 1 分鐘。

NEW:使用者已看過某部劇集內容的所有上架集數,但新集數已上架,而且剛好只有一集尚未觀看。這類型適用於電視節目、足球比賽系列影片錄影等等。

NEXT:使用者已看完某部劇集內容的一或多個完整集數,但還剩下多集或剛好一集尚未觀看,而且最後一集並不屬於「NEW」類型,在使用者開始觀看該部劇集內容之前已經發布。

WATCHLIST:使用者已明確選擇將電影、活動或影集加入待觀看影劇清單,手動收錄接下來想看的內容。

上次互動時間 在特定情況下為必要 當項目屬於接續叢集時必須提供。以 Epoch 紀元時間計算的毫秒為單位。
上次播放位置時間點 在特定情況下為必要 當項目屬於接續叢集且 WatchNextType 為 CONTINUE 時必須提供。以 Epoch 時間計算的毫秒為單位。

TvEpisodeEntity

屬性 必要性 附註
名稱 必要
代表圖片 必要 至少需要一張圖片,且必須提供顯示比例 (偏好使用橫向圖片,但建議您同時傳送直向和橫向圖片供不同情境使用)。

如需相關指南,請參閱「圖片規格」一節。

播放 URI 必要

供應商應用程式的深層連結,可開始播放劇集。

注意:您可以使用深層連結追蹤歸因。請參閱這篇常見問題文章

資訊頁面 URI 選用

供應商應用程式的深層連結,可顯示電視節目劇集相關詳細資訊。

注意:您可以使用深層連結追蹤歸因。請參閱這篇常見問題文章

顯示集別

選用

適用於 1.3.1 版

字串
播映日期 必要 以 Epoch 時間計算的毫秒為單位。
可用條件 必要

AVAILABLE:使用者無須採取進一步行動,即可使用內容。

FREE_WITH_SUBSCRIPTION:使用者購買訂閱項目後,即可使用內容。

PAID_CONTENT:使用者必須購買或租借內容。

PURCHASED:使用者已購買或租借內容。

優惠價格 選用 任意文字
時間長度 必要 必須是以毫秒為單位的正值。
類型 必要 任意文字
內容分級 必要 任意文字,請遵循業界標準 (範例)。
「接下來請看」類型 在特定情況下為必要

當項目屬於接續叢集時必須提供,且須為以下四種類型之一:

CONTINUE:使用者已觀看此內容超過 1 分鐘。

NEW:使用者已看過某部劇集內容的所有上架集數,但新集數已上架,而且剛好只有一集尚未觀看。這類型適用於電視節目、足球比賽系列影片錄影等等。

NEXT:使用者已看完某部劇集內容的一或多個完整集數,但還剩下多集或剛好一集尚未觀看,而且最後一集並不屬於「NEW」類型,在使用者開始觀看該部劇集內容之前已經發布。

WATCHLIST:使用者已明確選擇將電影、活動或影集加入待觀看影劇清單,手動收錄接下來想看的內容。

上次互動時間 在特定情況下為必要 當項目屬於接續叢集時必須提供。以 Epoch 紀元時間計算的毫秒為單位。
上次播放位置時間點 在特定情況下為必要 當項目屬於接續叢集且 WatchNextType 為 CONTINUE 時必須提供。以 Epoch 時間計算的毫秒為單位。

LiveStreamingVideoEntity

屬性 必要性 附註
名稱 必要
代表圖片 必要 至少需要一張圖片,且必須提供顯示比例 (偏好使用橫向圖片,但建議您同時傳送直向和橫向圖片供不同情境使用)。

如需相關指南,請參閱「圖片規格」一節。

播放 URI 必要

供應商應用程式的深層連結,可開始播放影片。

注意:您可以使用深層連結追蹤歸因。請參閱這篇常見問題文章

電視台 必要 任意文字
開始時間 選用 以 Epoch 時間計算的毫秒為單位。
結束時間 選用 以 Epoch 時間計算的毫秒為單位。
觀看次數 選用 任意文字,必須進行本地化。
「接下來請看」類型 在特定情況下為必要

當項目屬於接續叢集時必須提供,且須為以下四種類型之一:

CONTINUE:使用者已觀看此內容超過 1 分鐘。

NEW:使用者已看過某部劇集內容的所有上架集數,但新集數已上架,而且剛好只有一集尚未觀看。這類型適用於電視節目、足球比賽系列影片錄影等等。

NEXT:使用者已看完某部劇集內容的一或多個完整集數,但還剩下多集或剛好一集尚未觀看,而且最後一集並不屬於「NEW」類型,在使用者開始觀看該部劇集內容之前已經發布。

WATCHLIST:使用者已明確選擇將電影、活動或影集加入待觀看影劇清單,手動收錄接下來想看的內容。

上次互動時間 在特定情況下為必要 當項目屬於接續叢集時必須提供。以 Epoch 紀元時間計算的毫秒為單位。
上次播放位置時間點 在特定情況下為必要 當項目屬於接續叢集且 WatchNextType 為 CONTINUE 時必須提供。以 Epoch 時間計算的毫秒為單位。

VideoClipEntity

VideoClipEntity 物件代表來自社群媒體 (例如 TikTok 或 YouTube) 的影片實體。

屬性 必要性 附註
名稱 必要
代表圖片 必要 至少需要一張圖片,且必須提供顯示比例 (偏好使用橫向圖片,但建議您同時傳送直向和橫向圖片供不同情境使用)。

如需相關指南,請參閱「圖片規格」一節。

播放 URI 必要

供應商應用程式的深層連結,可開始播放影片。

注意:您可以使用深層連結追蹤歸因。請參閱這篇常見問題文章

建立時間 必要 以 Epoch 時間計算的毫秒為單位。
時間長度 必要 必須是以毫秒為單位的正值。
創作者 必要 任意文字
創作者圖片 選用 創作者顯示圖片
觀看次數 選用 任意文字,必須進行本地化。
「接下來請看」類型 在特定情況下為必要

當項目屬於接續叢集時必須提供,且須為以下四種類型之一:

CONTINUE:使用者已觀看此內容超過 1 分鐘。

NEW:使用者已看過某部劇集內容的所有上架集數,但新集數已上架,而且剛好只有一集尚未觀看。這類型適用於電視節目、足球比賽系列影片錄影等等。

NEXT:使用者已看完某部劇集內容的一或多個完整集數,但還剩下多集或剛好一集尚未觀看,而且最後一集並不屬於「NEW」類型,在使用者開始觀看該部劇集內容之前已經發布。

WATCHLIST:使用者已明確選擇將電影、活動或影集加入待觀看影劇清單,手動收錄接下來想看的內容。

上次互動時間 在特定情況下為必要 當項目屬於接續叢集時必須提供。以 Epoch 紀元時間計算的毫秒為單位。
上次播放位置時間點 在特定情況下為必要 當項目屬於接續叢集且 WatchNextType 為 CONTINUE 時必須提供。以 Epoch 時間計算的毫秒為單位。

圖片規格

以下章節列出圖片素材資源的必要規格:

檔案格式

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

服務收到要求後,系統會在單一交易中執行以下動作:

  • 移除開發合作夥伴提供的現有 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());

服務收到要求後,系統會在單一交易中執行以下動作:

  • 移除開發合作夥伴提供的現有 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());

服務收到要求後,系統會在單一交易中執行以下動作:

  • 移除開發合作夥伴提供的現有 ContinuationCluster 資料。
  • 剖析要求所提供的資料並儲存在更新後的接續叢集中。

如果發生錯誤,整個要求都會遭到拒絕,現有狀態則維持不變。

publishUserAccountManagementRequest

這個 API 是用來發布「登入」資訊卡。登入動作會將使用者導向應用程式的登入頁面,方便應用程式發布內容 (或提供更個人化的內容)

登入資訊卡包含下列中繼資料:

屬性 必要性 說明
動作 URI 必要 導向動作的深層連結,也就是前往應用程式登入頁面
圖片 選用 - 如未提供,則必須提供標題

資訊卡上顯示的圖片

解析度 1264x712、顯示比例 16x9 的圖片

標題 選用 - 如未提供,則必須提供圖片 資訊卡上的標題
動作文字 選用 行動號召中顯示的文字,也就是「登入」
副標題 選用 資訊卡上的選用副標題

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

服務收到要求後,系統會在單一交易中執行以下動作:

  • 移除開發合作夥伴提供的現有 UserAccountManagementCluster 資料。
  • 剖析要求所提供的資料並儲存在更新後的 UserAccountManagementCluster 叢集中。

如果發生錯誤,整個要求都會遭到拒絕,現有狀態則維持不變。

updatePublishStatus

如因內部業務原因,導致無法發布任何叢集,我們強烈建議使用 updatePublishStatus API 更新發布狀態。這麼做很重要,因為:

  • 在所有情況下,提供狀態都至關重要,即使內容已發布 (STATUS == PUBLISHED) 也一樣。如此一來,才能為資訊主頁填入資料,並以明確的狀態表示整合項目的健康度和其他指標。
  • 如未發布內容,但整合狀態未遭中斷 (STATUS == NOT_PUBLISHED),Google 便可避免在應用程式健康資訊主頁中觸發快訊。這可從提供者的角度確認內容是因預期的情況而未發布。
  • 這有助開發人員深入瞭解資料何時已發布或未發布。
  • 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

如果內容因使用者未登入而未發布,建議您發布登入資訊卡。如因任何原因導致提供者無法發布登入資訊卡,建議您呼叫 updatePublishStatus API,並使用狀態碼 NOT_PUBLISHED_REQUIRES_SIGN_IN

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 可用來刪除 UserAccountManagement 叢集的內容。

Kotlin


client.deleteUserManagementCluster()

Java


client.deleteUserManagementCluster();

服務收到要求後,會從 UserAccountManagement 叢集中移除現有資料。如果發生錯誤,整個要求都會遭到拒絕,現有狀態則維持不變。

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

服務收到要求後,會從符合指定叢集類型的所有叢集中移除現有資料。用戶端可以選擇傳遞一或多個叢集類型。如果發生錯誤,整個要求都會遭到拒絕,現有狀態則維持不變。

處理錯誤

強烈建議您監聽來自發布 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 Service 判定內容可能過時 (例如已滿一週)。這樣一來,即使應用程式已有長時間未執行,使用者也能獲得最新的內容體驗。

BroadcastReceiver 必須透過下列兩種方式進行設定:

  • 使用 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 與我們聯絡。

後續步驟

完成這項整合後,後續步驟如下:

  • 傳送電子郵件至 engage-developers@google.com,並附上整合完成可供 Google 測試的 APK。
  • Google 會在內部執行驗證及審查,確認整合項目能夠正常運作。如果需要進行變更,Google 會與您聯絡並提供所有必要詳細資料。
  • 測試完成後,如果不需要進行任何變更,Google 會與您聯絡,通知您可以開始將完成整合的更新版 APK 發布至 Play 商店。
  • Google 確認您已將更新版 APK 發布至 Play 商店後,就會發布您的推薦精選接續叢集供使用者瀏覽。