To ćwiczenie programowania jest częścią kursu „Android dla zaawansowanych w Kotlinie”. Korzyści z tego kursu będą dla Ciebie najbardziej wartościowe, jeśli wykonasz je w sekwencjach ćwiczeń z programowania, ale nie jest to obowiązkowe. Wszystkie ćwiczenia z kursu są wymienione na stronie Zaawansowane ćwiczenia z programowania na Androida w Kotlin.
Wstęp
Tworzenie aplikacji na Androida daje użytkownikom wiele korzyści z logowania. Jeśli zezwolisz użytkownikom na tworzenie tożsamości w aplikacji, zyskasz więcej możliwości interakcji z nią.
Dzięki spersonalizowanym kontom użytkownicy mogą dostosować sposób korzystania z aplikacji, nawiązać kontakt z innymi użytkownikami oraz zachować swoje dane i przenieść je, jeśli używają aplikacji na innym urządzeniu (np. w przeglądarce lub na nowym telefonie).
Z tego modułu dowiesz się, jak obsługiwać logowanie się w aplikacji przy użyciu biblioteki FirebaseUI. Biblioteka FirebaseUI ułatwia m.in. tworzenie aplikacji i przepływ pracy związanych z zarządzaniem kontami użytkowników.
Co musisz wiedzieć
- Podstawy tworzenia aplikacji na Androida
- LiveData i ModelModel
Czego się nauczysz
- Jak dodać Firebase do projektu
- Jak obsługiwać logowanie do aplikacji na Androida
- Jak sprawdzić obecny stan uwierzytelniania aplikacji
- Jak wylogować użytkowników
Jakie zadania wykonasz:
- Aby zintegrować Firebase z aplikacją, użyj konsoli Firebase.
- Zaimplementuj funkcję logowania.
- Dodaj dostosowania w aplikacji dla zalogowanych użytkowników.
- Wdrażanie wylogowania użytkowników.
Więcej informacji o LiveData i ViewModel
W przypadku tego ćwiczenia z programowania musisz znać podstawy LiveData i ViewModel. Przeczytaj też omówienie LiveData i ViewModel, jeśli chcesz zapoznać się z tymi zagadnieniami.
Możesz też zapoznać się z kursem Tworzenie aplikacji na Androida z Kotlin, by poznać podstawowe tematy związane z Androidem, które znajdziesz podczas tego ćwiczenia. Ten kurs jest dostępny w ramach kursu Udacity i ćwiczeń z programowania.
W tym ćwiczeniu utworzysz aplikację, która będzie pokazywać zabawne fakty na temat Androida. Co ważniejsze, aplikacja będzie miała przycisk Login/Wyloguj. Gdy użytkownik zaloguje się w aplikacji, wszystkie wyświetlane informacje o Androidzie będą zawierać powitanie dla użytkownika, co umożliwia dodanie personalizacji.
Pobierz przykładową aplikację:
... lub skopiuj repozytorium GitHub z wiersza poleceń, używając poniższego polecenia, i przejdź do gałęzi start
repozytorium:
$ git clone https://github.com/googlecodelabs/android-kotlin-login
Ważne: ponieważ będziesz integrować aplikacje tak, aby korzystały z Firebase, aplikacja wstępna wymaga pewnej konfiguracji, aby mogła zostać utworzona i uruchomiona. Zrobisz to w następnym kroku ćwiczenia.
Krok 1. Utwórz projekt Firebase
Zanim dodasz Firebase do swojej aplikacji na Androida, musisz utworzyć projekt Firebase i połączyć się z aplikacją na Androida.
- W konsoli Firebase kliknij Dodaj projekt.
- Wybierz lub wpisz nazwę projektu. Możesz nadać projektowi dowolną nazwę, ale postaraj się wybrać nazwę zgodną z aplikacją, którą tworzysz.
- Kliknij Dalej.
- Możesz pominąć konfigurowanie Google Analytics i wybrać opcję Nie teraz.
- Kliknij Utwórz projekt, aby zakończyć konfigurowanie projektu Firebase.
Krok 2. Zarejestruj aplikację w Firebase
Po utworzeniu projektu Firebase możesz dodać do niego aplikację na Androida.
- Na środku strony podsumowania projektu w konsoli Firebase kliknij ikonę Androida, aby uruchomić przepływ konfiguracji.
- Wpisz identyfikator aplikacjiaplikacji w polu nazwa pakietu na Androida. Wpisz identyfikator, którego używa Twoja aplikacja, ponieważ nie możesz jej dodać ani zmienić po zarejestrowaniu aplikacji w projekcie Firebase.
- Identyfikator aplikacji jest czasem nazywany nazwą pakietu.
- Znajdź ten identyfikator aplikacji w pliku Gradle modułu (na poziomie aplikacji), zwykle
app/build.gradle
(przykładowy identyfikator:com.yourcompany.yourproject
). - Wpisz certyfikat SHA-1 do podpisania aplikacji. Możesz wygenerować ten klucz, wpisując następujące polecenie w terminalu wiersza poleceń:
keytool -alias androiddebugkey -keystore ~/.android/debug.keystore -list -v -storepass android
- Kliknij Zarejestruj aplikację.
Krok 3. Dodaj plik konfiguracji Firebase do projektu
Dodaj do aplikacji plik konfiguracji Firebase na Androida:
- Kliknij Pobierz google-services.json, aby uzyskać plik konfiguracyjny Firebase na Androida (
google-services.json
).
- W każdej chwili możesz ponownie pobrać plik konfiguracyjny Firebase na Androida.
- Upewnij się, że plik konfiguracji nie zawiera dodatkowych znaków i powinien mieć tylko nazwę
google-services.json
.
- Przenieś plik konfiguracyjny do katalogu modułu (na poziomie aplikacji) aplikacji.
Krok 4. Skonfiguruj projekt na Androida, aby włączyć usługi Firebase
- Aby włączyć usługi Firebase w aplikacji, dodaj wtyczkę google-services do plików Gradle.
- W pliku Gradle na poziomie projektu (
build.gradle
) dodaj reguły, by uwzględnić wtyczkę Google Services. Sprawdź też, czy masz repozytorium Maven.
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
// ...
}
}
- W pliku Gradle modułu (na poziomie aplikacji) (zazwyczaj
app/build.gradle
) dodaj wiersz na dole pliku.
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
Krok 4. Dodaj zależność z Firebase
W ramach tych ćwiczeń głównym celem integracji Firebase jest tworzenie kont użytkowników i zarządzanie nimi. Aby to zrobić, musisz dodać bibliotekę Firebase umożliwiającą implementację logowania.
- Dodaj ten zależność w pliku
build.gradle (Module:app)
, aby móc używać pakietu SDK w aplikacji. Pakiet SDKfirebase-auth
umożliwia zarządzanie uwierzytelnionymi użytkownikami Twojej aplikacji.
app/build.gradle:
implementation 'com.firebaseui:firebase-ui-auth:5.0.0'
- Zsynchronizuj swój projekt z plikami Gradle, aby mieć pewność, że wszystkie zależności są dostępne dla aplikacji. Jeśli nie pojawi się taka prośba, wybierz File > Sync Project with Gradle Files w menu Android Studio lub na pasku narzędzi.
Krok 5. Uruchom aplikację i sprawdź kod
- Uruchom aplikację w emulatorze lub na fizycznym urządzeniu, aby upewnić się, że środowisko zostało skonfigurowane tak, by można było rozpocząć programowanie.
Jeśli wszystko się uda, na ekranie głównym powinien wyświetlić się ciekawostka dotycząca Androida i przycisk logowania w lewym górnym rogu. Naciśnięcie przycisku logowania jeszcze nic nie robi.
Ogólnie rzecz biorąc, jest to aplikacja z jedną aktywnością z wieloma fragmentami. MainFragment
zawiera wszystkie elementy interfejsu, które widzisz na ekranie poniżej. (Będziesz ćwiczyć LoginFragment
i SettingsFragment
podczas kolejnego kursu).
- Zapoznaj się z tym kodem. Zwróć uwagę na te kwestie:
FirebaseUserLiveData
to klasa, którą wdrożysz, aby obserwować bieżącego użytkownika Firebase powiązanego z aplikacją. Wykorzystasz instancjęFirebaseAuth
jako punkt wejścia, aby uzyskać te informacje o użytkowniku w późniejszym kroku.MainFragment
remisuje zLoginViewModel
.LoginViewModel
to klasa, którą wdrożysz, aby użyć zmiennejFirebaseUserLiveData
do utworzenia zmiennejauthenticationState
. Korzystając z tej zmiennejauthenticationState
,MainFragment
może następnie zauważyć wartość, aby odpowiednio zaktualizować interfejs użytkownika.
W tym kroku skonfigurujesz w konsoli Firebase metody uwierzytelniania, które ma obsługiwać Twoja aplikacja. W ramach tego ćwiczenia skupisz się na umożliwieniu użytkownikom logowania się przy użyciu podanego przez nich adresu e-mail lub konta Google.
- Otwórz konsolę Firebase. (Uwaga: jeśli nadal korzystasz z procesu dodawania Firebase, kliknij X w lewym górnym rogu, aby wrócić do konsoli.
- Wybierz projekt, jeśli jeszcze nie jesteś w jego projekcie.
- W menu po lewej stronie wybierz Developer > Authentication (Rozwijanie uwierzytelniania).
- Wybierz kartę Metoda logowania na górnym pasku nawigacyjnym.
- Kliknij wiersz E-mail / Hasło.
- W wyskakującym okienku włącz przełącznik Włączony i kliknij Zapisz.
- Kliknij też wiersz Google.
- Kliknij przełącznik Włączony, wpisz adres e-mail pomocy dla projektu i kliknij Zapisz.
W tym zadaniu wdrożysz funkcję logowania dla użytkowników.
- Otwórz aplikację
MainFragment.kt
. - Spójrz na układ
MainFragment
iauth_button
. Obecnie nie jest skonfigurowana do obsługi danych wejściowych użytkownika. - W aplikacji
onViewCreated(),
dodaj:onClickListener
do:auth_button
, by zadzwonić pod numerlaunchSignInFlow()
.
GłównyFragment.kt
binding.authButton.setOnClickListener { launchSignInFlow() }
- Znajdź metodę
launchSignInFlow()
wMainFragment.kt
. Obecnie zawieraTODO
. - Wykonaj podaną niżej funkcję
launchSignInFlow()
.
GłównyFragment.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
)
}
Dzięki temu mogą rejestrować się i logować przy użyciu adresu e-mail lub konta Google. Jeśli użytkownik zdecyduje się zarejestrować za pomocą swojego adresu e-mail, utworzona przez niego kombinacja adresu e-mail i hasła jest unikalna dla Twojej aplikacji. Będzie on mógł logować się do Twojej aplikacji za pomocą kombinacji adresu e-mail i hasła, ale nie oznacza to, że będą mogli logować się do dowolnej innej aplikacji obsługiwanej przez Firebase za pomocą tych samych danych logowania.
- W usłudze
MainFragment.kt
możesz sprawdzić wynik logowania, stosując metodęonActivityResult()
, jak pokazano poniżej. Rozpoczęłeś proces logowania wSIGN_IN_REQUEST_CODE
, więc możesz też odsłuchać przebieg procesu logowania, filtrując, gdySIGN_IN_REQUEST_CODE
zostanie zwrócony doonActivityResult()
. Zacznij od dodania do instrukcji logowania informacji o tym, czy użytkownik zalogował się prawidłowo.
GłównyFragment.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}")
}
}
}
Twoja aplikacja powinna już obsługiwać rejestrację i logowanie użytkowników.
- Uruchom aplikację i sprawdź, czy dotknięcie przycisku Login (Zaloguj się) powoduje wyświetlenie ekranu logowania.
- Możesz teraz logować się za pomocą adresu e-mail i hasła lub konta Google.
- Po zalogowaniu się nic się nie zmieni (w następnym kroku wdrożysz interfejs użytkownika). Jeśli jednak wszystko działa prawidłowo, po zakończeniu procesu rejestracji powinien pojawić się komunikat
Successfully signed in user ${your name}!
. - Możesz też otworzyć konsolę Firebase i przejść do sekcji Programowanie > Uwierzytelnianie > Użytkownicy, aby sprawdzić, czy aplikacja ma teraz jednego zarejestrowanego użytkownika.
- Pamiętaj, że gdy użytkownicy tworzą konto do Twojej aplikacji, jest ono powiązane tylko z Twoją aplikacją, a nie z żadną aplikacją korzystającą z Firebase do obsługi logowania.
W tym zadaniu wdrożysz aktualizowanie interfejsu na podstawie stanu uwierzytelniania. Gdy użytkownik jest zalogowany, możesz spersonalizować jego ekran główny, wyświetlając jego nazwę. Zaktualizujesz też przycisk Zaloguj, gdy będzie zalogowany(-a) jako Wyloguj.
- Otwórz zajęcia
FirebaseUserLiveData.kt
, które zostały już dla Ciebie utworzone. Najpierw musisz udostępnić w innej aplikacji informacje o tym, kiedy użytkownicy są zalogowani lub wylogowani. Klasa nie może jednak nic zrobić, ponieważ wartość elementuLiveData
nie jest aktualizowana. - Ponieważ używasz biblioteki
FirebaseAuth
, możesz słuchać zmian dotyczących zalogowanego użytkownika za pomocą wywołania zwrotnegoFirebaseUser.AuthStateListener
, które znajdziesz w bibliotece FirebaseUI. To wywołanie zwrotne jest wywoływane za każdym razem, gdy użytkownik się zaloguje lub wyloguje z Twojej aplikacji. - Zwróć uwagę, że
FirebaseUserLiveData.kt
określa zmiennąauthStateListener
. Użyjesz tej zmiennej do przechowywania wartości właściwościLiveData
. ZmiennaauthStateListener
została utworzona, by prawidłowo rozpoczynać i zatrzymywać słuchanie zmian w stanie uwierzytelniania na podstawie stanu aplikacji. Jeśli na przykład użytkownik umieści aplikację w tle, aplikacja powinna przestać nasłuchiwać zmian w stanie uwierzytelniania, aby zapobiec ewentualnym wyciekom pamięci. - Zaktualizuj wartość
authStateListener
, by wartośćFirebaseUserLiveData
odpowiadała wartości bieżącego użytkownika Firebase.
FirebaseUserLiveData.kt
private val authStateListener = FirebaseAuth.AuthStateListener { firebaseAuth ->
value = firebaseAuth.currentUser
}
- Otwórz aplikację
LoginViewModel.kt
. - W
LoginViewModel.kt
utwórz zmiennąauthenticationState
na podstawie właśnie wdrożonego obiektuFirebaseUserLiveData
. Po utworzeniu tej zmiennejauthenticationState
inne klasy mogą teraz wysyłać zapytanie o to, czy użytkownik jest zalogowany za pomocąLoginViewModel
.
LoginViewModel.kt,
val authenticationState = FirebaseUserLiveData().map { user ->
if (user != null) {
AuthenticationState.AUTHENTICATED
} else {
AuthenticationState.UNAUTHENTICATED
}
}
- Otwórz:
MainFragment.kt.
- W przeglądarce
MainFragment.kt
observeAuthenticationState()
możesz użyć zmiennejauthenticationState
dodanej przed chwilą wLoginViewModel
i odpowiednio zmienić interfejs. W przypadku zalogowanych użytkownikówauthButton
powinien wyświetlać się Wyloguj.
GłównyFragment.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.
}
}
})
}
- Jeśli użytkownik jest zalogowany, możesz też dostosować komunikat powitalny, używając funkcji
getFactWithPersonalization()
dostępnej wMainFragment
.
GłównyFragment.kt
binding.welcomeText.text = getFactWithPersonalization(factToDisplay)
- Jeśli nie ma zalogowanego użytkownika (gdy
authenticationState
ma wartość inną niżLoginViewModel.AuthenticationState.AUTHENTICATED
),auth_button
powinien wyświetlić Login i zalogować się, a następnie kliknąć ekran logowania. Wiadomość nie powinna też być personalizowana.
GłównyFragment.kt
binding.authButton.text = getString(R.string.login_button_text)
binding.authButton.setOnClickListener { launchSignInFlow() }
binding.welcomeText.text = factToDisplay
Po wykonaniu wszystkich kroków ostateczna metoda observeAuthenticationState()
powinna wyglądać podobnie do poniższego kodu.
GłównyFragment.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()
}
}
}
})
}
- Uruchom aplikację. Interfejs powinien być aktualizowany w zależności od tego, czy użytkownik jest zalogowany. Jeśli wszystko działa prawidłowo i jesteś zalogowany, ekran główny nie tylko powinien wyświetlić komunikat o Androidzie, ale też zawierać Twoje imię i nazwisko. Przycisk Login (Zaloguj się) powinien teraz pokazywać Wyloguj.
W tym zadaniu wdrożysz funkcję wylogowania.
Ponieważ aplikacja umożliwia logowanie, użytkownicy powinni mieć możliwość wylogowania się. Oto przykład wylogowywania użytkownika z jednym wierszem kodu:
AuthUI.getInstance().signOut(requireContext())
- Otwórz aplikację
MainFragment.kt
. - W sekcji
MainFragment.kt
observeAuthenticationState()
dodaj logi wylogowania, abyauth_button
działał prawidłowo, gdy zalogowany użytkownik jest zalogowany. Końcowy wynik metody wygląda tak:
GłównyFragment.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()
}
}
}
})
}
- Uruchom aplikację.
- Kliknij przycisk Wyloguj się i sprawdź, czy użytkownik jest wylogowany, a jego stan zmieni się na Logowanie.
Ostateczną wersję gotowej aplikacji znajdziesz tutaj: https://github.com/googlecodelabs/android-kotlin-login.
Dzięki niemu dowiesz się:
- Jak dodać do projektu Firebase z użyciem niezbędnych zależności w pliku Gradle i skonfigurować projekt w konsoli Firebase.
- Jak zaimplementować logowanie się w aplikacji za pomocą biblioteki FirebaseUI i określić, jak chcesz zezwolić użytkownikom na logowanie się. Pamiętaj, że każde konto utworzone przez użytkownika w Twojej aplikacji jest związane tylko z Twoją aplikacją i nie jest wspólne dla wszystkich aplikacji, które korzystają z Firebase do obsługi logowania.
- Jak sprawdzić obecny stan uwierzytelniania aplikacji za pomocą
LiveData
. - Jak wylogować użytkowników.
Ćwiczenia z programowania zawierały podstawowe informacje o obsłudze logowania w aplikacji na Androida.
W ramach tych ćwiczeń zezwalałeś użytkownikom na rejestrowanie się i logowanie za pomocą ich adresów e-mail. W bibliotece Firebase możesz też obsługiwać inne metody uwierzytelniania, na przykład logowanie się przy użyciu numeru telefonu. Aby dowiedzieć się więcej o możliwościach biblioteki FirebaseUI i o tym, jak korzystać z innych jej funkcji, zapoznaj się z tymi zasobami:
- Dokumentacja uwierzytelniania FirebaseUI&s
- Prezentacja i przykładowy kod uwierzytelniania FirebaseUI
Aby dowiedzieć się więcej o sprawdzonych metodach logowania, zapoznaj się z tymi materiałami:
Ćwiczenia z programowania:
- Optymalizacja aplikacji pod kątem autouzupełniania
- Bezproblemowe logowanie przy użyciu funkcji Smart Lock
Dokumentacja dla programistów Androida:
Materiały wideo:
Linki do innych ćwiczeń z programowania znajdziesz w kursie dotyczącym programowania na Androida dla zaawansowanych w Kotlin.