إنشاء حسابات جديدة بنقرة واحدة

إذا كنت تتيح تسجيل الدخول باستخدام حسابات Google، يمكنك استخدام ملف برمجي لميزة "تسجيل الدخول بنقرة واحدة" لمنح المستخدمين أيضًا تجربة إنشاء حساب سلسة بدون إخراجهم من سياق تطبيقك.

واجهة مستخدم الاشتراك بنقرة واحدة

عند عرض واجهة مستخدم One Tap، سيُطلب من المستخدمين إنشاء حساب جديد في تطبيقك باستخدام أحد حسابات Google على أجهزتهم. إذا اختار المستخدم متابعة الخطوات، ستحصل على رمز تعريف يتضمّن معلومات الملف الشخصي الأساسية، وهي الاسم وصورة الملف الشخصي وعنوان البريد الإلكتروني الذي تم إثبات ملكيته، ويمكنك استخدام هذا الرمز لمحاولة إنشاء الحساب الجديد.

يتضمّن تنفيذ ميزة "إنشاء الحساب بنقرة واحدة" جزءَين:

  • دمج برنامج One Tap في تطبيقك، كما هو موضّح في هذه الصفحة يشبه هذا الإجراء إلى حدٍ كبير استخدام ميزة "تسجيل الدخول باستخدام نقرة واحدة"، ولكن مع بعض الاختلافات في الإعداد.
  • إضافة إمكانية إنشاء حسابات مستخدمين من علامات Google المتعلّقة بالمعرّف ، والتي تمت مناقشتها في مقالة استخدام علامات المعرّف في الخلفية

أين يجب استخدام ميزة "الاشتراك بنقرة واحدة"؟

إنّ أفضل مكان لتقديم ميزة "الاشتراك بنقرة واحدة" للمستخدمين هو في سياق يؤدي فيه تسجيل الدخول إلى تفعيل ميزات جديدة. أولاً، حاوِل تسجيل دخول المستخدم باستخدام مستند اعتماد محفوظ. إذا لم يتم العثور على بيانات اعتماد محفوظة، يمكنك أن تقترح على المستخدم إنشاء حساب جديد.

قبل البدء

إعداد مشروعك على Google APIs Console ومشروع Android كما هو موضّح في مقالة البدء باستخدام ميزة "تسجيل الدخول بنقرة واحدة"

‫1. ضبط إعدادات برنامج 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- تتبُّع عمليات إلغاء واجهة مستخدم "نقرة واحدة"

يجب تتبُّع ما إذا كان المستخدم قد رفض استخدام ميزة "تسجيل الاشتراك بنقرة واحدة" من خلال إغلاق الطلب أو النقر خارج الطلب. ويمكن أن يكون ذلك بسيطًا مثل سمة منطقية لنشاطك. (اطّلِع على إيقاف عرض واجهة مستخدم One Tap أدناه).

3- عرض واجهة مستخدم الاشتراك باستخدام ميزة "نقرة واحدة"

إذا لم يرفض المستخدم استخدام ميزة "النقرة الواحدة" لإنشاء حساب جديد، يمكنك استدعاء beginSignIn() في مثيل العميل، وإرفاق مستمعين بالقيمة التي يعرضها Task. تُجري التطبيقات هذه الخطوة عادةً عندما لا يعثر طلب تسجيل الدخول بنقرة واحدة على أي بيانات اعتماد محفوظة، أي في معالج الأخطاء لطلب تسجيل الدخول.

سيستدعي برنامج One Tap مستمع الطلبات الناجحة إذا كان لدى المستخدم حساب Google واحد أو أكثر تم إعداده على الجهاز. في معالج الإشعار بالنجاح، احصل على الintent في انتظار المراجعة من نتيجة Task ونقلها إلى startIntentSenderForResult() لبدء واجهة مستخدم One Tap.

إذا لم يكن لدى المستخدم أي حسابات 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- التعامل مع ردّ المستخدم

سيتم إرسال ردّ المستخدم على طلب الاشتراك بنقرة واحدة إلى تطبيقك باستخدام طريقة onActivityResult() في نشاطك. إذا اختار المستخدم إنشاء حساب، ستكون النتيجة رمزًا مميّزًا لتعريف Google. إذا رفض المستخدم الاشتراك، سواءً من خلال إغلاق واجهة مستخدم One Tap أو النقر خارجها، ستظهر النتيجة بالرمز RESULT_CANCELED. يجب أن يتعامل تطبيقك مع كلتا الحالتَين.

إنشاء حساب باستخدام رمز تعريف Google

إذا اختار المستخدم الاشتراك باستخدام حساب Google، يمكنك الحصول على رمز تعريف للمستخدم من خلال تمرير بيانات النية من 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) {
                    // ...
            }
        }
    }
    // ...
}

إيقاف عرض واجهة مستخدم ميزة "نقرة واحدة"

إذا رفض المستخدم تسجيل الدخول، ستؤدي الدعوة إلى getSignInCredentialFromIntent() إلى طرح ApiException مع رمز الحالة CommonStatusCodes.CANCELED. عند حدوث ذلك، يجب إيقاف عرض واجهة مستخدم تسجيل الدخول بنقرة واحدة مؤقتًا كي لا تزعج المستخدمين بطلبات متكرّرة. يحقّق المثال التالي هذا من خلال ضبط خاصيّة على "النشاط"، والتي يستخدمها لتحديد ما إذا كان سيتمّ منح المستخدم ميزة "تسجيل الدخول بنقرة واحدة" أم لا. ومع ذلك، يمكنك أيضًا حفظ قيمة في 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})")
                        }
                    }
                }
            }
        }
    }
    // ...
}

الخطوات التالية

عندما يُكمل المستخدم عملية الاشتراك باستخدام ميزة "النقرة الواحدة"، تحصل على رمز تعريف Google الذي يحتوي على بعض المعلومات الأساسية للملف الشخصي، مثل عنوان البريد الإلكتروني للمستخدم واسم المستخدم الكامل وعنوان URL لصورة الملف الشخصي. في العديد من التطبيقات، تكون هذه المعلومات كافية لكي تتمكّن من مصادقة المستخدم في الخلفية وإنشاء حساب جديد.

إذا كنت بحاجة إلى معلومات إضافية لإكمال عملية إنشاء الحساب، مثل تاريخ ميلاد المستخدم، عليك تقديم مسار تفاصيل الاشتراك للمستخدم، حيث تطلب منه هذه المعلومات الإضافية. بعد ذلك، أرسِل هذه المعلومات إلى الخلفية لإكمال عملية إنشاء الحساب.