Tạo tài khoản mới chỉ bằng một lần nhấn

Nếu hỗ trợ Đăng nhập bằng Google, bạn có thể sử dụng ứng dụng Đăng nhập bằng một lần chạm để mang đến cho người dùng trải nghiệm tạo tài khoản liền mạch mà không bao giờ đưa họ ra khỏi bối cảnh ứng dụng của bạn.

Giao diện người dùng đăng ký bằng một lần nhấn

Khi bạn hiển thị giao diện người dùng Một lần nhấn, người dùng sẽ được nhắc tạo tài khoản mới bằng ứng dụng của bạn thông qua một trong các Tài khoản Google trên thiết bị của họ. Nếu người dùng chọn tiếp tục, bạn sẽ nhận được một mã nhận dạng có thông tin cơ bản trong hồ sơ (tên, ảnh hồ sơ và địa chỉ email đã xác minh của họ). Bạn có thể dùng mã này để tạo tài khoản mới.

Việc triển khai tính năng tạo tài khoản bằng Một lần nhấn bao gồm 2 phần:

  • Tích hợp ứng dụng Một lần nhấn vào ứng dụng của bạn, như được mô tả trên trang này. Điều này gần giống với việc sử dụng tính năng Đăng nhập bằng một lần chạm, nhưng có một số điểm khác biệt trong cấu hình.
  • Thêm vào phần phụ trợ của bạn khả năng tạo tài khoản người dùng từ mã thông báo nhận dạng của Google, được thảo luận trong phần Sử dụng mã thông báo nhận dạng trên phần phụ trợ.

Tôi nên sử dụng tính năng Đăng ký bằng một lần chạm ở đâu?

Nơi có tác động lớn nhất để cung cấp tính năng Đăng ký bằng một lần chạm cho người dùng là trong bối cảnh mà việc đăng nhập sẽ cho phép họ sử dụng các tính năng mới. Trước tiên, hãy thử đăng nhập cho người dùng bằng thông tin đăng nhập đã lưu. Nếu không tìm thấy thông tin đăng nhập đã lưu, hãy đề nghị tạo một tài khoản mới cho người dùng.

Trước khi bắt đầu

Thiết lập dự án Bảng điều khiển API Google và dự án Android như mô tả trong phần Bắt đầu sử dụng tính năng đăng nhập bằng một lần chạm.

1. Định cấu hình ứng dụng Một lần nhấn

Để định cấu hình ứng dụng Một lần nhấn để tạo tài khoản, hãy làm như sau:

  • Không bật yêu cầu thông tin đăng nhập bằng mật khẩu. (Bạn chỉ có thể đăng ký bằng một lần nhấn khi xác thực dựa trên mã thông báo.)
  • Bật yêu cầu mã thông báo nhận dạng của Google bằng cách sử dụng setGoogleIdTokenRequestOptions() và các chế độ cài đặt sau:

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. Theo dõi việc huỷ giao diện người dùng Một lần nhấn

Bạn nên theo dõi xem người dùng đã từ chối sử dụng tính năng đăng ký bằng Một lần nhấn hay chưa bằng cách đóng lời nhắc hoặc nhấn vào bên ngoài lời nhắc. Điều này có thể đơn giản như một thuộc tính boolean của Hoạt động. (Xem phần Ngừng hiển thị giao diện người dùng Một lần nhấn bên dưới.)

3. Hiển thị giao diện người dùng Đăng ký bằng một lần chạm

Nếu người dùng chưa từ chối sử dụng tính năng Đăng nhập bằng một lần nhấn để tạo tài khoản mới, hãy gọi phương thức beginSignIn() của đối tượng ứng dụng và đính kèm các trình nghe vào Task mà phương thức này trả về. Các ứng dụng thường thực hiện bước này khi yêu cầu đăng nhập bằng một lần chạm không tìm thấy thông tin đăng nhập đã lưu nào, tức là trong trình nghe lỗi của yêu cầu đăng nhập.

Ứng dụng Một lần nhấn sẽ gọi trình nghe thành công nếu người dùng đã thiết lập một hoặc nhiều Tài khoản Google trên thiết bị. Trong trình nghe thành công, hãy lấy ý định đang chờ xử lý từ kết quả Task và truyền ý định đó đến startIntentSenderForResult() để bắt đầu giao diện người dùng Một lần nhấn.

Nếu người dùng không có Tài khoản Google nào trên thiết bị, thì ứng dụng Một lần nhấn sẽ gọi trình nghe lỗi. Trong trường hợp này, bạn không cần làm gì cả: bạn chỉ cần tiếp tục trình bày trải nghiệm khi người dùng đã đăng xuất khỏi ứng dụng và người dùng có thể đăng ký bằng quy trình tạo tài khoản thông thường của bạn.

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. Xử lý phản hồi của người dùng

Phản hồi của người dùng đối với lời nhắc Đăng ký bằng một lần chạm sẽ được báo cáo cho ứng dụng của bạn bằng phương thức onActivityResult() của Hoạt động. Nếu người dùng chọn tạo tài khoản, kết quả sẽ là mã thông báo nhận dạng của Google. Nếu người dùng từ chối đăng ký bằng cách đóng giao diện người dùng Một lần nhấn hoặc nhấn vào bên ngoài giao diện này, thì kết quả sẽ trả về mã RESULT_CANCELED. Ứng dụng của bạn cần xử lý cả hai trường hợp này.

Tạo tài khoản bằng mã thông báo nhận dạng của Google

Nếu người dùng chọn đăng ký bằng Tài khoản Google, bạn có thể nhận mã thông báo nhận dạng cho người dùng bằng cách truyền dữ liệu ý định từ onActivityResult() đến phương thức getSignInCredentialFromIntent() của ứng dụng Một lần nhấn. Thông tin đăng nhập sẽ có một thuộc tính googleIdToken không rỗng.

Sử dụng mã thông báo nhận dạng để tạo một tài khoản trên phần phụ trợ của bạn (xem phần Xác thực bằng phần phụ trợ bằng mã thông báo nhận dạng) và đăng nhập cho người dùng.

Thông tin đăng nhập này cũng chứa mọi thông tin bổ sung mà bạn đã yêu cầu, chẳng hạn như số điện thoại đã xác minh của tài khoản (nếu có).

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) {
                    // ...
            }
        }
    }
    // ...
}

Ngừng hiển thị giao diện người dùng Một lần nhấn

Nếu người dùng từ chối đăng nhập, lệnh gọi đến getSignInCredentialFromIntent() sẽ gửi một ApiException có mã trạng thái CommonStatusCodes.CANCELED. Khi điều này xảy ra, bạn nên tạm thời ngừng hiển thị giao diện người dùng Đăng nhập bằng một lần chạm để không làm phiền người dùng bằng các lời nhắc lặp lại. Ví dụ sau đây thực hiện việc này bằng cách đặt một thuộc tính trên Hoạt động mà ứng dụng dùng để xác định xem có nên cung cấp tính năng Đăng nhập bằng một lần chạm cho người dùng hay không; tuy nhiên, bạn cũng có thể lưu một giá trị vào SharedPreferences hoặc sử dụng một phương thức khác.

Điều quan trọng là bạn phải triển khai tính năng giới hạn tốc độ của riêng mình cho lời nhắc Đăng nhập bằng một lần chạm. Nếu bạn không làm như vậy và người dùng huỷ nhiều lời nhắc liên tiếp, thì ứng dụng Một lần nhấn sẽ không nhắc người dùng trong 24 giờ tiếp theo.

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})")
                        }
                    }
                }
            }
        }
    }
    // ...
}

Các bước tiếp theo

Khi người dùng hoàn tất quy trình đăng ký bằng tính năng Đăng ký bằng một lần chạm, bạn sẽ nhận được mã thông báo nhận dạng Google, trong đó có một số thông tin cơ bản trong hồ sơ: địa chỉ email, tên đầy đủ và URL ảnh hồ sơ của người dùng. Đối với nhiều ứng dụng, thông tin này là đủ để bạn xác thực người dùng trên phần phụ trợ và tạo một tài khoản mới.

Nếu bạn cần thêm thông tin để hoàn tất quá trình tạo tài khoản (ví dụ: ngày sinh của người dùng), hãy cung cấp cho người dùng một quy trình chi tiết đăng ký, trong đó bạn yêu cầu thông tin bổ sung này. Sau đó, hãy gửi thông tin đó đến phần phụ trợ của bạn để hoàn tất quá trình tạo tài khoản.