在遊戲中整合 PGS Recall API

本頁面說明如何在遊戲中實作 Recall API。首先介紹如何設定遊戲伺服器和用戶端來支援這個 API,接著逐步解說如何儲存及擷取符記。

遊戲伺服器設定

設定遊戲伺服器,向 Google 伺服器發出 Recall API 呼叫。

1. 設定 Play 遊戲服務專案

如果尚未完成設定,請按照「設定 Google Play 遊戲服務」的指示操作。

2. 為遊戲設定服務帳戶

按照「建立服務帳戶」的指示操作。最後,您應該會取得含有服務帳戶憑證的 JSON 檔案。

<x0A>

3. 下載 PlayGamesServices 的伺服器端 Java 程式庫

下載最新的 google-api-services-games 程式庫,並上傳至伺服器。

4. 為 Recall API 呼叫準備憑證

詳情請參閱「準備發出授權的 API 呼叫」一文。

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.services.games.Games;
import com.google.api.services.games.GamesScopes;

// ...

GoogleCredential credential =
  GoogleCredential.fromStream(new FileInputStream("<credentials>.json"))
    .createScoped(Collections.singleton(GamesScopes.ANDROIDPUBLISHER));

Games gamesApi =
    new Games.Builder(httpTransport, JSON_FACTORY, credential).build();

遊戲用戶端設定

設定遊戲用戶端,以擷取伺服器用來與 Google 伺服器連線的喚回工作階段 ID。

Java SDK

在用戶端中設定 Java SDK,並務必納入 com.google.android.gms:play-services-games-v2:19.0.0

並在 Gradle 檔案中納入 com.google.android.gms:play-services-tasks:18.0.2 以上版本。

為了使用正確資訊與 Google 伺服器建立連線,您必須從用戶端 SDK 要求喚回工作階段 ID,並傳送至遊戲伺服器。

Kotlin

PlayGames.getRecallClient(getActivity())
                .requestRecallAccess()
                .addOnSuccessListener { recallAccess -> val recallSessionId: String = recallAccess.getSessionId() }
                // Send the recallSessionId to your game server

Java

PlayGames.getRecallClient(getActivity())
  .requestRecallAccess()
  .addOnSuccessListener(
    recallAccess -> {
      String recallSessionId = recallAccess.getSessionId();
      // Send the recallSessionId to your game server
    });

Unity SDK

如尚未完成設定,請在用戶端中設定 Unity SDK

為了使用正確資訊與 Google 伺服器建立連線,您必須從用戶端 SDK 要求喚回工作階段 ID,並傳送至遊戲伺服器。

PlayGamesPlatform.Instance.RequestRecallAccess(
    recallAccess => {
        string recallSessionId = recallAccess.sessionId;
        // Send the recallSessionId to your game server
    });

在遊戲伺服器中使用 Recall API

設定伺服器和用戶端後,只要從遊戲用戶端將 recallSessionID 傳送至遊戲伺服器,並按照以下指示操作,即可開始在伺服器端使用 Java API 儲存、擷取或刪除喚回符記。

儲存符記

Google Play Games Recall API 中的玩家帳戶包含兩項資訊:

  • 身分 ID,做為遊戲內帳戶的穩定 ID
  • 權杖:做為安全地將玩家登入帳戶的金鑰

使用 LinkPersonaRequest 物件即可儲存使用者的人物角色和符記。您必須使用 GoogleCredential 呼叫 Google API (詳情請參閱「呼叫 Google API」一文)。人物角色有1:1 基數限制:單一 PGS 設定檔只能包含單一人物角色,且人物角色只能存在於單一 PGS 設定檔中。設定衝突連結解決政策,定義如何解決違反 1:1 基數限制的問題。

視需要設定權杖的到期時間。使用 SetTtl()Durations 物件設定存留時間,或使用 setExpireTime() 提供確切的到期時間。

您必須對人物角色和遊戲符記加密,且不得包含個人識別資訊。人物角色和符記的字串長度上限為 256 個字元。

import com.google.api.services.games.Games.Recall.LinkPersona;
import com.google.api.services.games.model.LinkPersonaRequest;
import com.google.api.services.games.model.LinkPersonaResponse;
import com.google.protobuf.util.Durations;

// ...

Games gamesApi =
    new Games.Builder(httpTransport, JSON_FACTORY, credential).build();

String recallSessionId = ... // recallSessionID from game client
String persona = ... // encrypted opaque string, stable for in-game account
String token = ... // encrypted opaque string encoding the progress line

LinkPersonaRequest linkPersonaRequest =
  LinkPersonaRequest.newBuilder()
    .setSessionId(recallSessionId)
    .setPersona(persona)
    .setToken(token)
    .setCardinalityConstraint(ONE_PERSONA_TO_ONE_PLAYER)
    .setConflictingLinksResolutionPolicy(CREATE_NEW_LINK)
    .setTtl(Durations.fromDays(7)) // Optionally set TTL for token
    .build();

LinkPersonaResponse linkPersonaResponse =
  gamesApi.recall().linkPersona(linkPersonaRequest).execute();

if (linkPersonaResponse.getState() == LINK_CREATED) {
  // success
}

擷取符記

您可以根據遊戲需求,透過三種方式擷取權杖。您可以要求下列項目:

  • 與目前遊戲相關聯的權杖,包括遊戲範圍內的回想權杖。
  • 開發人員帳戶擁有的所有遊戲中儲存的最後一個權杖。
  • 針對開發人員帳戶擁有的遊戲清單,列出與各遊戲相關聯的所有回溯權杖。

遊戲範圍的召回權杖

如要從目前遊戲擷取喚回符記,請從用戶端取得 recallSessionId,並傳遞至 retrieveTokens API:

import com.google.api.services.games.Games;
import com.google.api.services.games.model.RetrievePlayerTokensResponse;
import com.google.api.services.games.model.RecallToken;

// ...

String recallSessionId = ... // recallSessionID from game client

RetrievePlayerTokensResponse retrievePlayerTokensResponse =
  gamesApi.recall().retrieveTokens(recallSessionId).execute();

for (RecallToken recallToken : retrievePlayerTokensResponse.getTokens()) {
  String token recallToken.getToken();
  // Same string as was written in LinkPersona call
  // decrypt and recover in-game account
}

開發人員帳戶擁有的所有遊戲中,最新的喚回符記

如要擷取 Google Play 管理中心開發人員帳戶擁有的所有遊戲中儲存的最新權杖,您需要從用戶端取得 recallSessionId,並將其傳遞至 lastTokenFromAllDeveloperGames API,如下列程式碼片段所示。在回應中,您可以檢查與這個權杖相關聯的應用程式 ID

import com.google.api.services.games.Games;
import com.google.api.services.games.model.RetrieveDeveloperGamesLastPlayerTokenResponse;
import com.google.api.services.games.model.GamePlayerToken;
import com.google.api.services.games.model.RecallToken;

// ...

String recallSessionId = ... // recallSessionID from game client

RetrieveDeveloperGamesLastPlayerTokenResponse response =
        gamesApi.recall().lastTokenFromAllDeveloperGames(recallSessionId)
        .execute();

if (response.hasGamePlayerToken()) {
    GamePlayerToken gamePlayerToken = response.getGamePlayerToken();

    // The ID of the application that the token is associated with.
    String applicationId = gamePlayerToken.getApplicationId();

    // Same string as was written in LinkPersona call.
    RecallToken recallToken = gamePlayerToken.getRecallToken();

    // Decrypt and recover in-game account.
}

開發人員帳戶所列遊戲的所有喚回符記

如要擷取與 Google Play 管理中心開發人員帳戶擁有的遊戲清單相關聯的所有權杖,請從用戶端取得 recallSessionId,然後傳遞至 gamesPlayerTokens API。提供應用程式 ID 清單。

import com.google.api.services.games.Games;
import com.google.api.services.games.model.RetrieveGamesPlayerTokensResponse;
import com.google.api.services.games.model.GamePlayerToken;
import com.google.api.services.games.model.RecallToken;

// ...

String recallSessionId = ... // recallSessionID from game client

// Application IDs for which you would like to retrieve the recall tokens.
List<String> applicationIds = ...

RetrieveGamesPlayerTokensResponse response =
gamesApiClient
        .recall()
        .gamesPlayerTokens(recallSessionId)
        .setApplicationIds(applicationIds)
        .execute();

for (GamePlayerToken gamePlayerToken : response.getGamePlayerTokens()) {
    // The ID of the application that the token is associated with.
    String applicationId  = gamePlayerToken.getApplicationId();

    // Same string as was written in LinkPersona call.
    RecallToken recallToken = gamePlayerToken.getRecallToken();

    // Decrypt and recover in-game account.
}

刪除喚回符記

必要時,您也可以透過以下呼叫刪除喚回符記:

import com.google.api.services.games.Games;
import com.google.api.services.games.model.UnlinkPersonaRequest;
import com.google.api.services.games.model.UnlinkPersonaResponse;

// ...

String recallSessionId = ...
String persona = ...
String token = ...

Games gamesApi =
    new Games.Builder(httpTransport, JSON_FACTORY, credential).build();

UnlinkPersonaRequest unlinkPersonaRequest =
  UnlinkPersonaRequest.newBuilder()
    .setSessionId(recallSessionId)
    .setPersona(persona)
    // .setToken(token) - alternatively set token, but not both
    .build();

UnlinkPersonaResponse unlinkPersonaResponse =
  gamesApi.recall().unlinkPersona(unlinkPersonaRequest).execute();

boolean unlinked = unlinkPersonaResponse.isUnlinked();

啟用無設定檔模式

如要為沒有 PGS 設定檔的使用者啟用有限的 Recall API 功能,請按照下列步驟操作:

  1. 在 Play 管理中心中,為 PGS 遊戲專案啟用無設定檔喚回功能。選取標示為「開啟儲存空間」的選項。
  2. 請參閱本節稍後說明的其他條款
  3. 應用程式資訊清單中加入下列中繼資料標記:
<meta-data
  android:name="com.google.android.gms.games.PROFILELESS_RECALL_ENABLED"
  android:value="true" />

附加條款

除了須遵守《Play 遊戲服務服務條款》外,您也同意,如果對沒有 PGS 設定檔的使用者使用 Recall API,讓系統在使用者沒有 Play 遊戲服務設定檔的情況下,與 Google 分享使用者資料,您必須先向使用者提供適當的通知,說明下列事項,再與 Google 分享這類資料:

  1. 您與 Google 共用資料,啟用 Play 遊戲帳戶連結功能。
  2. 管理這類分享內容的設定是否可用,例如透過 Play 遊戲設定。
  3. 根據《Google 隱私權政策》處理這類資料,並取得適當的使用者同意聲明,確保共用資料符合所有適用的法律規定。