สร้างบัญชีใหม่ด้วยการแตะเพียงครั้งเดียว

หากรองรับการลงชื่อเข้าใช้ด้วยบัญชี Google คุณสามารถใช้ไคลเอ็นต์การลงชื่อเข้าใช้แบบแตะครั้งเดียวเพื่อให้ผู้ใช้ได้รับประสบการณ์การสร้างบัญชีที่ราบรื่นซึ่งไม่นำผู้ใช้ออกจากบริบทของแอป

UI การลงชื่อสมัครใช้ด้วย One Tap

เมื่อคุณแสดง UI แบบ One Tap ระบบจะแจ้งให้ผู้ใช้สร้างบัญชีใหม่ในแอปโดยใช้บัญชี Google บัญชีใดบัญชีหนึ่งในอุปกรณ์ หากผู้ใช้เลือกที่จะดำเนินการต่อ คุณจะได้รับโทเค็นระบุตัวตนที่มีข้อมูลโปรไฟล์พื้นฐาน ได้แก่ ชื่อ รูปโปรไฟล์ และอีเมลที่ยืนยันแล้ว ซึ่งคุณใช้สร้างบัญชีใหม่ได้

การใช้การสร้างบัญชีแบบ One Tap แบ่งออกเป็น 2 ส่วน ดังนี้

  • การผสานรวมไคลเอ็นต์ One Tap เข้ากับแอป ซึ่งอธิบายไว้ในหน้านี้ การดำเนินการนี้ส่วนใหญ่เหมือนกับการใช้ฟีเจอร์ลงชื่อเข้าใช้ด้วย One Tap แต่มีการกําหนดค่าที่แตกต่างกันเล็กน้อย
  • เพิ่มความสามารถในการสร้างบัญชีผู้ใช้จากโทเค็น Google ID ลงในแบ็กเอนด์ ซึ่งจะกล่าวถึงในการใช้โทเค็นระบุตัวตนในแบ็กเอนด์

ฉันควรใช้การลงชื่อสมัครใช้ด้วย One Tap ที่ไหน

ตําแหน่งที่จะเสนอการลงชื่อสมัครใช้ด้วย One Tap ให้แก่ผู้ใช้ได้อย่างมีประสิทธิภาพมากที่สุดคือบริบทที่การลงชื่อเข้าใช้จะเปิดใช้ฟีเจอร์ใหม่ๆ ก่อนอื่น ให้ลองลงชื่อเข้าใช้ผู้ใช้ด้วยข้อมูลเข้าสู่ระบบที่บันทึกไว้ หากไม่พบข้อมูลเข้าสู่ระบบที่บันทึกไว้ ให้เสนอสร้างบัญชีใหม่ให้ผู้ใช้

ก่อนเริ่มต้น

ตั้งค่าโปรเจ็กต์คอนโซล Google API และโปรเจ็กต์ Android ตามที่อธิบายไว้ในเริ่มต้นใช้งานฟีเจอร์ลงชื่อเข้าใช้แบบแตะครั้งเดียว

1. กำหนดค่าไคลเอ็นต์ One Tap

หากต้องการกำหนดค่าไคลเอ็นต์ One Tap สำหรับการสร้างบัญชี ให้ทำดังนี้

  • อย่าเปิดใช้คำขอข้อมูลเข้าสู่ระบบด้วยรหัสผ่าน (การลงชื่อสมัครใช้ด้วย One Tap ใช้ได้กับการตรวจสอบสิทธิ์แบบใช้โทเค็นเท่านั้น)
  • เปิดใช้คําขอโทเค็นระบุตัวตนของ Google โดยใช้ setGoogleIdTokenRequestOptions() และการตั้งค่าต่อไปนี้

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. ติดตามการยกเลิก UI ของ One Tap

คุณควรติดตามว่าผู้ใช้ปฏิเสธที่จะใช้ฟีเจอร์ลงชื่อสมัครใช้แบบ One Tap ไปแล้วหรือไม่โดยการปิดข้อความแจ้งหรือแตะนอกข้อความแจ้ง ซึ่งอาจง่ายเพียงพร็อพเพอร์ตี้บูลีนของกิจกรรม (ดูหยุดแสดง UI การแตะเพียงครั้งเดียวด้านล่าง)

3. แสดง UI การลงชื่อสมัครใช้ด้วย One Tap

หากผู้ใช้ไม่ได้ปฏิเสธที่จะใช้ One Tap เพื่อสร้างบัญชีใหม่ ให้เรียกใช้เมธอด beginSignIn() ของออบเจ็กต์ไคลเอ็นต์ และแนบ Listeners กับ Task ที่แสดงผล โดยปกติแล้ว แอปจะทำขั้นตอนนี้เมื่อคําขอลงชื่อเข้าใช้แบบแตะครั้งเดียวไม่พบข้อมูลเข้าสู่ระบบที่บันทึกไว้ ซึ่งก็คือในโปรแกรมรับฟังการดําเนินการที่ไม่สําเร็จของคําขอลงชื่อเข้าใช้

ไคลเอ็นต์ One Tap จะเรียกฟังก์ชันการฟังผลลัพธ์สำเร็จหากผู้ใช้ตั้งค่าบัญชี Google ไว้อย่างน้อย 1 บัญชีในอุปกรณ์ ใน Listener ที่ดำเนินการสำเร็จ ให้รับ Intent ที่รอดำเนินการจากผลลัพธ์ Task แล้วส่งไปยัง startIntentSenderForResult() เพื่อเริ่ม 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 หากผู้ใช้ปฏิเสธที่จะลงชื่อสมัครใช้ ไม่ว่าจะโดยการปิด UI การชำระเงินแบบไม่ต้องสัมผัสหรือแตะนอก UI ดังกล่าว ระบบจะแสดงผลลัพธ์พร้อมรหัส RESULT_CANCELED แอปของคุณต้องจัดการกับทั้ง 2 กรณี

สร้างบัญชีด้วยโทเค็น Google ID

หากผู้ใช้เลือกลงชื่อสมัครใช้ด้วยบัญชี Google คุณจะได้รับโทเค็นระบุตัวตนสำหรับผู้ใช้โดยการส่งข้อมูล Intent จาก onActivityResult() ไปยังเมธอด getSignInCredentialFromIntent() ของไคลเอ็นต์ One Tap ข้อมูลเข้าสู่ระบบจะมีพร็อพเพอร์ตี้ googleIdToken ที่ไม่ใช่ค่าว่าง

ใช้โทเค็นระบุตัวตนเพื่อสร้างบัญชีในแบ็กเอนด์ (ดูตรวจสอบสิทธิ์กับแบ็กเอนด์โดยใช้โทเค็นระบุตัวตน) และลงชื่อเข้าใช้ผู้ใช้

ข้อมูลเข้าสู่ระบบยังมีรายละเอียดเพิ่มเติมที่คุณขอด้วย เช่น หมายเลขโทรศัพท์ที่ยืนยันแล้วของบัญชี (หากมี)

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

หยุดแสดง UI ของ One Tap

หากผู้ใช้ปฏิเสธที่จะลงชื่อเข้าใช้ การเรียกใช้ getSignInCredentialFromIntent() จะแสดง ApiException พร้อมรหัสสถานะ CommonStatusCodes.CANCELED เมื่อเกิดกรณีนี้ คุณควรหยุดแสดง UI การลงชื่อเข้าใช้แบบแตะครั้งเดียวชั่วคราวเพื่อไม่ให้ผู้ใช้รำคาญกับข้อความแจ้งซ้ำๆ ตัวอย่างต่อไปนี้จะทําเช่นนี้โดยการตั้งค่าพร็อพเพอร์ตี้ในกิจกรรม ซึ่งระบบจะใช้เพื่อพิจารณาว่าจะเสนอฟีเจอร์ลงชื่อเข้าใช้แบบแตะครั้งเดียวให้ผู้ใช้หรือไม่ อย่างไรก็ตาม คุณยังบันทึกค่าลงใน 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 ซึ่งประกอบด้วยข้อมูลโปรไฟล์พื้นฐานบางอย่าง เช่น อีเมล ชื่อเต็ม และ URL รูปโปรไฟล์ของผู้ใช้ สําหรับแอปจํานวนมาก ข้อมูลนี้เพียงพอที่จะให้คุณตรวจสอบสิทธิ์ผู้ใช้ในแบ็กเอนด์และสร้างบัญชีใหม่

หากต้องการข้อมูลเพิ่มเติมเพื่อสร้างบัญชีให้เสร็จสมบูรณ์ เช่น วันเกิดของผู้ใช้ ให้แสดงขั้นตอนการลงชื่อสมัครใช้แบบละเอียดแก่ผู้ใช้เพื่อขอข้อมูลเพิ่มเติม จากนั้นส่งข้อมูลดังกล่าวไปยังแบ็กเอนด์เพื่อสร้างบัญชีให้เสร็จสมบูรณ์