ה-codelab הזה הוא חלק מהקורס Advanced Android in Kotlin (פיתוח מתקדם ל-Android ב-Kotlin). כדי להפיק את המרב מהקורס הזה, מומלץ לעבוד על ה-codelabs לפי הסדר, אבל זה לא חובה. כל ה-codelab של הקורס מפורטים בדף הנחיתה של ה-codelab בנושא Android מתקדם ב-Kotlin.
מבוא
כשמפתחים אפליקציה ל-Android, יש הרבה יתרונות לתמיכה בכניסה לחשבון עבור המשתמשים. אם תאפשרו למשתמשים ליצור זהות באפליקציה שלכם, תוכלו לספק להם דרכים נוספות ליצור אינטראקציה עם האפליקציה.
בחשבונות מותאמים אישית, המשתמשים יכולים להתאים אישית את חוויית השימוש באפליקציה, ליצור קשר עם משתמשים אחרים ולשמור את הנתונים שלהם ולהעביר אותם אם הם משתמשים באפליקציה במכשיר אחר (כמו אינטרנט או טלפון חדש).
ב-codelab הזה תלמדו את העקרונות הבסיסיים של הוספת תמיכה בכניסה לאפליקציה באמצעות ספריית FirebaseUI. בין היתר, ספריית FirebaseUI מאפשרת למפתחים שרוצים ליצור תהליך כניסה לעשות זאת בקלות, והיא מטפלת בעבודה של ניהול חשבונות משתמשים בשבילכם.
מה שכדאי לדעת
- היסודות של יצירת אפליקציה ל-Android
- LiveData ו-ViewModel
מה תלמדו
- איך מוסיפים את Firebase לפרויקט
- איך תומכים בכניסה לאפליקציית Android
- איך בודקים את סטטוס האימות הנוכחי של האפליקציה
- איך מנתקים משתמשים
הפעולות שתבצעו:
- משתמשים במסוף Firebase כדי לשלב את Firebase באפליקציה.
- מטמיעים את תכונת ההתחברות.
- להוסיף התאמות אישיות באפליקציה למשתמשים שמחוברים.
- הטמעה של ניתוק המשתמשים מהמערכת.
מידע נוסף על LiveData ו-ViewModel
כדי להשתמש באפליקציה ב-codelab הזה, צריך להבין את המושגים הבסיסיים של LiveData ו-ViewModel. אם אתם רוצים לקבל סקירה כללית קצרה של המושגים האלה, כדאי לקרוא את הסקירות הכלליות על LiveData ועל ViewModel.
אפשר גם לעבור על הקורס Developing Android Apps with Kotlin (פיתוח אפליקציות ל-Android באמצעות Kotlin) כדי ללמוד על נושאים בסיסיים ב-Android שתיתקלו בהם כחלק מה-codelab הזה. הקורס הזה זמין גם כקורס ב-Udacity וגם כקורס ב-codelabs.
ב-codelab הזה תבנו אפליקציה שמציגה עובדות מעניינות על Android. חשוב מכך, באפליקציה יופיע לחצן כניסה/יציאה. כשהמשתמש מחובר לאפליקציה, כל עובדה שמוצגת באנדרואיד כוללת ברכה למשתמש, כדי להוסיף נופך אישי.

מורידים את האפליקציה לדוגמה. אפשר לעשות זאת באחת מהדרכים הבאות:
… או משכפלים את מאגר GitHub משורת הפקודה באמצעות הפקודה הבאה ועוברים להסתעפות start של המאגר:
$ git clone https://github.com/googlecodelabs/android-kotlin-login
חשוב: מכיוון שתשלבו את האפליקציה כדי להשתמש ב-Firebase, אפליקציית המתחילים דורשת הגדרה מסוימת כדי שניתן יהיה לבנות ולהפעיל אותה. תעשו את זה בשלב הבא של ה-codelab.
שלב 1: יצירת פרויקט Firebase
כדי להוסיף את Firebase לאפליקציית Android, צריך ליצור פרויקט Firebase שאליו תתחברו מאפליקציית Android.
- במסוף Firebase, לוחצים על הוספת פרויקט.
- בוחרים או מזינים שם פרויקט. אפשר לתת לפרויקט כל שם שרוצים, אבל כדאי לבחור שם שרלוונטי לאפליקציה שאתם מפתחים.
- לוחצים על המשך.
- אפשר לדלג על ההגדרה של Google Analytics ולבחור באפשרות לא כרגע.
- לוחצים על יצירת פרויקט כדי לסיים את ההגדרה של פרויקט Firebase.
שלב 2: רישום האפליקציה ב-Firebase
עכשיו, כשיש לכם פרויקט Firebase, אתם יכולים להוסיף אליו את אפליקציית Android.
- במרכז דף סקירת הפרויקט במסוף Firebase, לוחצים על סמל Android כדי להפעיל את תהליך ההגדרה.
- מזינים את מזהה האפליקציה של האפליקציה בשדה שם החבילה של Android. חשוב להזין את המזהה שבו האפליקציה משתמשת, כי אי אפשר להוסיף או לשנות את הערך הזה אחרי שמבצעים רישום של האפליקציה בפרויקט Firebase.
- מזהה אפליקציה נקרא לפעמים שם חבילה.
- מזהה האפליקציה מופיע בקובץ Gradle של המודול (ברמת האפליקציה), בדרך כלל
app/build.gradle(מזהה לדוגמה:com.yourcompany.yourproject). - מזינים את ה-SHA-1 של אישור החתימה של ניפוי הבאגים. כדי ליצור את המפתח הזה, מזינים את הפקודה הבאה בטרמינל של שורת הפקודה.
keytool -alias androiddebugkey -keystore ~/.android/debug.keystore -list -v -storepass android
- לוחצים על רישום האפליקציה.
שלב 3: מוסיפים את קובץ ההגדרות של Firebase לפרויקט
מוסיפים לאפליקציה את קובץ ההגדרות של Firebase ל-Android:
- לוחצים על Download google-services.json (הורדת קובץ google-services.json) כדי להוריד את קובץ התצורה של Firebase ל-Android (
google-services.json).
- אתם יכולים להוריד שוב את קובץ התצורה של Firebase Android בכל שלב.
- מוודאים שלא נוספו תווים לקובץ ההגדרות, וששמו הוא
google-services.jsonבלבד.
- מעבירים את קובץ ההגדרות לתיקיית המודול (ברמת האפליקציה) של האפליקציה.
שלב 4: הגדרת פרויקט Android כדי להפעיל מוצרים של Firebase
- כדי להפעיל מוצרים של Firebase באפליקציה, מוסיפים את הפלאגין google-services לקובצי Gradle.
- בקובץ Gradle ברמת השורש (ברמת הפרויקט) (
build.gradle), מוסיפים כללים להכללת הפלאגין של שירותי Google. כדאי גם לבדוק שיש לכם את מאגר Maven של Google.
build.gradle
buildscript {
repositories {
// Check that you have the following line (if not, add it):
google() // Google's Maven repository
}
dependencies {
// ...
// Add the following line:
classpath 'com.google.gms:google-services:4.3.0' // Google Services plugin
}
}
allprojects {
// ...
repositories {
// Check that you have the following line (if not, add it):
google() // Google's Maven repository
// ...
}
}- בקובץ Gradle של המודול (ברמת האפליקציה) (בדרך כלל
app/build.gradle), מוסיפים שורה לתחתית הקובץ.
app/build.gradle
apply plugin: 'com.android.application'
android {
// ...
}
// Add the following line to the bottom of the file:
apply plugin: 'com.google.gms.google-services' // Google Play services Gradle pluginשלב 4: מוסיפים תלות ב-Firebase
ב-codelab הזה, הסיבה העיקרית לשילוב של Firebase היא ליצור ולנהל משתמשים. לשם כך, צריך להוסיף ספריית Firebase שמאפשרת להטמיע התחברות.
- מוסיפים את התלות הבאה בקובץ
build.gradle (Module:app)כדי שתוכלו להשתמש ב-SDK באפליקציה. ה-SDKfirebase-authמאפשר לנהל משתמשים מאומתים באפליקציה.
app/build.gradle:
implementation 'com.firebaseui:firebase-ui-auth:5.0.0'- מסנכרנים את הפרויקט עם קובצי Gradle כדי לוודא שכל התלויות זמינות לאפליקציה. אם לא מוצגת בקשה, בוחרים באפשרות File > Sync Project with Gradle Files ב-Android Studio או בסרגל הכלים.
שלב 5: מריצים את האפליקציה ובודקים את הקוד
- מריצים את האפליקציה באמולטור או במכשיר פיזי כדי לוודא שהסביבה הוגדרה בהצלחה ומוכנה להתחלת הפיתוח.
אם הפעולה תצליח, במסך הבית יוצג נתון מעניין על Android ולחצן התחברות בפינה הימנית העליונה. הקשה על לחצן הכניסה לא גורמת לשום פעולה.
באופן כללי, זו אפליקציה עם פעילות אחת וכמה פרגמנטים. התמונה MainFragment מכילה את כל ממשק המשתמש שמופיע במסך למטה. (תעבדו עם LoginFragment ועם SettingsFragment ב-Codelab הבא).

- כדאי להכיר את הקוד. חשוב לשים לב במיוחד:
-
FirebaseUserLiveDataהיא המחלקה שתטמיעו כדי לצפות במשתמש הנוכחי ב-Firebase שמשויך לאפליקציה. תשתמשו במופעFirebaseAuthכנקודת כניסה כדי לקבל את פרטי המשתמש האלה בשלב מאוחר יותר. - הדומיין
MainFragmentמקושר אלLoginViewModel. LoginViewModelהיא המחלקה שתטמיעו כדי להשתמש ב-FirebaseUserLiveDataליצירת משתנהauthenticationState. באמצעות המשתנהauthenticationState, אפשר להבחין בערךMainFragmentולעדכן את ממשק המשתמש בהתאם.
בשלב הזה משתמשים במסוף Firebase כדי להגדיר את שיטות האימות שרוצים שהאפליקציה תתמוך בהן. ב-codelab הזה, תתמקדו במתן אפשרות למשתמשים להתחבר באמצעות כתובת אימייל שהם מספקים או באמצעות חשבון Google שלהם.
- עוברים אל מסוף Firebase. הערה: אם אתם עדיין בתהליך העבודה של הוספת Firebase, לוחצים על X בפינה הימנית העליונה כדי לחזור למסוף.
- בוחרים את הפרויקט הרצוי, אם עדיין לא נמצאים בו.
- פותחים את סרגל הניווט הימני ובוחרים באפשרות פיתוח > אימות .

- בסרגל הניווט העליון, בוחרים בכרטיסייה שיטת הכניסה.

- לוחצים על השורה אימייל/סיסמה.
- בחלון הקופץ, מעבירים את המתג מופעל למצב מופעל ולוחצים על שמירה.
- באופן דומה, לוחצים על השורה Google.
- מעבירים את המתג מופעל, מזינים אימייל לתמיכה בפרויקט ולוחצים על שמירה.
במשימה הזו נלמד איך להטמיע את תכונת הכניסה למשתמשים.
- פתיחת
MainFragment.kt. - בפריסה של
MainFragment, שימו לב לauth_button. נכון לעכשיו, הוא לא מוגדר לטפל בקלט משתמש. - ב-
onViewCreated(),מוסיפיםonClickListenerל-auth_buttonכדי להתקשר אלlaunchSignInFlow().
MainFragment.kt
binding.authButton.setOnClickListener { launchSignInFlow() }- מחפשים את השיטה
launchSignInFlow()ב-MainFragment.kt. הוא מכיל כרגעTODO. - משלימים את הפונקציה
launchSignInFlow()כמו שמוצג בהמשך.
MainFragment.kt
private fun launchSignInFlow() {
// Give users the option to sign in / register with their email or Google account.
// If users choose to register with their email,
// they will need to create a password as well.
val providers = arrayListOf(
AuthUI.IdpConfig.EmailBuilder().build(), AuthUI.IdpConfig.GoogleBuilder().build()
// This is where you can provide more ways for users to register and
// sign in.
)
// Create and launch sign-in intent.
// We listen to the response of this activity with the
// SIGN_IN_REQUEST_CODE
startActivityForResult(
AuthUI.getInstance()
.createSignInIntentBuilder()
.setAvailableProviders(providers)
.build(),
MainFragment.SIGN_IN_REQUEST_CODE
)
}כך המשתמשים יכולים להירשם ולהיכנס באמצעות כתובת האימייל או חשבון Google שלהם. אם המשתמש בוחר להירשם באמצעות כתובת האימייל שלו, השילוב של כתובת האימייל והסיסמה שהוא יוצר הוא ייחודי לאפליקציה שלכם. כלומר, הוא יוכל להתחבר לאפליקציה שלכם באמצעות השילוב של כתובת האימייל והסיסמה, אבל זה לא אומר שהוא יוכל להתחבר גם לכל אפליקציה אחרת שנתמכת על ידי Firebase באמצעות אותם פרטי כניסה.
- ב-
MainFragment.kt, אפשר להאזין לתוצאה של תהליך הכניסה על ידי הטמעה של השיטהonActivityResult(), כמו שמוצג בהמשך. מכיוון שהתחלת את תהליך הכניסה באמצעותSIGN_IN_REQUEST_CODE, אפשר גם להאזין לתוצאה של תהליך הכניסה על ידי סינון של המצב שבוSIGN_IN_REQUEST_CODEמועבר בחזרה אלonActivityResult(). כדאי להתחיל עם כמה הצהרות יומן כדי לדעת אם המשתמש נכנס בהצלחה.
MainFragment.kt
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == SIGN_IN_REQUEST_CODE) {
val response = IdpResponse.fromResultIntent(data)
if (resultCode == Activity.RESULT_OK) {
// User successfully signed in
Log.i(TAG, "Successfully signed in user ${FirebaseAuth.getInstance().currentUser?.displayName}!")
} else {
// Sign in failed. If response is null the user canceled the
// sign-in flow using the back button. Otherwise check
// response.getError().getErrorCode() and handle the error.
Log.i(TAG, "Sign in unsuccessful ${response?.error?.errorCode}")
}
}
}האפליקציה שלכם אמורה עכשיו לטפל ברישום של משתמשים ובכניסה שלהם לחשבון.
- מריצים את האפליקציה ומוודאים שהקשה על הלחצן התחברות פותחת את מסך ההתחברות.
- עכשיו אפשר להיכנס באמצעות כתובת האימייל והסיסמה, או באמצעות חשבון Google.
- לא יהיה שינוי בממשק המשתמש אחרי שתתחברו (תטמיעו את עדכון ממשק המשתמש בשלב הבא), אבל אם הכול פועל כמו שצריך, אחרי שתשלימו את תהליך ההרשמה תראו את הודעת היומן
Successfully signed in user ${your name}!. - אפשר גם להיכנס למסוף Firebase ולעבור אל Develop > Authentication > Users כדי לוודא שיש לאפליקציה משתמש רשום אחד.
- חשוב לזכור שכאשר משתמשים יוצרים חשבון באפליקציה שלכם, החשבון הזה משויך רק לאפליקציה הזו, ולא לאפליקציות אחרות שמשתמשות ב-Firebase לצורך פונקציונליות ההתחברות.
במשימה הזו תטמיעו עדכון של ממשק המשתמש על סמך מצב האימות. אחרי שהמשתמש מתחבר, אפשר להתאים אישית את מסך הבית שלו ולהציג בו את השם שלו. בנוסף, תעדכנו את הלחצן כניסה ללחצן יציאה כשהמשתמש מחובר לחשבון.
- פותחים את הכיתה
FirebaseUserLiveData.ktשכבר נוצרה בשבילכם. הדבר הראשון שצריך לעשות הוא לספק דרך לכיתות אחרות באפליקציה לדעת מתי משתמש התחבר או התנתק. עם זאת, המחלקה לא עושה כלום כי הערך שלLiveDataלא מתעדכן. - מכיוון שאתם משתמשים בספרייה
FirebaseAuth, אתם יכולים להאזין לשינויים במשתמש המחובר באמצעות הקריאה החוזרתFirebaseUser.AuthStateListenerשמוטמעת עבורכם כחלק מהספרייה FirebaseUI. הקריאה החוזרת (callback) הזו מופעלת בכל פעם שמשתמש מתחבר לאפליקציה או מתנתק ממנה. - שימו לב שהתג
FirebaseUserLiveData.ktמגדיר את המשתנהauthStateListener. המשתנה הזה ישמש לאחסון הערך שלLiveData. המשתנהauthStateListenerנוצר כדי שתוכלו להתחיל ולהפסיק את ההאזנה לשינויים במצב האימות בצורה נכונה, בהתאם למצב האפליקציה. לדוגמה, אם המשתמש מעביר את האפליקציה לרקע, האפליקציה צריכה להפסיק להאזין לשינויים בסטטוס האימות כדי למנוע דליפות זיכרון פוטנציאליות. - מעדכנים את
authStateListenerכך שהערך שלFirebaseUserLiveDataיתאים למשתמש הנוכחי ב-Firebase.
FirebaseUserLiveData.kt
private val authStateListener = FirebaseAuth.AuthStateListener { firebaseAuth ->
value = firebaseAuth.currentUser
}- פתיחת
LoginViewModel.kt. - ב-
LoginViewModel.kt, יוצרים משתנהauthenticationStateעל סמך אובייקטFirebaseUserLiveDataשהטמעתם זה עתה. יצירת המשתנהauthenticationStateמאפשרת למחלקות אחרות לשלוח שאילתות כדי לבדוק אם המשתמש מחובר או לא דרךLoginViewModel.
LoginViewModel.kt
val authenticationState = FirebaseUserLiveData().map { user ->
if (user != null) {
AuthenticationState.AUTHENTICATED
} else {
AuthenticationState.UNAUTHENTICATED
}
}- פתיחה של
MainFragment.kt. - ב-
MainFragment.kt'sobserveAuthenticationState()אפשר להשתמש במשתנהauthenticationStateשזה עתה הוספתם ב-LoginViewModelולשנות את ממשק המשתמש בהתאם. אם יש משתמש מחובר,authButtonצריך להציג את האפשרות התנתקות.
MainFragment.kt
private fun observeAuthenticationState() {
val factToDisplay = viewModel.getFactToDisplay(requireContext())
viewModel.authenticationState.observe(viewLifecycleOwner, Observer { authenticationState ->
when (authenticationState) {
LoginViewModel.AuthenticationState.AUTHENTICATED -> {
binding.authButton.text = getString(R.string.logout_button_text)
binding.authButton.setOnClickListener {
// TODO implement logging out user in next step
}
// TODO 2. If the user is logged in,
// you can customize the welcome message they see by
// utilizing the getFactWithPersonalization() function provided
}
else -> {
// TODO 3. Lastly, if there is no logged-in user,
// auth_button should display Login and
// launch the sign in screen when clicked.
}
}
})
}- אם המשתמש מחובר, אפשר גם להתאים אישית את הודעת הפתיחה שהוא רואה באמצעות הפונקציה
getFactWithPersonalization()שמופיעה ב-MainFragment.
MainFragment.kt
binding.welcomeText.text = getFactWithPersonalization(factToDisplay)- לבסוף, אם אין משתמש מחובר (כאשר
authenticationStateהוא כל ערך אחר מלבדLoginViewModel.AuthenticationState.AUTHENTICATED),auth_buttonצריך להציג את התחברות ולהפעיל את מסך הכניסה כשלוחצים עליו. בנוסף, אסור שההודעה שמוצגת תהיה מותאמת אישית.
MainFragment.kt
binding.authButton.text = getString(R.string.login_button_text)
binding.authButton.setOnClickListener { launchSignInFlow() }
binding.welcomeText.text = factToDisplayאחרי השלמת כל השלבים, הפונקציה הסופית observeAuthenticationState() אמורה להיראות כמו הקוד שבהמשך.
MainFragment.kt
private fun observeAuthenticationState() {
val factToDisplay = viewModel.getFactToDisplay(requireContext())
viewModel.authenticationState.observe(viewLifecycleOwner, Observer { authenticationState ->
// TODO 1. Use the authenticationState variable you just added
// in LoginViewModel and change the UI accordingly.
when (authenticationState) {
// TODO 2. If the user is logged in,
// you can customize the welcome message they see by
// utilizing the getFactWithPersonalization() function provided
LoginViewModel.AuthenticationState.AUTHENTICATED -> {
binding.welcomeText.text = getFactWithPersonalization(factToDisplay)
binding.authButton.text = getString(R.string.logout_button_text)
binding.authButton.setOnClickListener {
// TODO implement logging out user in next step
}
}
else -> {
// TODO 3. Lastly, if there is no logged-in user,
// auth_button should display Login and
// launch the sign in screen when clicked.
binding.welcomeText.text = factToDisplay
binding.authButton.text = getString(R.string.login_button_text)
binding.authButton.setOnClickListener {
launchSignInFlow()
}
}
}
})
}- מריצים את האפליקציה. ממשק המשתמש אמור להתעדכן בהתאם למצב הכניסה של המשתמש. אם הכול פועל כמו שצריך ואתם מחוברים, במסך הבית אמור להופיע השם שלכם בנוסף לעובדה על Android. במקום הלחצן התחברות, אמור להופיע עכשיו הלחצן התנתקות.

במשימה הזו תטמיעו את תכונת היציאה מהחשבון.
אם האפליקציה מאפשרת למשתמשים להתחבר, היא צריכה גם לספק להם דרך להתנתק. הנה דוגמה לאופן שבו מתנתקים ממשתמש באמצעות שורה אחת בלבד של קוד:
AuthUI.getInstance().signOut(requireContext())- פתיחת
MainFragment.kt. - ב-
MainFragment.kt, בקטעobserveAuthenticationState(), מוסיפים את הלוגיקה של היציאה מהחשבון כדי שהפונקציותauth_buttonיפעלו בצורה תקינה כשמשתמש מחובר לחשבון. התוצאה הסופית של השיטה נראית כמו הקוד שבהמשך.
MainFragment.kt
private fun observeAuthenticationState() {
val factToDisplay = viewModel.getFactToDisplay(requireContext())
viewModel.authenticationState.observe(viewLifecycleOwner, Observer { authenticationState ->
when (authenticationState) {
LoginViewModel.AuthenticationState.AUTHENTICATED -> {
binding.welcomeText.text = getFactWithPersonalization(factToDisplay)
binding.authButton.text = getString(R.string.logout_button_text)
binding.authButton.setOnClickListener {
AuthUI.getInstance().signOut(requireContext())
}
}
else -> {
binding.welcomeText.text = factToDisplay
binding.authButton.text = getString(R.string.login_button_text)
binding.authButton.setOnClickListener {
launchSignInFlow()
}
}
}
})
}- מפעילים את האפליקציה.
- מקישים על הלחצן יציאה ומוודאים שהמשתמש יצא מהחשבון, ושהמצב של הלחצן משתנה לכניסה.

הגרסה הסופית של האפליקציה המלאה זמינה כאן: https://github.com/googlecodelabs/android-kotlin-login.
ב-codelab הזה למדתם:
- איך מוסיפים את Firebase לפרויקט על ידי הוספת התלויות הנדרשות בקובץ gradle והגדרת הפרויקט במסוף Firebase.
- איך להטמיע כניסה לאפליקציה באמצעות ספריית FirebaseUI ולציין איך רוצים לאפשר למשתמשים להיכנס. חשוב לדעת שכל חשבון שמשתמש יוצר באפליקציה שלכם הוא ספציפי לאפליקציה הזו בלבד, ולא משותף עם כל האפליקציות שמשתמשות ב-Firebase לצורך פונקציונליות ההתחברות.
- איך בודקים את סטטוס האימות הנוכחי של האפליקציה באמצעות
LiveData. - איך מנתקים משתמשים מהמערכת.
ב-codelab הזה למדנו את עקרונות הבסיס של תמיכה בכניסה לאפליקציית Android.
ב-codelab הזה אפשרתם למשתמשים להירשם ולבצע כניסה באמצעות כתובת האימייל שלהם. עם זאת, באמצעות ספריית FirebaseUI אפשר לתמוך גם בשיטות אימות אחרות, כמו כניסה באמצעות מספר טלפון. כדי לקבל מידע נוסף על היכולות של ספריית FirebaseUI ועל פונקציות אחרות שהיא מספקת, אפשר לעיין במקורות המידע הבאים:
למידע נוסף על שיטות מומלצות בנושא התחברות, אפשר לעיין במקורות המידע הבאים:
Codelabs:
מסמכי תיעוד למפתחי Android:
סרטי וידאו:
קישורים למדריכי Codelab נוספים בקורס הזה זמינים בדף הנחיתה של מדריכי Codelab בנושא Android מתקדם ב-Kotlin.