استخدِم برنامج تسجيل الدخول بنقرة واحدة لطلب إذن من المستخدم لاسترداد إحدى بيانات الاعتماد التي استخدمها في السابق لتسجيل الدخول إلى تطبيقك. قد تكون بيانات الاعتماد هذه حساب Google أو مجموعة من اسم المستخدم وكلمة المرور تم حفظها لدى Google باستخدام Chrome أو ميزة "الملء التلقائي" في جهاز Android أو ميزة Smart Lock لكلمات المرور.
عند استرداد بيانات الاعتماد بنجاح، يمكنك استخدامها لتسجيل دخول المستخدم إلى تطبيقك بسلاسة.
إذا لم يحفظ المستخدم أي بيانات اعتماد، لن يتم عرض واجهة المستخدم، ويمكنك تقديم تجربة تسجيل الخروج المعتادة.
أين يجب استخدام ميزة "تسجيل الدخول بنقرة واحدة"؟
إذا كان تطبيقك يتطلب من المستخدمين تسجيل الدخول، يمكنك عرض واجهة المستخدم بنقرة واحدة على شاشة تسجيل الدخول. يمكن أن يكون ذلك مفيدًا حتى إذا كان لديك زر "تسجيل الدخول باستخدام حساب Google": لأنه يمكن ضبط واجهة المستخدم بنقرة واحدة بحيث لا تعرض سوى بيانات الاعتماد التي استخدمها المستخدم في السابق لتسجيل الدخول فقط، فقد تكون هذه الصفحة بمثابة تذكير للمستخدمين الذين يسجلون الدخول بشكل غير منتظم على طريقة تسجيل الدخول في المرة الأخيرة، ومنعهم من إنشاء حسابات جديدة باستخدام تطبيقك عن طريق الخطأ.
إذا كان تسجيل الدخول اختياريًا لتطبيقك، فيمكنك استخدام "تسجيل الدخول بنقرة واحدة" على أي شاشة ذات تجربة محسّنة من خلال تسجيل الدخول. على سبيل المثال، إذا كان بإمكان المستخدمين تصفّح المحتوى باستخدام تطبيقك بدون تسجيل الدخول، ولكن يمكنهم فقط نشر التعليقات أو إضافة عناصر إلى سلة التسوّق بعد تسجيل الدخول، سيكون ذلك سياقًا منطقيًا لتسجيل الدخول بنقرة واحدة.
من المفترض أن تستخدم التطبيقات الاختيارية لتسجيل الدخول أيضًا ميزة تسجيل الدخول بنقرة واحدة على شاشات تسجيل الدخول، للأسباب المذكورة أعلاه.
قبل البدء
- عليك إعداد مشروع وحدة تحكّم Google APIs ومشروع Android كما هو موضّح في البدء باستخدام ميزة "تسجيل الدخول بنقرة واحدة".
- إذا كان تسجيل الدخول يتيح استخدام كلمة المرور، يمكنك تحسين تطبيقك لملء البيانات تلقائيًا (أو استخدام Smart Lock لكلمات المرور) حتى يتمكن المستخدمون من حفظ بيانات اعتماد كلمة المرور بعد تسجيل الدخول.
1- ضبط برنامج تسجيل الدخول بنقرة واحدة
يمكنك إعداد برنامج تسجيل الدخول بنقرة واحدة لتسجيل دخول المستخدمين باستخدام كلمات المرور المحفوظة أو حسابات Google المحفوظة أو أيٍّ منهما. (ننصح لإتاحة إنشاء الحساب بنقرة واحدة للمستخدمين الجدد وتسجيل الدخول تلقائيًا أو بنقرة واحدة لأكبر عدد ممكن من المستخدمين المكرّري الزيارة.)
إذا كان تطبيقك يستخدم تسجيل الدخول المستند إلى كلمة المرور، يمكنك استخدام setPasswordRequestOptions()
لتفعيل طلبات بيانات اعتماد كلمة المرور.
إذا كان تطبيقك يستخدم ميزة "تسجيل الدخول بحساب Google"، يمكنك استخدام setGoogleIdTokenRequestOptions()
لتفعيل وضبط طلبات الرموز المميّزة لمعرّف Google:
اضبط معرِّف عميل الخادم على المعرِّف الذي أنشأته في وحدة تحكُّم Google APIs. لاحظ أن هذا هو معرف العميل لخادمك، وليس معرِّف عميل Android.
اضبط العميل للفلترة حسب الحسابات المُصرَّح بها. عند تفعيل هذا الخيار، لا يطلب برنامج "نقرة واحدة" من المستخدمين سوى تسجيل الدخول إلى تطبيقك باستخدام حسابات Google التي سبق لهم استخدامها في السابق. يؤدي ذلك إلى مساعدة المستخدمين في تسجيل الدخول بنجاح عندما لا يكونوا متأكدين مما إذا كان لديهم حساب من قبل أو حساب Google الذي استخدموه، كما يمنع المستخدمين من إنشاء حسابات جديدة باستخدام تطبيقك عن طريق الخطأ.
إذا أردت تسجيل دخول المستخدمين تلقائيًا إن أمكن، فعِّل الميزة باستخدام
setAutoSelectEnabled()
. يمكن تسجيل الدخول تلقائيًا عند استيفاء المعايير التالية:- المستخدم لديه بيانات اعتماد واحدة محفوظة لتطبيقك بالضبط. وهي كلمة مرور واحدة محفوظة أو حساب Google محفوظ واحد.
- لم يوقِف المستخدم تسجيل الدخول التلقائي في إعدادات حساب Google.
على الرغم من أن هذا الإجراء اختياري، ننصحك بالتفكير بشدة في استخدام رقم خاص لتحسين أمان تسجيل الدخول وتجنُّب إعادة تشغيل الهجمات. استخدِم setNonce لتضمين رقم خاص في كل طلب. راجِع قسم الحصول على خاصية في 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()
للنشاط أو بعد انتقالات الشاشة عند استخدام بنية "نشاط واحد".
سيتصل برنامج "نقرة واحدة" بأداة معالجة النتائج إذا كان لدى المستخدم أي بيانات اعتماد محفوظة لتطبيقك. وفي أداة معالجة النجاح، يمكنك الحصول على الغرض المعلق من
نتيجة Task
وتمريره إلى startIntentSenderForResult()
لبدء
واجهة المستخدم لتسجيل الدخول بنقرة واحدة.
إذا لم يكن لدى المستخدم أي بيانات اعتماد محفوظة، سيتصل برنامج "نقرة واحدة" بأداة معالجة الإخفاق. في هذه الحالة، ليس عليك اتّخاذ أي إجراء: يمكنك ببساطة مواصلة تقديم تجربة استخدام التطبيق بعد تسجيل الخروج منه. في المقابل، إذا كان موقعك الإلكتروني يتيح استخدام ميزة "نقرة واحدة"، يمكنك بدء هذه العملية من هنا لتوفير تجربة سلسة لإنشاء الحساب. يُرجى الاطّلاع على إنشاء حسابات جديدة بنقرة واحدة.
لغة 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()
في "النشاط". إذا اختار المستخدم تسجيل الدخول،
ستكون النتيجة بيانات اعتماد محفوظة. إذا رفض المستخدم تسجيل الدخول سواء بإغلاق واجهة المستخدم بنقرة واحدة أو النقر خارجها، ستظهر النتيجة مع الرمز RESULT_CANCELED
. يحتاج تطبيقك إلى كلا الاحتمالين.
تسجيل الدخول باستخدام بيانات الاعتماد التي تم استردادها
إذا اختار المستخدم مشاركة بيانات الاعتماد مع تطبيقك، يمكنك استردادها عن طريق
تمرير بيانات الغرض من onActivityResult()
إلى طريقة getSignInCredentialFromIntent()
في برنامج "نقرة واحدة". ستحتوي بيانات الاعتماد على سمة 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
أو استخدام طريقة أخرى.
من المهم تطبيق تحديد المعدّل الخاص بك لمطالبات تسجيل الدخول بنقرة واحدة. إذا لم تفعل ذلك، وألغى المستخدم عدة مطالبات متتالية، فلن يطلب برنامج "نقرة واحدة" من المستخدم خلال 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()
التابعة لعميل ميزة "نقرة واحدة".
يؤدي الاتصال برقم signOut()
إلى إيقاف تسجيل الدخول التلقائي إلى أن يسجِّل المستخدم الدخول مرة أخرى.
حتى إذا كنت لا تستخدم ميزة "تسجيل الدخول تلقائيًا"، تكون هذه الخطوة مهمة لأنّها تضمن أنّه عندما يسجّل المستخدمون خروجهم من تطبيقك، ستتم أيضًا إعادة ضبط حالة المصادقة لأي واجهات برمجة تطبيقات لخدمة Play تستخدمها.
الخطوات التالية
إذا ضبطت برنامج "نقرة واحدة" لاسترداد بيانات اعتماد Google، سيتمكّن تطبيقك الآن من الحصول على الرموز المميّزة لمعرّف Google التي تمثِّل حسابات المستخدمين على Google. اطّلِع على كيفية استخدام هذه الرموز المميّزة في الخلفية.
إذا كنت توفّر ميزة "تسجيل الدخول بحساب Google"، يمكنك أيضًا استخدام برنامج "نقرة واحدة" لإضافة عمليات إنشاء حساب سلسة إلى تطبيقك.