如果您的游戏使用后端服务器,我们建议您使用 Google 登录功能,用于对玩家进行身份验证并 安全地将玩家的身份信息传递给后端服务器。这还可以 安全地检索玩家的身份和其他数据 在通过设备时可能会被篡改
在这种情况下,您的游戏会像平常一样提示玩家登录 Google Play 游戏服务。当
GoogleSignInAccount
对象包含一个特殊的一次性代码
(称为服务器授权代码)。然后在服务器上
OAuth 2.0 令牌的服务器授权代码,服务器可以使用该代码调用
Google Play Games Services API。
如需获得有关在游戏中添加登录机制的其他指导,请参阅 在 Android 游戏中登录。
要查看展示如何使用 Google 登录功能对玩家进行身份验证的详细代码示例,请参阅
GitHub 上的 clientserverskeleton
示例。
如需离线访问,必须执行以下步骤:
- 在 Google Play 管理中心内:为游戏服务器创建凭据。通过 凭据的 OAuth 客户端类型为“web”。
- 在 Android 应用中:在登录过程中,请求获取服务器凭据的服务器授权代码,并将其传递给您的服务器。
- 在游戏服务器上:使用服务器授权代码获取 OAuth 访问 令牌,然后使用该令牌来调用 Play 游戏服务 REST API。
准备工作
您需要先将游戏添加到游戏中,然后才能将 Google 登录功能集成到 Google Play 管理中心,如 设置 Google Play 游戏服务。
为您的游戏创建关联的服务器端 Web 应用
Google Play 游戏服务未针对网络游戏提供后端支持。但该服务为 Android 游戏的服务器提供了后端服务器支持。
如果您希望在服务器端应用中使用适用于 Google Play 游戏服务的 REST API,请按以下步骤操作:
- 请在以下位置的关联的应用部分中为您的游戏创建关联的 Web 应用
Google Play 管理中心。请注意,
launch_url
不用于此流程,可以留空。 - 如需获取应用的凭据信息,请按以下步骤操作:
<ph type="x-smartling-placeholder">
- </ph>
- 在 Google Play 管理中心内,在您的游戏中,点击游戏详情。
- 向下滚动到 API 控制台项目部分,然后点击链接 添加到 API 控制台项目
- 在 API 和服务 >Google API 中的“Credentials”屏幕
控制台,为您的 Web 应用下载
client_secret.json
文件 并将其保存到服务器可访问的位置。录制客户端视频 凭据 ID,供稍后参考。
- 重启服务器端应用,以便可以接受来自 游戏的客户端应用
在客户端上执行登录
GoogleSignInClient
类是用于检索当前
登录,并在他们之前未在您的应用中登录过
设备。
如需创建登录客户端,请按以下步骤操作:
- 通过
GoogleSignInOptions
对象创建登录客户端。在GoogleSignInOptions.Builder
以配置登录,您必须指定GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN
。 - 您还必须指定您的游戏需要身份验证
(通过调用
GoogleSignInOptions.Builder.requestServerAuthCode()
方法,并使用服务器的客户端 ID 作为 参数。稍后,您需要按照说明在后端服务器上检索访问令牌的授权代码 获取服务器授权代码部分。 - 调用
GoogleSignIn.getClient()
方法并传入您之前配置的选项。如果调用 成功后,Google Sign-In API 会返回一个GoogleSignInClient
实例。 - 获取
GoogleSignInClient
实例后,你就可以继续让玩家登录了 从 Activity 的onResume()
中静默运行,如 执行静默登录。
示例如下:
private static final int RC_SIGN_IN = 9001; private GoogleSignInClient mGoogleSignInClient; private void startSignInForAuthCode() { // Client ID for your backend server. String webClientId = getString(R.string.webclient_id); GoogleSignInOptions signInOption = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN) .requestServerAuthCode(webClientId) .build(); GoogleSignInClient signInClient = GoogleSignIn.getClient(this, signInOption); Intent intent = signInClient.getSignInIntent(); startActivityForResult(intent, RC_SIGN_IN); }
获取服务器授权代码
如需检索您的游戏可用于获取后端服务器上的访问令牌的服务器授权代码,请按以下步骤操作:
打电话给getServerAuthCode()
针对 GoogleSignInAccount
的方法
对象。
示例如下:
// Auth code to send to backend server. private String mServerAuthCode; @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == RC_SIGN_IN) { GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data); if (result.isSuccess()) { mServerAuthCode = result.getSignInAccount().getServerAuthCode(); } else { String message = result.getStatus().getStatusMessage(); if (message == null || message.isEmpty()) { message = getString(R.string.signin_other_error); } new AlertDialog.Builder(this).setMessage(message) .setNeutralButton(android.R.string.ok, null).show(); } } }
用服务器授权代码换取服务器上的访问令牌
将服务器授权代码发送到您的后端服务器,以交换访问和刷新令牌。 使用访问令牌代表玩家调用 Google Play 游戏服务 API;您也可以选择使用 存储刷新令牌,以便在访问令牌到期时获取新的访问令牌。
以下代码段展示了如何在 Java 代码中实现服务器端代码, 编程语言,用于将服务器授权代码换成访问令牌。时间是 使用 clientserverskeleton 示例应用:
/**
* Exchanges the authcode for an access token credential. The credential
* is the associated with the given player.
*
* @param authCode - the non-null authcode passed from the client.
* @param player - the player object which the given authcode is
* associated with.
* @return the HTTP response code indicating the outcome of the exchange.
*/
private int exchangeAuthCode(String authCode, Player player) {
try {
// The client_secret.json file is downloaded from the Google API
// console. This is used to identify your web application. The
// contents of this file should not be shared.
//
File secretFile = new File("client_secret.json");
// If we don't have the file, we can't access any APIs, so return
// an error.
if (!secretFile.exists()) {
log("Secret file : " + secretFile
.getAbsolutePath() + " does not exist!");
return HttpServletResponse.SC_FORBIDDEN;
}
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(
JacksonFactory.getDefaultInstance(), new
FileReader(secretFile));
// Extract the application id of the game from the client id.
String applicationId = extractApplicationId(clientSecrets
.getDetails().getClientId());
GoogleTokenResponse tokenResponse =
new GoogleAuthorizationCodeTokenRequest(
HTTPTransport,
JacksonFactory.getDefaultInstance(),
"https://oauth2.googleapis.com/token",
clientSecrets.getDetails().getClientId(),
clientSecrets.getDetails().getClientSecret(),
authCode,
"")
.execute();
log("hasRefresh == " + (tokenResponse.getRefreshToken() != null));
log("Exchanging authCode: " + authCode + " for token");
Credential credential = new Credential
.Builder(BearerToken.authorizationHeaderAccessMethod())
.setJsonFactory(JacksonFactory.getDefaultInstance())
.setTransport(HTTPTransport)
.setTokenServerEncodedUrl("https://www.googleapis.com/oauth2/v4/token")
.setClientAuthentication(new HttpExecuteInterceptor() {
@Override
public void intercept(HttpRequest request)
throws IOException {
}
})
.build()
.setFromTokenResponse(tokenResponse);
player.setCredential(credential);
// Now that we have a credential, we can access the Games API.
PlayGamesAPI api = new PlayGamesAPI(player, applicationId,
HTTPTransport, JacksonFactory.getDefaultInstance());
// Call the verify method, which checks that the access token has
// access to the Games API, and that the player id used by the
// client matches the playerId associated with the accessToken.
boolean ok = api.verifyPlayer();
// Call a Games API on the server.
if (ok) {
ok = api.updatePlayerInfo();
if (ok) {
// persist the player.
savePlayer(api.getPlayer());
}
}
return ok ? HttpServletResponse.SC_OK :
HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
} catch (IOException e) {
e.printStackTrace();
}
return HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
}
如需详细了解如何以已登录玩家的身份从后端服务器访问 Google API, 请参阅启用服务器端访问。
处理玩家退出账号
如需让玩家退出游戏,请对 GoogleSignInClient
调用 signOut()
方法。对于
代码段示例,请参阅
使玩家退出账号。
从服务器调用 REST API
如需了解以下内容,请参阅适用于 Google Play 游戏服务的 REST API 可用 API 调用的完整说明。
以下这些 REST API 调用示例可能对您有所帮助:
玩家
- 想要获取已登录玩家的 ID 和个人资料数据?调用 Players.get
'me'
作为 ID。
好友
请务必查看好友指南,其中详细介绍了好友功能。
- 想要检索玩家的好友列表?使用以下参数调用 Players.list:
'friends_all'
作为collection
。 - 检查您是否可以访问好友列表?为
me
调用 Players.get; 查看响应中的profileSettings.friendsListVisibility
字段。
成就
请务必查看成就指南,其中解释了成就 。
- 想要获取当前成就列表?您可以调用 AchievementDefinitions.list。
- 然后结合调用 Achievements.list 的结果,便可了解玩家解锁了哪些成就。
- 玩家是否赢得了成就?不妨使用 Achievements.unlock 解锁成就!
- 玩家是否取得了部分成就?使用 Achievements.increment 可获得以下功能: 报告进度(并查看玩家是否已解锁)。
- 您是否正在调试一个尚未发布为正式版的游戏?尝试拨打电话 Management API 中的 Achievements.reset 或 Achievements.resetAll 将成就重置为原始状态。
排行榜
请务必查看排行榜指南,其中对排行榜进行了更详细的说明。
- 是否想获取游戏中所有记分板的列表?可以调用 Leaderboards.list。
- 玩家结束了游戏吗?您可以将他们的得分提交到 Scores.submit,并了解 这是一个新的高分。
- 想要显示排行榜?从 Scores.list 获取数据并显示给用户。
- 使用 Scores.listWindow 查找一系列接近用户最高得分的得分。
- 获取有关玩家在特定排行榜(例如,如果 名列前 12%),请调用 Scores.get。
- 您是否正在调试一个游戏?尝试从管理界面调用 Scores.reset 用于重置该玩家在特定排行榜中的所有得分的 API