Android 游戏中的登录功能

若要使用 Google Play 游戏服务功能,您的游戏需要提供 登录玩家的账号。如果玩家未经过身份验证,您的游戏可能会遇到错误 。本文档介绍了如何在游戏中实现无缝登录体验。

实现玩家登录

GoogleSignInClient 类是用于检索当前 登录,并在他们之前未在您的应用中登录过 设备。

如需创建登录客户端,请按以下步骤操作:

  1. 通过 GoogleSignInOptions 对象,如以下代码段所示。在 GoogleSignInOptions.Builder 您必须指定 GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN

    GoogleSignInOptions signInOptions = GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN;
  2. 如果您想使用 SnapshotsClient, 然后将.requestScopes(Games.SCOPE_GAMES_SNAPSHOTS)添加到您的 GoogleSignInOptions.Builder 如以下代码段所示:

    GoogleSignInOptions  signInOptions =
        new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
            .requestScopes(Games.SCOPE_GAMES_SNAPSHOTS)
            .build();
  3. 调用 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() 方法。

如需静默执行登录,请按以下步骤操作:

  1. GoogleSignInClient 调用 silentSignIn() 方法以启动静默登录流程。 此调用会返回一个 Task<GoogleSignInAccount> 对象,该对象包含 GoogleSignInAccount(如果存在以下情况) 静默登录成功了
  2. 通过替换 OnCompleteListener

以下代码段展示了您的应用如何执行静默登录:

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 回调。

如需以交互方式执行登录,请按以下步骤操作:

  1. 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);
    }
  2. onActivityResult()中 回调,处理返回的 intent 的结果。

    • 如果登录结果成功,则获取 来自 GoogleSignInResultGoogleSignInAccount 对象。
    • 如果登录结果未成功,您应处理登录错误(例如, 在提醒中显示错误消息)。 以下代码段展示了您的应用如何处理玩家登录结果:
    @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), 您可以按照以下步骤获取这些信息。

  1. 通过调用 getPlayersClient() 方法并传入一个 PlayersClient 对象 GoogleSignInAccount 作为参数传递。
  2. 使用 PlayersClient 方法异步加载 Player 对象,该对象包含玩家的信息。例如,您可以调用 getCurrentPlayer() 加载当前已登录的播放器。如果任务返回一个 带有状态代码的 ApiExceptionSIGN_IN_REQUIRED 个, 则表示需要对玩家重新进行身份验证。为此,请调用 GoogleSignInClient.getSignInIntent() 以便以交互方式登录播放器
  3. 如果任务成功返回了 Player 对象,您可以调用 Player 对象,用于检索特定玩家详细信息(例如, getDisplayName()getPlayerId()

提供登录按钮

如需在游戏中提供标准的 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.
        }
      });
}