Эта практическая работа входит в курс «Advanced Android in Kotlin». Вы получите максимальную пользу от этого курса, выполняя задания последовательно, но это не обязательно. Все практическая работа курса перечислены на целевой странице практической работы «Advanced Android in Kotlin» .
Введение
При разработке приложения для Android поддержка входа пользователей может дать множество преимуществ. Позволяя пользователям создавать учетные записи в приложении, вы предоставляете им больше способов взаимодействия с приложением.
С помощью персонализированных учетных записей пользователи могут настраивать свой опыт использования приложения, взаимодействовать с другими пользователями, а также сохранять и переносить свои данные, если они используют приложение на другом устройстве (например, в Интернете или на новом телефоне).
В этой лабораторной работе вы изучите основы поддержки входа в приложение с помощью библиотеки FirebaseUI . Помимо прочего, библиотека FirebaseUI упрощает разработчикам создание процесса входа в систему и берёт на себя управление учётными записями пользователей.
Что вам уже следует знать
- Основы создания приложения для Android
- LiveData и ViewModel
Чему вы научитесь
- Как добавить Firebase в свой проект
- Как обеспечить поддержку входа в приложение Android
- Как проверить текущий статус аутентификации вашего приложения
- Как вывести пользователей из системы
Что ты будешь делать?
- Используйте консоль Firebase для интеграции Firebase в ваше приложение.
- Реализуйте функцию входа в систему.
- Добавьте настройки в приложение для пользователей, вошедших в систему.
- Реализовать выход пользователей из системы.
Узнайте больше о LiveData и ViewModel
Для приложения в этой практической работе вам потребуется базовое понимание LiveData и ViewModel. Ознакомьтесь с обзорами LiveData и ViewModel , чтобы получить краткий обзор этих концепций.
Вы также можете пройти курс «Разработка приложений для Android на Kotlin», чтобы узнать об основных темах Android, с которыми вы столкнётесь в рамках этой практической работы. Этот курс доступен как в формате курса Udacity , так и в формате практической работы .
В этой лабораторной работе вы создадите приложение, отображающее интересные факты об Android. Что ещё важнее, в приложении будет кнопка входа/выхода . Когда пользователь войдет в приложение, любой отображаемый факт об Android будет содержать приветствие, что позволит персонализировать его.


Загрузить пример приложения можно одним из следующих способов:
... или клонируйте репозиторий GitHub из командной строки, используя следующую команду, и переключитесь на start ветку репозитория:
$ git clone https://github.com/googlecodelabs/android-kotlin-login
Важно: поскольку вы будете интегрировать приложение с Firebase, для сборки и запуска стартового приложения потребуется некоторая настройка. Это будет сделано на следующем этапе практического занятия.
Шаг 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 в свое приложение:
- Нажмите «Загрузить google-services.json» , чтобы получить файл конфигурации Firebase Android (
google-services.json).
- Вы можете снова загрузить файл конфигурации Firebase Android в любое время.
- Убедитесь, что файл конфигурации не дополнен дополнительными символами и должен иметь только имя
google-services.json
- Переместите файл конфигурации в каталог модуля (уровня приложения) вашего приложения.
Шаг 4: Настройте свой проект Android для включения продуктов Firebase
- Чтобы включить продукты Firebase в свое приложение, добавьте плагин google-services в файлы Gradle.
- В файле Gradle корневого уровня (уровня проекта) (
build.gradle) добавьте правила для включения плагина Google Services. Также убедитесь, что у вас есть репозиторий 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) добавьте строку в конец файла.
приложение/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
В этой лабораторной работе основной целью интеграции Firebase является создание и управление пользователями. Для этого необходимо добавить библиотеку Firebase, которая позволит реализовать вход в систему.
- Добавьте следующую зависимость в файл
build.gradle (Module:app), чтобы использовать SDK в вашем приложении. SDKfirebase-authпозволяет управлять аутентифицированными пользователями вашего приложения.
приложение/build.gradle:
implementation 'com.firebaseui:firebase-ui-auth:5.0.0'- Синхронизируйте свой проект с файлами Gradle, чтобы убедиться, что все зависимости доступны вашему приложению. Если запрос не появится, выберите «Файл» > «Синхронизировать проект с файлами Gradle» в Android Studio или на панели инструментов.
Шаг 5: Запустите приложение и проверьте код.
- Запустите приложение на эмуляторе или физическом устройстве, чтобы убедиться, что ваша среда успешно настроена для начала разработки.
В случае успеха на главном экране вы увидите интересный факт об Android и кнопку входа в левом верхнем углу. Нажатие на кнопку входа пока ничего не даёт.
На высоком уровне это приложение с одним действием и несколькими фрагментами. MainFragment содержит весь пользовательский интерфейс, который вы видите на экране ниже. (Вы будете работать с LoginFragment и SettingsFragment в следующей лабораторной работе.)

- Ознакомьтесь с кодом. В частности, обратите внимание на:
-
FirebaseUserLiveData— это класс, который вы реализуете для отслеживания текущего пользователя Firebase, связанного с приложением. ЭкземплярFirebaseAuthбудет использоваться в качестве точки входа для получения информации об этом пользователе на следующем этапе. -
MainFragmentпривязан кLoginViewModel.LoginViewModel— это класс, который вы реализуете, чтобы использоватьFirebaseUserLiveDataдля создания переменнойauthenticationState. Используя эту переменнуюauthenticationState,MainFragmentможет отслеживать значение и соответствующим образом обновлять пользовательский интерфейс.
На этом этапе вы будете использовать Firebase Console для настройки методов аутентификации, которые должно поддерживать ваше приложение. В этой лабораторной работе вы сосредоточитесь на том, чтобы пользователи могли входить в систему, используя предоставленный ими адрес электронной почты или учётную запись 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 и перейти в раздел Разработка > Аутентификация > Пользователи , чтобы проверить, что теперь в приложении зарегистрирован один пользователь.
- Обратите внимание, что когда пользователи создают учетную запись для вашего приложения, эта учетная запись привязывается только к вашему приложению, а не к любому другому приложению, использующему Firebase для функции входа в систему.
В этой задаче вы реализуете обновление пользовательского интерфейса в зависимости от состояния аутентификации. Когда пользователь вошел в систему, вы можете персонализировать его главный экран, отображая его имя. Вы также измените кнопку «Войти» на кнопку «Выйти» , когда пользователь вошел в систему.
- Откройте класс
FirebaseUserLiveData.kt, который уже создан. Первое, что вам нужно сделать, — это предоставить другим классам приложения возможность узнавать, когда пользователь вышел из системы или вошел в нее. Однако этот класс пока ничего не делает, поскольку значениеLiveDataне обновляется. - Поскольку вы используете библиотеку
FirebaseAuth, вы можете отслеживать изменения состояния вошедшего в систему пользователя с помощью обратного вызоваFirebaseUser.AuthStateListener, реализованного в библиотеке FirebaseUI. Этот обратный вызов срабатывает при каждом входе или выходе пользователя из вашего приложения. - Обратите внимание, что в
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. - В методе
observeAuthenticationState()MainFragment.ktвы можете использовать переменнуюauthenticationStateтолько что добавленную вLoginViewModel, и соответствующим образом изменить пользовательский интерфейс. Если пользователь вошел в систему,authButtonдолжен отображать Logout .
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должна отображать «Login» и запускать экран входа при нажатии. Также не должно быть персонализации отображаемого сообщения.
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. - В методе
observeAuthenticationState()объектаMainFragment.ktдобавьте логику выхода из системы, чтобы кнопка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 .
В этой лабораторной работе вы узнали:
- Как добавить Firebase в свой проект, добавив необходимые зависимости в файл Gradle и настроив проект в консоли Firebase.
- Как реализовать вход в приложение с помощью библиотеки FirebaseUI и указать, как вы хотите разрешить пользователям входить в систему. Обратите внимание, что любая учётная запись, создаваемая пользователем в вашем приложении, относится только к вашему приложению и не является общей для всех приложений, использующих Firebase для входа в систему.
- Как отслеживать текущий статус аутентификации вашего приложения с помощью
LiveData. - Как вывести пользователей из системы.
В этой лабораторной работе были рассмотрены основы поддержки входа в приложение Android.
В этой лабораторной работе вы разрешили пользователям регистрироваться и входить в систему, используя свой адрес электронной почты. Однако библиотека FirebaseUI также поддерживает другие методы аутентификации, например, вход по номеру телефона. Чтобы узнать больше о возможностях библиотеки FirebaseUI и о том, как использовать другие её функции, ознакомьтесь со следующими ресурсами:
Дополнительную информацию о передовых методах входа в систему можно найти на следующих ресурсах:
Кодлабы:
Документация для разработчиков Android:
Видео:
Ссылки на другие практические занятия по этому курсу см. на целевой странице практических занятий по курсу Advanced Android in Kotlin.