点按一下即可创建新帐号

如果您支持使用 Google 帐号登录,则还可以使用一键登录客户端,为用户提供顺畅的帐号创建体验,使他们永远不会离开您的应用环境。

一键注册界面

当您显示一键式界面时,系统会提示用户使用设备上的一个 Google 帐号为您的应用创建新帐号。如果用户选择继续,您会收到一个包含基本个人资料信息的 ID 令牌(用户的姓名、个人资料照片和经过验证的电子邮件地址),您可以使用该令牌创建新帐号。

实现一键快捷帐号创建功能包含两个部分:

  • 将一键式客户端集成到您的应用中,如本页所述。 这与使用一键登录大致相同,但在配置方面存在一些差异。
  • 在后端添加通过 Google ID 令牌创建用户帐号的功能,这一功能在在后端使用 ID 令牌中讨论。

我应该在哪里使用一键注册?

要向用户提供一键注册功能,影响最大的位置是登录将启用新功能。首先,请尝试使用保存的凭据让用户登录。如果未找到已保存的凭据,请提议为用户创建一个新帐号。

准备工作

按照一键登录使用入门中的说明设置您的 Google API 控制台项目和 Android 项目。

1. 配置一键采纳客户端

若要配置一键式客户端以创建帐号,请执行以下操作:

  • 不启用密码凭据请求。(只有基于令牌的身份验证支持一键注册。)
  • 使用 setGoogleIdTokenRequestOptions() 和以下设置启用 Google ID 令牌请求:

Java

public class YourActivity extends AppCompatActivity {

  // ...

  private SignInClient oneTapClient;
  private BeginSignInRequest signUpRequest;

  @Override
  public void onCreate(@Nullable Bundle savedInstanceState,
                       @Nullable PersistableBundle persistentState) {
      super.onCreate(savedInstanceState, persistentState);

      oneTapClient = Identity.getSignInClient(this);
      signUpRequest = BeginSignInRequest.builder()
              .setGoogleIdTokenRequestOptions(GoogleIdTokenRequestOptions.builder()
                      .setSupported(true)
                      // Your server's client ID, not your Android client ID.
                      .setServerClientId(getString(R.string.your_web_client_id))
                      // Show all accounts on the device.
                      .setFilterByAuthorizedAccounts(false)
                      .build())
              .build();

      // ...
  }
}

Kotlin

class YourActivity : AppCompatActivity() {
    // ...

    private lateinit var oneTapClient: SignInClient
    private lateinit var signUpRequest: BeginSignInRequest

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        oneTapClient = Identity.getSignInClient(this)
        signUpRequest = BeginSignInRequest.builder()
            .setGoogleIdTokenRequestOptions(
                BeginSignInRequest.GoogleIdTokenRequestOptions.builder()
                    .setSupported(true)
                    // Your server's client ID, not your Android client ID.
                    .setServerClientId(getString(R.string.your_web_client_id))
                    // Show all accounts on the device.
                    .setFilterByAuthorizedAccounts(false)
                    .build())
            .build()
        // ...
    }
    // ...
}

2. 跟踪一键式界面取消操作

您应关闭提示或在提示之外点按一下,以跟踪用户是否已拒绝使用一键注册。这可以很简单,比如 Activity 的布尔值属性。(请参阅下文的停止显示一键式界面)。

3. 显示一键注册界面

如果用户尚未拒绝使用一键快捷功能创建新帐号,请调用客户端对象的 beginSignIn() 方法,并将监听器附加到其返回的 Task。应用通常在一键登录请求未找到任何已保存的凭据(即登录请求的失败监听器中)时执行此步骤。

如果用户在设备上设置了一个或多个 Google 帐号,一键客户端将会调用成功监听器。在成功监听器中,从 Task 结果中获取待定 intent 并将其传递给 startIntentSenderForResult(),以启动一键快捷界面。

如果用户在设备上没有任何 Google 帐号,一键式客户端将调用失败监听器。在这种情况下,无需执行任何操作:您只需继续呈现应用的未登录体验,用户就可以使用您的常规帐号创建流程进行注册。

Java

oneTapClient.beginSignIn(signUpRequest)
        .addOnSuccessListener(this, new OnSuccessListener<BeginSignInResult>() {
            @Override
            public void onSuccess(BeginSignInResult result) {
                try {
                    startIntentSenderForResult(
                            result.getPendingIntent().getIntentSender(), REQ_ONE_TAP,
                            null, 0, 0, 0);
                } catch (IntentSender.SendIntentException e) {
                    Log.e(TAG, "Couldn't start One Tap UI: " + e.getLocalizedMessage());
                }
            }
        })
        .addOnFailureListener(this, new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                // No Google Accounts found. Just continue presenting the signed-out UI.
                Log.d(TAG, e.getLocalizedMessage());
            }
        });

Kotlin

oneTapClient.beginSignIn(signUpRequest)
    .addOnSuccessListener(this) { result ->
        try {
            startIntentSenderForResult(
                result.pendingIntent.intentSender, REQ_ONE_TAP,
                null, 0, 0, 0)
        } catch (e: IntentSender.SendIntentException) {
            Log.e(TAG, "Couldn't start One Tap UI: ${e.localizedMessage}")
        }
    }
    .addOnFailureListener(this) { e ->
        // No Google Accounts found. Just continue presenting the signed-out UI.
        Log.d(TAG, e.localizedMessage)
    }

4. 处理用户的响应

系统将使用 activity 的 onActivityResult() 方法将用户对一键注册提示的响应报告给您的应用。如果用户选择创建帐号,结果将是一个 Google ID 令牌。如果用户拒绝注册(通过关闭一键式界面或点按该界面以外的区域),系统将返回代码 RESULT_CANCELED 的结果。您的应用需要同时处理这两种可能性。

使用 Google ID 令牌创建账号

如果用户选择使用 Google 帐号进行注册,您可以将 intent 数据从 onActivityResult() 传递到一键客户端的 getSignInCredentialFromIntent() 方法,从而为用户获取 ID 令牌。凭据将具有非 null googleIdToken 属性。

使用 ID 令牌在后端创建帐号(请参阅使用 ID 令牌进行后端身份验证)并让用户登录。

该凭据还包含您请求的任何其他详细信息,例如帐号的已验证电话号码(如果有)。

Java

public class YourActivity extends AppCompatActivity {

  // ...
  private static final int REQ_ONE_TAP = 2;  // Can be any integer unique to the Activity.
  private boolean showOneTapUI = true;
  // ...

  @Override
  protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
      super.onActivityResult(requestCode, resultCode, data);

      switch (requestCode) {
          case REQ_ONE_TAP:
              try {
                  SignInCredential credential = oneTapClient.getSignInCredentialFromIntent(data);
                  String idToken = credential.getGoogleIdToken();
                  if (idToken !=  null) {
                      // Got an ID token from Google. Use it to authenticate
                      // with your backend.
                      Log.d(TAG, "Got ID token.");
                  }
              } catch (ApiException e) {
                  // ...
              }
              break;
      }
  }
}

Kotlin

class YourActivity : AppCompatActivity() {

    // ...
    private val REQ_ONE_TAP = 2  // Can be any integer unique to the Activity
    private var showOneTapUI = true
    // ...

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        when (requestCode) {
             REQ_ONE_TAP -> {
                try {
                    val credential = oneTapClient.getSignInCredentialFromIntent(data)
                    val idToken = credential.googleIdToken
                    when {
                        idToken != null -> {
                            // Got an ID token from Google. Use it to authenticate
                            // with your backend.
                            Log.d(TAG, "Got ID token.")
                        }
                        else -> {
                            // Shouldn't happen.
                            Log.d(TAG, "No ID token!")
                        }
                    }
                } catch (e: ApiException) {
                    // ...
            }
        }
    }
    // ...
}

停止显示一键式界面

如果用户拒绝登录,调用 getSignInCredentialFromIntent() 将抛出 ApiException 以及 CommonStatusCodes.CANCELED 状态代码。发生这种情况时,您应该暂时停止显示一键登录界面,以免重复提示给用户造成困扰。以下示例通过在 Activity 上设置属性来实现这一点,该属性用于确定是否为用户提供一键登录功能;不过,您也可以将值保存到 SharedPreferences 或使用其他方法。

请务必实现您自己的一键登录提示速率限制。如果您没有这样做,并且用户连续取消了多次提示,那么一键式客户端在接下来的 24 小时内将不会提示用户。

Java

public class YourActivity extends AppCompatActivity {

  // ...
  private static final int REQ_ONE_TAP = 2;  // Can be any integer unique to the Activity.
  private boolean showOneTapUI = true;
  // ...

  @Override
  protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
      super.onActivityResult(requestCode, resultCode, data);

      switch (requestCode) {
          case REQ_ONE_TAP:
              try {
                  // ...
              } catch (ApiException e) {
                  switch (e.getStatusCode()) {
                      case CommonStatusCodes.CANCELED:
                          Log.d(TAG, "One-tap dialog was closed.");
                          // Don't re-prompt the user.
                          showOneTapUI = false;
                          break;
                      case CommonStatusCodes.NETWORK_ERROR:
                          Log.d(TAG, "One-tap encountered a network error.");
                          // Try again or just ignore.
                          break;
                      default:
                          Log.d(TAG, "Couldn't get credential from result."
                                  + e.getLocalizedMessage());
                          break;
                  }
              }
              break;
      }
  }
}

Kotlin

class YourActivity : AppCompatActivity() {

    // ...
    private val REQ_ONE_TAP = 2  // Can be any integer unique to the Activity
    private var showOneTapUI = true
    // ...

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        when (requestCode) {
            REQ_ONE_TAP -> {
                try {
                    // ...
                } catch (e: ApiException) {
                    when (e.statusCode) {
                        CommonStatusCodes.CANCELED -> {
                            Log.d(TAG, "One-tap dialog was closed.")
                            // Don't re-prompt the user.
                            showOneTapUI = false
                        }
                        CommonStatusCodes.NETWORK_ERROR -> {
                            Log.d(TAG, "One-tap encountered a network error.")
                            // Try again or just ignore.
                        }
                        else -> {
                            Log.d(TAG, "Couldn't get credential from result." +
                                " (${e.localizedMessage})")
                        }
                    }
                }
            }
        }
    }
    // ...
}

后续步骤

当用户完成一键注册流程后,您会获得一个 Google ID 令牌,其中包含一些基本个人资料信息:用户的电子邮件地址、全名和个人资料照片网址。对于许多应用来说,这些信息足以让您在后端对用户进行身份验证,并创建新帐号。

如果您需要其他信息(例如用户的出生日期)才能完成帐号创建,请向用户显示注册详情流程,您可以在其中请求这些额外信息。然后,将其发送到您的后端以完成帐号创建。