التنقّل الشرطي في Android باستخدام تسجيل الدخول

هذا الدرس العملي حول الترميز هو جزء من دورة "تطبيقات متقدّمة متوافقة مع نظام Android باستخدام لغة Kotlin". ستستفيد إلى أقصى حدّ من هذه الدورة التدريبية إذا تابعت دروس الترميز بالتسلسل، ولكن هذا ليس إلزاميًا. يمكنك الاطّلاع على جميع دورات الترميز في الدورة التدريبية على الصفحة المقصودة لدورات الترميز في "تطبيقات متقدمة متوافقة مع نظام Android باستخدام لغة Kotlin".


يستند هذا الدرس التطبيقي إلى تنفيذ ميزة تسجيل الدخول على Android باستخدام FirebaseUI. يمكنك تنزيل رمز البداية لهذا الدرس التطبيقي حول الترميز إذا لم تكن قد أكملت الدرس التطبيقي السابق، ولكن قد يكون من المفيد إكمال الدرس التطبيقي حول الترميز تنفيذ تسجيل الدخول على Android باستخدام FirebaseUI أولاً.

مقدمة

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

في مثل هذه الحالات، يمكنك استخدام التنقّل الشرطي لنقل المستخدمين إلى الشاشة المناسبة استنادًا إلى حالة المصادقة.

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

ما يجب معرفته

أهداف الدورة التعليمية

  • كيفية توجيه المستخدمين إلى الشاشات المناسبة في تطبيقك استنادًا إلى ما إذا كانوا قد سجّلوا الدخول أم لا

الإجراءات التي ستنفذّها

  • التعامل بشكل صحيح مع توجيه المستخدمين إلى الشاشة الصحيحة بعد تسجيل الدخول بنجاح
  • منع المستخدمين من الوصول إلى شاشة الإعدادات إذا لم يكونوا مسجّلين الدخول، وإعادة توجيههم بدلاً من ذلك إلى شاشة تسجيل الدخول

في الدرس التطبيقي السابق، عملت على تطبيق يعرض معلومات عن نظام التشغيل Android. كان تطبيقك يسمح أيضًا للمستخدمين بتسجيل الدخول والخروج. في هذا الدرس العملي، ستضيف شاشة إعدادات إلى التطبيق الحالي. ولن يتمكّن المستخدم من الوصول إلى شاشة الإعدادات إلا إذا سجّل الدخول.

إذا لم يكن المستخدم مسجّلاً الدخول، ستتم إعادة توجيهه إلى شاشة تسجيل الدخول عند محاولة الوصول إلى شاشة الإعدادات. بعد إكمال عملية تسجيل الدخول بنجاح، سيتم إعادة المستخدم إلى شاشة الإعدادات التي حاول الوصول إليها في الأصل.

يستند هذا الدرس التطبيقي إلى تنفيذ ميزة تسجيل الدخول على Android باستخدام FirebaseUI. يمكنك تنزيل رمز البداية لهذا الدرس التطبيقي حول الترميز إذا لم تكن قد أكملت الدرس التطبيقي السابق، ولكن قد يكون من المفيد إكمال الدرس التطبيقي حول الترميز تنفيذ تسجيل الدخول على Android باستخدام FirebaseUI أولاً.

نزِّل التطبيق النموذجي، ويمكنك إجراء أحد الإجراءَين التاليَين:

تنزيل ملف Zip


... أو استنسِخ مستودع GitHub من سطر الأوامر باستخدام الأمر التالي وانتقِل إلى فرع start من المستودع:

$  git clone https://github.com/googlecodelabs/android-kotlin-login-navigation

بعد تحميل المشروع في "استوديو Android"، اتّبِع الخطوات التالية:

  1. شغِّل التطبيق على محاكي أو جهاز فعلي للتأكّد من إعداد بيئتك بنجاح لبدء عملية التطوير.

في حال نجاح ذلك، من المفترض أن تظهر لك الشاشة الرئيسية تعرض معلومة مسلّية عن Android وزر تسجيل الدخول في أعلى يسار الشاشة.


الميزات الحالية للتطبيق التجريبي:

  • إذا لم يكن المستخدم مسجّلاً الدخول، يؤدي النقر على الزر تسجيل الدخول إلى بدء عملية تسجيل الدخول والسماح للمستخدم بتسجيل الدخول باستخدام عنوان بريد إلكتروني أو حساب Google.
  • إذا كان المستخدم مسجّلاً الدخول، يتغيّر الزر إلى زر تسجيل الخروج الذي يتيح للمستخدم تسجيل الخروج.

في هذه المهمة، ستضيف زرًا على الشاشة الرئيسية يتيح للمستخدم الانتقال إلى شاشة الإعدادات. ستتيح شاشة الإعدادات للمستخدم اختيار نوع الحقائق المسلّية التي يريد عرضها على الشاشة الرئيسية. من شاشة الإعدادات، يمكنهم اختيار الاطّلاع على حقائق حول نظام التشغيل Android أو حقائق حول ولاية كاليفورنيا.

  1. فتح "fragment_main.xml"
  2. في fragment_main.xml,، أضِف زر الإعدادات مضمّنًا في ConstraintLayout، وضَع الزر في أعلى يسار الشاشة.

fragment_main.xml

<TextView
       android:id="@+id/settings_btn"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_margin="@dimen/text_margin"
       android:background="@color/colorAccent"
       android:padding="10dp"
       android:text="@string/settings_btn"
       android:textColor="#ffffff"
       android:textSize="20sp"
       app:layout_constraintRight_toRightOf="parent"
       app:layout_constraintTop_toTopOf="parent"/>
  1. فتح "nav_graph.xml"
  2. أضِف إجراءً داخل mainFragment. id الإجراء هو action_mainFragment_to_customizeFragment، والوجهة هي customizeFragment.

nav_graph.xml

<fragment
       android:id="@+id/mainFragment"
       android:name="com.example.android.firebaseui_login_sample.MainFragment"
       android:label="MainFragment">
   <action
           android:id="@+id/action_mainFragment_to_settingsFragment"
           app:destination="@id/settingsFragment"/>
</fragment>
  1. فتح "MainFragment.kt"
  2. في onViewCreated()، اضبط onClickListener لـ settings_btn، حتى يؤدي النقر على الزر إلى نقل المستخدم إلى customizeFragment.

MainFragment.kt

binding.settingsBtn.setOnClickListener {
   val action = MainFragmentDirections.actionMainFragmentToSettingsFragment()
   findNavController().navigate(action)
}
  1. إذا ظهرت لك أخطاء لم يتم حلّها، أعِد تجميع التطبيق من قائمة إنشاء لإنشاء إجراءات التنقّل الجديدة التي أنشأتها واستخدامها.
  2. أعِد تشغيل التطبيق. من المفترض أن يظهر الآن زر الإعدادات الذي يعمل في أعلى يسار الشاشة.
  3. انقر على الزر الذي من المفترض أن ينقلك إلى شاشة الإعدادات. لا تحتوي شاشة الإعدادات إلا على خيار واحد، وهو السماح للمستخدم باختيار نوع المعلومة المسلّية التي يريد عرضها على الشاشة الرئيسية.
  4. انقر على زر الرجوع في جهاز Android للعودة إلى الشاشة الرئيسية.

في هذه المهمة، ستضيف رمزًا برمجيًا لنقل المستخدم إلى شاشة تسجيل الدخول إذا حاول الوصول إلى شاشة الإعدادات بدون تسجيل الدخول.

  1. فتح "SettingsFragment.kt"
  2. في onViewCreated()، راقِب authenticationState وأعِد توجيه المستخدم إلى LoginFragment إذا لم تتم مصادقته.

SettingsFragment.kt

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
   super.onViewCreated(view, savedInstanceState)
   val navController = findNavController()
   viewModel.authenticationState.observe(viewLifecycleOwner, Observer { authenticationState ->
       when (authenticationState) {
           LoginViewModel.AuthenticationState.AUTHENTICATED -> Log.i(TAG, "Authenticated")
           // If the user is not logged in, they should not be able to set any preferences,
           // so navigate them to the login fragment
           LoginViewModel.AuthenticationState.UNAUTHENTICATED -> navController.navigate(
               R.id.loginFragment
           )
           else -> Log.e(
               TAG, "New $authenticationState state that doesn't require any UI change"
           )
       }
   })
}

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

  1. فتح "LoginFragment.kt"
  2. في onViewCreated()، تعامَل مع إجراءات زر الرجوع من خلال إعادة المستخدم إلى MainFragment.

LoginFragment.kt

// If the user presses the back button, bring them back to the home screen
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
   navController.popBackStack(R.id.mainFragment, false)
}
  1. أعِد تشغيل تطبيقك وتأكَّد من أنّه في حال عدم تسجيل الدخول، ستتم إعادة توجيه محاولات الوصول إلى شاشة الإعدادات إلى عملية تسجيل الدخول.

على الرغم من أنّك نجحت في إعادة توجيه المستخدم لتسجيل الدخول، لم تتعامل مع ما يحدث بعد تسجيل الدخول بنجاح، لذا ستظهر محاولات تسجيل الدخول وكأنّها لا تعمل. سيتم حلّ هذه المشكلة في الخطوة التالية.

حتى الآن، تمكّنت من إعداد تطبيقك لإعادة توجيه المستخدم إلى شاشة تسجيل الدخول إذا حاول الوصول إلى شاشة الإعدادات بدون تسجيل الدخول.

ومع ذلك، بعد إكمال خطوات تسجيل الدخول، يتم إرجاعك إلى شاشة تسجيل الدخول مرة أخرى. هذا ليس خيارًا جيدًا للمستخدمين وقد يسبب لهم بعض الارتباك.

لتوفير تجربة مثالية للمستخدم، يجب أن يعيد التطبيق المستخدم إلى شاشة الإعدادات بعد تسجيل الدخول بنجاح.

  1. في LoginFragment.kt، في أي مكان في onViewCreated()، راقِب authenticationState وأعِد توجيه المستخدم إلى SettingsFragment عند إثبات هويته بنجاح.

LoginFragment.kt

// Observe the authentication state so we can know if the user has logged in successfully.
// If the user has logged in successfully, bring them back to the settings screen.
// If the user did not log in successfully, display an error message.
viewModel.authenticationState.observe(viewLifecycleOwner, Observer { authenticationState ->
   when (authenticationState) {
      // Since our login flow is only one screen instead of multiple 
      // screens, we can utilize popBackStack(). If our login flow 
      // consisted of multiple screens, we would have to call 
      // popBackStack() multiple times.
       LoginViewModel.AuthenticationState.AUTHENTICATED -> navController.popBackStack()
       else -> Log.e(
           TAG,
           "Authentication state that doesn't require any UI change $authenticationState"
       )
   }
})
  1. أعِد تشغيل تطبيقك وتأكَّد من أنّه عند تسجيل الدخول بنجاح، سيتم توجيهك إلى صفحة الإعدادات بدلاً من صفحة تسجيل الدخول.

يمكنك الاطّلاع على التطبيق الكامل مع جميع رموز الحلول في مستودع Github هذا https://github.com/googlecodelabs/android-kotlin-login-navigation.

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

لمزيد من المعلومات حول أفضل الممارسات المتعلّقة بالتنقّل في Android، يمكنك الاطّلاع على المراجع التالية:

مستندات مطوّري تطبيقات Android:

الدروس التطبيقية حول الترميز:

للحصول على روابط تؤدي إلى دروس برمجية أخرى في هذه الدورة التدريبية، يمكنك الانتقال إلى الصفحة المقصودة للدروس البرمجية المتقدّمة حول Android بلغة Kotlin.