輕觸一下即可建立新帳戶

如果您支援使用 Google 帳戶登入,可以使用 One Tap 登入用戶端,為使用者提供流暢的帳戶建立體驗,完全不會中斷應用程式的使用。

一鍵註冊 UI

顯示一鍵登入 UI 時,系統會提示使用者透過裝置上的其中一個 Google 帳戶,在您的應用程式建立新帳戶。如果使用者選擇繼續,您會取得含有基本個人資料資訊 (姓名、個人資料相片和已驗證的電子郵件地址) 的 ID 權杖,可用於建立新帳戶。

導入一鍵建立帳戶功能分為兩個部分:

  • 將一鍵登入用戶端整合至應用程式,如本頁所述。這與使用 One Tap 登入功能大致相同,但設定上有些差異。
  • 在後端新增功能,以便透過 Google ID 權杖建立使用者帳戶,詳情請參閱「在後端使用 ID 權杖」。

哪些情況適合使用 One Tap 註冊功能?

在登入後可啟用新功能的環境中,向使用者提供 One Tap 註冊功能,最能發揮效果。首先,請嘗試使用已儲存的憑證讓使用者登入。如果找不到已儲存的憑證,請為使用者建立新帳戶。

事前準備

按照「開始使用 One Tap 登入」一文所述,設定 Google Cloud 控制台專案和 Android 專案。

1. 設定一鍵登入用戶端

如要設定 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 UI 取消情形

您應追蹤使用者是否已關閉提示或輕觸提示以外的地方,拒絕使用一鍵註冊功能。舉例來說,您可以使用 Activity 的布林值屬性。(請參閱下方的「停止顯示一鍵登入 UI」)。

3. 顯示 One Tap 註冊 UI

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

  • 成功事件監聽器:如果使用者在裝置上設定一或多個 Google 帳戶,一鍵登入用戶端會呼叫成功事件監聽器。在成功事件監聽器中,從 Task 結果取得待處理意圖,並傳遞至 startIntentSenderForResult(),啟動一鍵快捷 UI。
  • 失敗事件監聽器:如果使用者在裝置上沒有任何 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() 方法,將使用者對 One Tap 註冊提示的回應回報給應用程式。如果使用者選擇建立帳戶,結果會是 Google ID 權杖。如果使用者關閉一鍵登入 UI 或輕觸 UI 外部,拒絕註冊,結果會傳回 RESULT_CANCELED 程式碼。應用程式必須能處理這兩種情況。

使用 Google ID 權杖建立帳戶

如果使用者選擇使用 Google 帳戶註冊,您可以將 onActivityResult() 的意圖資料傳遞至一鍵登入用戶端的 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() 的呼叫會擲回 ApiException,並傳回 CommonStatusCodes.CANCELED 狀態碼。發生這種情況時,請暫時停止顯示 One Tap 登入 UI,以免使用者因重複提示而感到困擾。以下範例透過在 Activity 上設定屬性來達成此目的,該屬性用於判斷是否要向使用者提供 One Tap 登入功能;不過,您也可以將值儲存至 SharedPreferences 或使用其他方法。

請務必自行設定 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 權杖,其中包含一些基本個人資料資訊:使用者的電子郵件地址、全名和個人資料相片網址。對許多應用程式來說,這項資訊足以讓您在後端驗證使用者並建立新帳戶。

如果您需要額外資訊才能完成帳戶建立程序 (例如使用者的出生日期),請向使用者顯示註冊詳細資料流程,要求提供這項額外資訊。接著,將資訊傳送至後端,完成帳戶建立程序。