若要使用 Google Play 游戏服务功能,您的游戏需要提供 登录玩家的账号。如果玩家未经过身份验证,您的游戏可能会遇到错误 。本文档介绍了如何在游戏中实现无缝登录体验。
实现玩家登录
GoogleSignInClient
类是用于检索当前
登录,并在他们之前未在您的应用中登录过
设备。
如需创建登录客户端,请按以下步骤操作:
通过
GoogleSignInOptions
对象,如以下代码段所示。在GoogleSignInOptions.Builder
您必须指定GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN
。GoogleSignInOptions signInOptions = GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN;
如果您想使用
SnapshotsClient
、 然后将.requestScopes(Games.SCOPE_GAMES_SNAPSHOTS)
添加到您的GoogleSignInOptions.Builder
如以下代码段所示:GoogleSignInOptions signInOptions = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN) .requestScopes(Games.SCOPE_GAMES_SNAPSHOTS) .build();
调用
GoogleSignIn.getClient()
方法并传入 您在前面的步骤中配置的选项。如果调用 请求成功后,Google Sign-In API 会返回一个GoogleSignInClient
。
检查玩家是否已登录
您可以查看某个账号是否已登录
使用 GoogleSignIn.getLastSignedInAccount()
在当前设备上使用
以及此账号是否已获得所需权限
GoogleSignIn.hasPermissions()
。
如果这两个条件都成立,即 getLastSignedInAccount()
会返回一个
非 null 值且 hasPermissions()
返回 true
,您可以放心地使用
从 getLastSignedInAccount()
返回的账号,即使设备
离线使用。
执行静默登录
您可以调用 silentSignIn()
来检索当前登录的玩家的账号,
并尝试在不显示界面的情况下让玩家登录
在其他设备上成功登录了您的应用。
silentSignIn()
方法会返回 Task<GoogleSignInAccount>
。任务完成后
请将之前声明的 GoogleSignInAccount
字段设置为执行任务的登录账号
作为结果返回,或者返回 null
,这表示没有已登录的用户。
如果静默登录尝试失败,您可以选择发送登录 intent 以显示 登录用户界面,如 执行交互式登录。
由于已登录玩家的状态可能会在 activity 不在前台运行时发生变化,因此我们
建议从 activity 的 activity 的 activity 中调用 silentSignIn()
onResume()
方法。
如需静默执行登录,请按以下步骤操作:
- 对
GoogleSignInClient
调用silentSignIn()
方法以启动静默登录流程。 此调用会返回一个Task<GoogleSignInAccount>
对象,该对象包含GoogleSignInAccount
(如果存在以下情况) 静默登录成功了 - 通过替换
OnCompleteListener
。- 如果登录任务成功,则获取
GoogleSignInAccount
调用getResult()
对象。 - 如果登录失败,您可以发送登录 intent 以启动交互式登录流程。
有关您可以使用的其他回调监听器的列表,请参阅
Tasks API 开发者指南
和
Task
API 参考文档。
- 如果登录任务成功,则获取
以下代码段展示了您的应用如何执行静默登录:
private void signInSilently() { GoogleSignInOptions signInOptions = GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN; GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(this); if (GoogleSignIn.hasPermissions(account, signInOptions.getScopeArray())) { // Already signed in. // The signed in account is stored in the 'account' variable. GoogleSignInAccount signedInAccount = account; } else { // Haven't been signed-in before. Try the silent sign-in first. GoogleSignInClient signInClient = GoogleSignIn.getClient(this, signInOptions); signInClient .silentSignIn() .addOnCompleteListener( this, new OnCompleteListener<GoogleSignInAccount>() { @Override public void onComplete(@NonNull Task<GoogleSignInAccount> task) { if (task.isSuccessful()) { // The signed in account is stored in the task's result. GoogleSignInAccount signedInAccount = task.getResult(); } else { // Player will need to sign-in explicitly using via UI. // See [sign-in best practices](http://developers.google.com/games/services/checklist) for guidance on how and when to implement Interactive Sign-in, // and [Performing Interactive Sign-in](http://developers.google.com/games/services/android/signin#performing_interactive_sign-in) for details on how to implement // Interactive Sign-in. } } }); } } @Override protected void onResume() { super.onResume(); signInSilently(); }
如果静默登录尝试失败,您可以调用
getException()
至
获取 ApiException
以及详细的状态代码状态代码 CommonStatusCodes.SIGN_IN_REQUIRED
表示玩家需要执行明确操作才能登录。在这种情况下,您的应用应
启动交互式登录流程,如下一部分所述。
执行交互式登录
为了在玩家互动过程中登录,您的应用需要启动登录 intent。如果成功
Google 登录 API 会显示一个界面,提示玩家输入其凭据
进行登录。此方法可简化应用开发,因为登录 activity 负责处理
例如需要更新 Google Play 服务或在应用的
。系统会通过
onActivityResult
回调。
如需以交互方式执行登录,请按以下步骤操作:
对
GoogleSignInClient
调用getSigninIntent()
以获取登录 intent,然后调用startActivity()
并传入该 intent。以下代码段展示了应用如何 启动交互式登录流程:private void startSignInIntent() { GoogleSignInClient signInClient = GoogleSignIn.getClient(this, GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN); Intent intent = signInClient.getSignInIntent(); startActivityForResult(intent, RC_SIGN_IN); }
在
onActivityResult()
中 回调,处理返回的 intent 的结果。- 如果登录结果成功,则获取
来自
GoogleSignInResult
的GoogleSignInAccount
对象。 - 如果登录结果未成功,您应处理登录错误(例如, 在提醒中显示错误消息)。 以下代码段展示了您的应用如何处理玩家登录结果:
@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()) { // The signed in account is stored in the result. GoogleSignInAccount signedInAccount = result.getSignInAccount(); } 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 Sign-In API 返回的 GoogleSignInAccount
未包含任何玩家
信息。如果您的游戏使用玩家信息(例如玩家的显示名称和玩家 ID),
您可以按照以下步骤获取这些信息。
- 通过调用
getPlayersClient()
方法并传入一个PlayersClient
对象GoogleSignInAccount
作为参数传递。 - 使用
PlayersClient
方法异步加载Player
对象,该对象包含玩家的信息。例如,您可以调用getCurrentPlayer()
加载当前已登录的播放器。如果任务返回一个 带有状态代码的ApiException
共SIGN_IN_REQUIRED
个, 则表示需要对玩家重新进行身份验证。为此,请调用GoogleSignInClient.getSignInIntent()
以便以交互方式登录播放器 - 如果任务成功返回了
Player
对象,您可以调用Player
对象,用于检索特定玩家详细信息(例如,getDisplayName()
或getPlayerId()
。
提供登录按钮
如需在游戏中提供标准的 Google 登录按钮,您可以使用 方法:
- 添加
com.google.android.gms.common.SignInButton
放置在主 activity 布局中或 - 根据 Google 登录品牌信息设计自定义登录按钮 指南。
当用户点击登录按钮时,您的游戏应通过发送 登录 intent,如执行交互式登录中所述。
以下代码段展示了如何在 onCreate()
中添加登录按钮
方法。
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sign_in); findViewById(R.id.sign_in_button).setOnClickListener(this); findViewById(R.id.sign_out_button).setOnClickListener(this); }
以下代码段展示了如何在用户点击 登录按钮。
@Override public void onClick(View view) { if (view.getId() == R.id.sign_in_button) { // start the asynchronous sign in flow startSignInIntent(); } else if (view.getId() == R.id.sign_out_button) { // sign out. signOut(); // show sign-in button, hide the sign-out button findViewById(R.id.sign_in_button).setVisibility(View.VISIBLE); findViewById(R.id.sign_out_button).setVisibility(View.GONE); } }
显示游戏弹出式窗口
您可以使用 GamesClient
类在游戏中显示弹出式视图。例如,您的游戏
可以显示“欢迎回来”或“已解锁成就”弹出式窗口。若要允许 Google Play 游戏服务,请执行以下操作:
要在游戏视图中启动弹出式窗口,请调用
setViewForPopups()
方法。您可以调用
setGravityForPopups()
。
退出玩家账号
可通过对 GoogleSignInClient
调用 signOut()
方法来完成退出登录。
private void signOut() { GoogleSignInClient signInClient = GoogleSignIn.getClient(this, GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN); signInClient.signOut().addOnCompleteListener(this, new OnCompleteListener<Void>() { @Override public void onComplete(@NonNull Task<Void> task) { // at this point, the user is signed out. } }); }