استخدِم برنامج تسجيل الدخول بنقرة واحدة لطلب الإذن من المستخدم لاسترداد إحدى بيانات الاعتماد التي استخدمها سابقًا لتسجيل الدخول إلى تطبيقك. يمكن أن تكون بيانات الاعتماد هذه إما حساب Google أو تركيبة اسم مستخدم وكلمة مرور حفظها المستخدم مع Google باستخدام Chrome أو ميزة "الملء التلقائي" في Android أو ميزة "قفل ذكي" لكلمات المرور.
عند استرداد بيانات الاعتماد بنجاح، يمكنك استخدامها لتسجيل دخول المستخدم إلى تطبيقك بدون أي مشاكل.
إذا لم يحفظ المستخدم أيّ بيانات اعتماد، لن يتم عرض واجهة مستخدم، ويمكنك تقديم تجربة تسجيل الخروج العادية.
أين يجب استخدام ميزة "تسجيل الدخول بنقرة واحدة"؟
إذا كان تطبيقك يتطلّب من المستخدمين تسجيل الدخول، يجب عرض واجهة مستخدم One Tap على شاشة تسجيل الدخول. يمكن أن يكون ذلك مفيدًا حتى إذا كان لديك زر "تسجيل الدخول باستخدام حساب Google"، لأنّه يمكن ضبط واجهة مستخدم One Tap لعرض بيانات الاعتماد التي استخدمها المستخدِم سابقًا لتسجيل الدخول فقط، ما يمكن أن يكون تذكيرًا للمستخدِمين الذين لا يسجّلون الدخول بشكل متكرّر بالطريقة التي سجّلوا بها الدخول في المرة الأخيرة، ويمنعهم من إنشاء حسابات جديدة عن طريق الخطأ باستخدام تطبيقك.
إذا كان تسجيل الدخول اختياريًا في تطبيقك، ننصحك باستخدام ميزة "تسجيل الدخول بنقرة واحدة" على أي شاشة توفّر تجربة محسّنة عند تسجيل الدخول. على سبيل المثال، إذا كان بإمكان المستخدمين تصفّح المحتوى باستخدام تطبيقك بدون تسجيل الدخول، ولكن لا يمكنهم نشر تعليقات أو إضافة مواد إلى سلة تسوّق إلا بعد تسجيل الدخول، سيكون ذلك سياقًا مناسبًا لاستخدام ميزة تسجيل الدخول بنقرة واحدة.
يجب أن تستخدم أيضًا التطبيقات التي تتيح تسجيل الدخول اختياريًا ميزة "تسجيل الدخول بنقرة واحدة" على شاشات تسجيل الدخول، للأسباب المذكورة أعلاه.
قبل البدء
- إعداد مشروعك على Google APIs Console ومشروع Android كما هو موضّح في مقالة البدء باستخدام ميزة "تسجيل الدخول بنقرة واحدة"
- إذا كنت تتيح تسجيل الدخول باستخدام كلمة المرور، عليك تحسين تطبيقك لاستخدام ميزة الملء التلقائي (أو استخدام ميزة "Smart Lock لكلمات المرور") حتى يتمكّن المستخدمون من حفظ بيانات اعتماد كلمة المرور بعد تسجيل الدخول.
1. ضبط إعدادات برنامج تسجيل الدخول باستخدام ميزة "نقرة واحدة"
يمكنك ضبط برنامج تسجيل الدخول بنقرة واحدة لتسجيل دخول المستخدمين باستخدام كلمات المرور المحفوظة أو حسابات Google المحفوظة أو كليهما. (ننصح بتوفّر كليهما لتوفير إمكانية إنشاء الحسابات بنقرة واحدة للمستخدمين الجدد وتسجيل الدخول تلقائيًا أو بنقرة واحدة لأكبر عدد ممكن من المستخدمين المتكررين).
إذا كان تطبيقك يستخدم تسجيل الدخول المستنِد إلى كلمة المرور، استخدِم setPasswordRequestOptions()
ل
تفعيل طلبات بيانات اعتماد كلمة المرور.
إذا كان تطبيقك يستخدم ميزة "تسجيل الدخول باستخدام حساب Google"، استخدِم setGoogleIdTokenRequestOptions()
ل
تفعيل طلبات رمز تعريف Google وضبطها:
اضبط معرّف عميل الخادم على المعرّف الذي أنشأته في وحدة تحكّم Google APIs. يُرجى العِلم أنّ هذا هو معرّف العميل الخاص بالخادم، وليس معرّف العميل الخاص بجهاز Android.
اضبط العميل على الفلترة حسب الحسابات المعتمَدة. عند تفعيل هذا الخيار، سيطلب برنامج One Tap من المستخدمين تسجيل الدخول إلى تطبيقك باستخدام حسابات Google التي سبق لهم استخدامها. يمكن أن يساعد ذلك المستخدمين في تسجيل الدخول بنجاح عندما لا يكونون متأكدين مما إذا كان لديهم حساب أو حساب Google الذي استخدموه، ويمنع المستخدمين من إنشاء حسابات جديدة عن طريق الخطأ باستخدام تطبيقك.
إذا كنت تريد تسجيل دخول المستخدمين تلقائيًا كلما أمكن ذلك، فعِّل الميزة باستخدام
setAutoSelectEnabled()
. يمكن تسجيل الدخول تلقائيًا عند استيفاء المعايير التالية:- يتوفّر لدى المستخدم بيانات اعتماد واحدة محفوظة لتطبيقك، أي كلمة مرور واحدة محفوظة أو حساب Google واحد محفوظ.
- لم يوقف المستخدم ميزة "تسجيل الدخول تلقائيًا" في إعدادات حسابه على Google.
على الرغم من أنّ استخدام مفتاح عشوائي لمرة واحدة اختياري، ننصحك بشدة باستخدامه لتحسين أمان تسجيل الدخول وتجنُّب هجمات إعادة التشغيل. استخدِم setNonce لتضمين مفتاح nonce في كل طلب. اطّلِع على قسم الحصول على مفتاح تشفير عشوائي في SafetyNet للحصول على اقتراحات وتفاصيل إضافية حول إنشاء مفتاح تشفير عشوائي.
Java
public class YourActivity extends AppCompatActivity { // ... private SignInClient oneTapClient; private BeginSignInRequest signInRequest; @Override public void onCreate(@Nullable Bundle savedInstanceState, @Nullable PersistableBundle persistentState) { super.onCreate(savedInstanceState, persistentState); oneTapClient = Identity.getSignInClient(this); signInRequest = BeginSignInRequest.builder() .setPasswordRequestOptions(PasswordRequestOptions.builder() .setSupported(true) .build()) .setGoogleIdTokenRequestOptions(GoogleIdTokenRequestOptions.builder() .setSupported(true) // Your server's client ID, not your Android client ID. .setServerClientId(getString(R.string.default_web_client_id)) // Only show accounts previously used to sign in. .setFilterByAuthorizedAccounts(true) .build()) // Automatically sign in when exactly one credential is retrieved. .setAutoSelectEnabled(true) .build(); // ... } // ... }
Kotlin
class YourActivity : AppCompatActivity() { // ... private lateinit var oneTapClient: SignInClient private lateinit var signInRequest: BeginSignInRequest override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) oneTapClient = Identity.getSignInClient(this) signInRequest = BeginSignInRequest.builder() .setPasswordRequestOptions(BeginSignInRequest.PasswordRequestOptions.builder() .setSupported(true) .build()) .setGoogleIdTokenRequestOptions( BeginSignInRequest.GoogleIdTokenRequestOptions.builder() .setSupported(true) // Your server's client ID, not your Android client ID. .setServerClientId(getString(R.string.your_web_client_id)) // Only show accounts previously used to sign in. .setFilterByAuthorizedAccounts(true) .build()) // Automatically sign in when exactly one credential is retrieved. .setAutoSelectEnabled(true) .build() // ... } // ... }
2- البحث عن مستخدم مسجّل الدخول
إذا كان بإمكان مستخدم سجّل الدخول أو لم يسجّل الدخول استخدام نشاطك، تحقّق من حالة المستخدم قبل عرض واجهة مستخدم ميزة "تسجيل الدخول بنقرة واحدة".
يجب أيضًا تتبُّع ما إذا كان المستخدم قد رفض استخدام ميزة "تسجيل الدخول بنقرة واحدة" من خلال إغلاق الطلب أو النقر خارج الطلب. يمكن أن يكون هذا بسيطًا مثل سمة منطقية لنشاطك. (اطّلِع على إيقاف عرض واجهة مستخدم "النقرة الواحدة" أدناه).
3- عرض واجهة مستخدم ميزة "تسجيل الدخول بنقرة واحدة"
إذا لم يكن المستخدم مسجِّلاً الدخول ولم يسبق له رفض استخدام ميزة "تسجيل الدخول بنقرة واحدة"،
اتصل بطريقة beginSignIn()
لعنصر العميل، واربط المستمعين بالقيمة التي يعرضها العنصر
Task
. وعادةً ما تُجري التطبيقات ذلك في طريقة onCreate()
لنشاط معيّن
أو بعد انتقالات الشاشة عند استخدام بنية نشاط واحد.
سيستدعي عميل One Tap معالج الإشعار بالنجاح إذا كان لدى المستخدم أي بيانات اعتماد محفوظة
لتطبيقك. في معالج الإشعار بالنجاح، يمكنك الحصول على النية المعلّقة من نتيجة Task
ونقلها إلى startIntentSenderForResult()
لبدء واجهة مستخدم تسجيل الدخول باستخدام One Tap.
إذا لم يكن لدى المستخدم أي بيانات اعتماد محفوظة، سيستدعي برنامج 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 saved credentials found. Launch the One Tap sign-up flow, or
// do nothing and continue presenting the signed-out UI.
Log.d(TAG, e.getLocalizedMessage());
}
});
Kotlin
oneTapClient.beginSignIn(signInRequest)
.addOnSuccessListener(this) { result ->
try {
startIntentSenderForResult(
result.pendingIntent.intentSender, REQ_ONE_TAP,
null, 0, 0, 0, null)
} catch (e: IntentSender.SendIntentException) {
Log.e(TAG, "Couldn't start One Tap UI: ${e.localizedMessage}")
}
}
.addOnFailureListener(this) { e ->
// No saved credentials found. Launch the One Tap sign-up flow, or
// do nothing and continue presenting the signed-out UI.
Log.d(TAG, e.localizedMessage)
}
4- التعامل مع ردّ المستخدم
سيتم إرسال ردّ المستخدم على طلب تسجيل الدخول بنقرة واحدة إلى تطبيقك
باستخدام طريقة onActivityResult()
في نشاطك. إذا اختار المستخدم تسجيل الدخول،
ستكون النتيجة بيانات اعتماد محفوظة. إذا رفض المستخدم تسجيل الدخول، إما
بإغلاق واجهة مستخدم One Tap أو النقر خارجها، ستظهر النتيجة مع
الرمز RESULT_CANCELED
. يجب أن يتعامل تطبيقك مع كلتا الحالتَين.
تسجيل الدخول باستخدام بيانات الاعتماد التي تم استردادها
إذا اختار المستخدم مشاركة بيانات الاعتماد مع تطبيقك، يمكنك استردادها من خلال
تمرير بيانات النية من onActivityResult()
إلى طريقة
getSignInCredentialFromIntent()
لخادم One Tap. ستحتوي بيانات الاعتماد على سمة
googleIdToken
غير فارغة إذا شارك المستخدم بيانات اعتماد حساب Google مع
تطبيقك، أو سمة password
غير فارغة إذا شارك المستخدم كلمة مرور محفوظة.
استخدِم بيانات الاعتماد للمصادقة مع الخلفية في تطبيقك.
- إذا تم استرداد اسم مستخدم وكلمة مرور، استخدِمهما لتسجيل الدخول بالطريقة نفسها التي كنت ستستخدمها إذا قدّمهما المستخدم يدويًا.
في حال استرداد بيانات اعتماد حساب Google، استخدِم الرمز المميّز للتعريف من أجل المصادقة مع الخلفية. إذا اخترت استخدام مفتاح عشوائي للمساعدة في تجنُّب هجمات إعادة التشغيل، عليك التحقّق من قيمة الاستجابة على خادم الخلفية. اطّلِع على مقالة المصادقة مع الخلفية باستخدام الرموز المميّزة لتعريف المستخدمين.
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(); String username = credential.getId(); String password = credential.getPassword(); if (idToken != null) { // Got an ID token from Google. Use it to authenticate // with your backend. Log.d(TAG, "Got ID token."); } else if (password != null) { // Got a saved username and password. Use them to authenticate // with your backend. Log.d(TAG, "Got password."); } } 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 val username = credential.id val password = credential.password when { idToken != null -> { // Got an ID token from Google. Use it to authenticate // with your backend. Log.d(TAG, "Got ID token.") } password != null -> { // Got a saved username and password. Use them to authenticate // with your backend. Log.d(TAG, "Got password.") } else -> { // Shouldn't happen. Log.d(TAG, "No ID token or password!") } } } 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})") } } } } } } // ... }
5. معالجة تسجيل الخروج
عندما يسجِّل مستخدم الخروج من تطبيقك، يمكنك استدعاء طريقة signOut()
في عميل One Tap.
يؤدي الاتصال بالرقم signOut()
إلى إيقاف ميزة "تسجيل الدخول تلقائيًا" إلى أن يسجّل المستخدم الدخول مرة أخرى.
حتى إذا كنت لا تستخدم ميزة "تسجيل الدخول تلقائيًا"، هذه الخطوة مهمة لأنّها تضمن أنّه عند تسجيل المستخدمين الخروج من تطبيقك، تتم أيضًا إعادة ضبط حالة المصادقة لأي واجهات برمجة تطبيقات "خدمات Play" تستخدمها.
الخطوات التالية
إذا أعددت برنامج One Tap لاسترداد بيانات اعتماد Google، يمكن لتطبيقك الحصول الآن على رموز Google ID التي تمثّل حسابات المستخدمين على Google. تعرَّف على كيفية استخدام هذه الرموز المميّزة في الخلفية.
إذا كنت تتيح ميزة "تسجيل الدخول باستخدام حساب Google"، يمكنك أيضًا استخدام برنامج One Tap لإضافة عمليات سلسة لإنشاء الحسابات إلى تطبيقك.