輕觸一下即可建立新帳戶

如果支援使用 Google 帳戶登入,則您可以使用 One Tap 登入用戶端,為使用者提供順暢的帳戶建立體驗,讓他們不必離開應用程式畫面。

輕觸一下的註冊 UI

您顯示 One Tap UI 時,系統會提示使用者在裝置上使用其中一個 Google 帳戶建立新帳戶。如果使用者選擇繼續,您會收到包含基本個人資料 (姓名、個人資料相片和已驗證的電子郵件地址) 的 ID 符記,您可以使用這些資訊建立新帳戶。

實作 One Tap 帳戶建立程序包含兩個部分:

  • 將 One Tap 用戶端整合至應用程式,詳情請參閱本頁說明。 這與使用 One Tap 登入行為大致相同,但設定有些許差異。
  • 在後端中新增可透過 Google ID 憑證建立使用者帳戶的功能,詳情請參閱在後端使用 ID 憑證

哪裡適合使用 One Tap 註冊?

如要向使用者提供 One Tap 註冊,最具影響力的位置就是登入會啟用新功能。首先,請嘗試使用已儲存的憑證登入使用者。如果找不到儲存的憑證,請提供為使用者建立新帳戶。

事前準備

按照「開始使用 One Tap 登入」一文的說明,設定 Google API 控制台專案和 Android 專案。

1. 設定 One Tap 用戶端

如要設定 One Tap 用戶端以建立帳戶,請按照下列步驟操作:

  • 不啟用密碼憑證要求。(只須使用權杖式驗證,輕觸一下即可註冊)。
  • 使用 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. 追蹤 One Tap 使用者介面取消情形

您應關閉提示或輕觸其他位置,藉此追蹤使用者是否已拒絕使用 One Tap 註冊。這可以像 Activity 的布林值屬性一樣簡單。(請參閱下方的「停止顯示 One Tap UI」一節)。

3. 顯示 One Tap 註冊 UI

如果使用者沒有拒絕使用 One Tap 建立新帳戶,請呼叫用戶端物件的 beginSignIn() 方法,然後將事件監聽器附加至其傳回的 Task。應用程式通常會在 One Tap 登入要求找不到任何已儲存的憑證時執行這個步驟,也就是在登入登入要求的失敗監聽器中。

如果使用者在裝置上設定了一或多個 Google 帳戶,One Tap 用戶端會呼叫成功的事件監聽器。在成功的事件監聽器中,從 Task 結果取得待處理意圖,並將其傳遞至 startIntentSenderForResult(),即可啟動 One Tap UI。

如果使用者在裝置上沒有任何 Google 帳戶,One Tap 用戶端會呼叫失敗事件監聽器。在這種情況下,您無須採取任何行動。只需繼續顯示應用程式已登出的體驗,使用者就可以透過一般的帳戶建立流程註冊。

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. 處理使用者的回應

使用者對 One Tap 註冊提示的回應,系統會使用活動的 onActivityResult() 方法向您的應用程式回報。如果使用者選擇建立帳戶,結果會是 Google ID 權杖。如果使用者拒絕註冊,無論是關閉 One Tap UI 或輕觸其他位置,結果都會傳回 RESULT_CANCELED 代碼。您的應用程式必須處理這兩種可能性。

使用 Google ID 權杖建立帳戶

如果使用者選擇註冊 Google 帳戶,您可以將意圖資料從 onActivityResult() 傳遞至 One Tap 用戶端的 getSignInCredentialFromIntent() 方法,藉此取得使用者的 ID 權杖。憑證將包含非空值的 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) {
                    // ...
            }
        }
    }
    // ...
}

停止顯示 One Tap UI

如果使用者拒絕登入,對 getSignInCredentialFromIntent() 的呼叫將會擲回含有 CommonStatusCodes.CANCELED 狀態碼的 ApiException。在此情況下,您應暫時停止顯示 One Tap 登入 UI,以免重複提示使用者感到困擾。下列範例配合在 Activity 上設定屬性,用來判斷是否要為使用者提供 One Tap 登入。不過,您也可以將值儲存至 SharedPreferences 或使用其他方法。

請務必自行設定 One Tap 登入提示的頻率限制。 如果您沒有這麼做,且使用者連續取消多則提示,則 One Tap 用戶端接下來的 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})")
                        }
                    }
                }
            }
        }
    }
    // ...
}

後續步驟

使用者完成 One Tap 註冊流程後,您會收到 Google ID 權杖,其中包含一些基本個人資料資訊:使用者的電子郵件地址、全名和個人資料相片網址。對於許多應用程式而言,這些資訊足以讓您在後端驗證使用者及建立新帳戶。

如果系統需要其他資訊才能完成帳戶建立程序 (例如使用者的出生日期),請在註冊詳細資料流程中向使用者顯示,以便您索取這項額外資訊。然後,將其傳送至後端,以便完成帳戶建立作業。