На этой странице объясняется, как реализовать API Recall в вашей игре. Сначала рассматривается настройка игрового сервера и клиента для поддержки API, а затем объясняется, как хранить и извлекать токены.
Настройка игрового сервера
Настройте свой игровой сервер для выполнения вызовов API Recall к серверам Google.
1. Настройте свой проект Play Games Services.
Если вы еще этого не сделали, следуйте инструкциям в разделе «Настройка служб Google Play Games» .
2. Создайте служебный аккаунт для игры.
Следуйте инструкциям по созданию учетной записи службы . В итоге у вас должен получиться JSON-файл с учетными данными учетной записи службы.
3. Загрузите серверную Java-библиотеку для PlayGamesServices.
Загрузите библиотеку google-api-services-games и выложите её на свой сервер.
4. Подготовьте учетные данные для вызовов API Recall.
Дополнительную информацию см. в разделе «Подготовка к выполнению авторизованного вызова 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.
Java SDK
Установите Java SDK в вашем клиенте и убедитесь, что в файл Gradle добавлены com.google.android.gms:play-services-games-v2:19.0.0 и com.google.android.gms:play-services-tasks:18.0.2 или более поздней версии.
Для связи с серверами Google с корректной информацией необходимо запросить идентификатор сессии Recall у клиентского SDK, который затем отправляется на сервер вашей игры.
Котлин
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 с корректной информацией необходимо запросить идентификатор сессии Recall у клиентского SDK и отправить его на сервер вашей игры.
PlayGamesPlatform.Instance.RequestRecallAccess(
recallAccess => {
string recallSessionId = recallAccess.sessionId;
// Send the recallSessionId to your game server
});
v2 Нативный SDK (бета-версия)
Если вы еще этого не сделали, начните работу с Play Games Services для C и C++ .
// Include the following headers
#include "play_games.h"
#include "recall_client.h"
#include "pgs_status_code.h"
// Request Recall Access
// Initializes the Play Games Services v2 Native SDK (beta).
Pgs_initialize(javaVM, activity);
//Creating Recall Client
PgsRecallClient* pgs_recall_client =
PgsRecallClient_create(activity);
// RequestRecallAccess Function
PgsRecallClient_requestRecallAccess(
pgs_recall_client,
// This is your callback function defined as an inline lambda
[](PgsStatusCode status_code, char* session_id, user_data) {
if (status_code == PGS_STATUS_SUCCESS) {
// Recall Session Id Fetched Successfully
} else {
// Fetching Recall Session Id Failed
// Handle error based on status_code.
// Examples:
// PGS_STATUS_NETWORK_ERROR: Check internet connection.
// PGS_STATUS_INTERNAL_ERROR: An unexpected error occurred.
}
// Clean up the client instance passed as user_data
PgsRecallClient* client = static_cast<PgsRecallClient*>(user_data);
if (client != nullptr) {
PgsRecallClient_destroy(client);
}
},
user_data // Data to pass to the callback
);
// Shuts down the Play Games Services v2 Native SDK (beta).
Pgs_destroy()
Используйте API Recall на своем игровом сервере.
После настройки сервера и клиента вы можете отправить recallSessionID из игрового клиента на игровой сервер и следовать приведенным ниже инструкциям, чтобы начать использовать Java API для хранения, извлечения или удаления токенов Recall на стороне сервера.
Токены магазина
В API Google Play Games учетная запись игрока состоит из двух частей информации:
- Персонаж , служащий стабильным идентификатором для внутриигрового аккаунта.
- Токен, служащий ключом для безопасного входа игрока в учетную запись.
Вы можете хранить профиль пользователя и токен, используя объект LinkPersonaRequest . Используйте GoogleCredential для вызова API Google (см. раздел «Вызов API Google» для получения дополнительной информации). Для профиля пользователя действует ограничение кардинальности 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 от клиента и передайте его в API retrieveTokens :
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 Console, необходимо получить recallSessionId от клиента и передать его в API lastTokenFromAllDeveloperGames , как показано в следующем фрагменте кода. В ответе вы можете увидеть идентификатор приложения, связанный с этим токеном.
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 Console, получите recallSessionId от клиента и передайте его в API gamesPlayerTokens . Укажите список идентификаторов приложений .
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, можно включить ограниченную функциональность API Recall, выполнив следующие действия:
- Включите функцию вызова без профилирования для вашего игрового проекта PGS в консоли разработчика Play.

- Ознакомьтесь с дополнительными терминами, описанными далее в этом разделе.
- Добавьте следующий тег метаданных в манифест вашего приложения :
<meta-data
android:name="com.google.android.gms.games.PROFILELESS_RECALL_ENABLED"
android:value="true" />
Дополнительные условия
Вы также должны соблюдать Условия предоставления услуг Play Games Services . Если вы используете API Recall для пользователей без профиля PGS, что предполагает передачу данных конечных пользователей в Google, вы должны, прежде чем передавать эти данные в Google, предоставить конечным пользователям соответствующее уведомление, описывающее следующее:
- Как вы обмениваетесь данными с Google, чтобы активировать функцию привязки учетных записей Play Games.
- Доступны настройки для управления этим обменом данными, например, через настройки Play Games.
- Обработка этих данных осуществляется в соответствии с Политикой конфиденциальности Google и требует получения надлежащего согласия конечного пользователя на их передачу, отвечающего всем применимым правовым требованиям.