在遊戲中整合 PGS Recall API

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

遊戲伺服器設定

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

1. 設定 Play 遊戲服務專案

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

2. 為遊戲設定服務帳戶

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

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,並務必在 Gradle 檔案中納入 com.google.android.gms:play-services-games-v2:19.0.0com.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 儲存、擷取或刪除喚回符記。

儲存符記

使用 LinkPersonaRequest 物件即可儲存使用者的人物角色和遊戲符記。您必須使用 GoogleCredential 呼叫 Google API (詳情請參閱「呼叫 Google API」一文)。請注意,由於 1:1 基數限制,您只能將一個人物角色連結至一個 PGS 設定檔 (反之亦然)。建議您設定這項解決政策,避免該 PGS 設定檔已連結至另一個人物角色。

或者,您可以選擇為符記設定存留時間,使用 Durations 物件宣告符記的有效時間長度。您可以選擇使用 SetTtl() (如下所示),依方法中指定的時間長度設定有效期限;或使用 setExpireTime() 來設定符記確切的到期時間。

您必須對人物角色和遊戲符記加密,且不得包含個人識別資訊。人物角色和符記的字串長度上限為 256 個字元,且每名玩家在每個遊戲中最多可儲存 20 個符記或人物角色。

系統在特定時間內只能為每名玩家的每個人物角色儲存一個符記。嘗試儲存相同人物角色的其他符記會覆寫原始符記。

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 Play 遊戲分享資料相關的法律處理規定和適用聲明,例如:1) 根據相關法律連結規定,向使用者提供與 Google Play 遊戲分享資料的適用聲明及相關法律聲明等規定。