Te warsztaty są częścią kursu Zaawansowany Android w Kotlinie. Najwięcej korzyści z tego kursu uzyskasz, jeśli przejdziesz wszystkie ćwiczenia w kolejności, ale nie jest to obowiązkowe. Wszystkie ćwiczenia z tego kursu znajdziesz na stronie docelowej ćwiczeń z zaawansowanego Androida w Kotlinie.
Wprowadzenie
Obsługa logowania użytkowników w aplikacji na Androida przynosi wiele korzyści. Umożliwiając użytkownikom tworzenie tożsamości w aplikacji, możesz zapewnić im więcej sposobów na korzystanie z niej.
Dzięki spersonalizowanym kontom użytkownicy mogą dostosowywać działanie aplikacji, wchodzić w interakcje z innymi użytkownikami oraz przechowywać i przenosić dane, jeśli korzystają z aplikacji na innym urządzeniu (np. w internecie lub na nowym telefonie).
Z tego przewodnika dowiesz się, jak obsługiwać logowanie w aplikacji za pomocą biblioteki FirebaseUI. Biblioteka FirebaseUI ułatwia deweloperom tworzenie procesu logowania i zarządzanie kontami użytkowników.
Co warto wiedzieć
- Podstawy tworzenia aplikacji na Androida
- LiveData i ViewModel
Czego się nauczysz
- Jak dodać Firebase do projektu
- Jak obsługiwać logowanie w aplikacji na Androida
- Jak sprawdzić bieżący stan uwierzytelniania aplikacji
- Wylogowywanie użytkowników
Jakie zadania wykonasz
- Użyj konsoli Firebase, aby zintegrować Firebase z aplikacją.
- Wdróż funkcję logowania.
- Dodawanie w aplikacji dostosowań dla zalogowanych użytkowników.
- Wdrażanie wylogowywania użytkowników.
Więcej informacji o klasach LiveData i ViewModel
W przypadku aplikacji w tym ćwiczeniu musisz mieć podstawową wiedzę o klasach LiveData i ViewModel. Jeśli chcesz poznać te koncepcje, przeczytaj omówienia LiveData i ViewModel.
Możesz też przejść kurs Tworzenie aplikacji na Androida w Kotlinie, aby poznać podstawowe zagadnienia związane z Androidem, które pojawią się w tym ćwiczeniu. Ten kurs jest dostępny zarówno jako kurs Udacity, jak i kurs codelabs.
W tym ćwiczeniu z programowania utworzysz aplikację, która wyświetla ciekawe fakty o Androidzie. Co ważniejsze, aplikacja będzie miała przycisk Zaloguj się/Wyloguj się. Gdy użytkownik jest zalogowany w aplikacji, każdy wyświetlany fakt dotyczący Androida będzie zawierać powitanie, które zwiększy poziom personalizacji.
Pobierz przykładową aplikację. Możesz to zrobić na 2 sposoby:
… lub sklonuj repozytorium GitHub z wiersza poleceń, używając tego polecenia, i przejdź do gałęzi start
repozytorium:
$ git clone https://github.com/googlecodelabs/android-kotlin-login
Ważne: ponieważ będziesz integrować aplikację z Firebase, aplikacja startowa wymaga pewnej konfiguracji, aby można było ją skompilować i uruchomić. Zrobisz to w następnym kroku tego laboratorium.
Krok 1. Utwórz projekt Firebase
Zanim dodasz Firebase do aplikacji na Androida, musisz utworzyć projekt Firebase, aby połączyć go z tą aplikacją.
- W konsoli Firebase kliknij Dodaj projekt.
- Wybierz lub wpisz nazwę projektu. Nazwa projektu może być dowolna, ale warto wybrać taką, która jest związana z tworzoną aplikacją.
- Kliknij Dalej.
- Możesz pominąć konfigurowanie Google Analytics i wybrać opcję Nie teraz.
- Aby zakończyć konfigurowanie projektu Firebase, kliknij Utwórz projekt.
Krok 2. Zarejestruj aplikację w Firebase
Mając projekt Firebase, możesz dodać do niego swoją aplikację na Androida.
- W centrum strony „Opis” projektu w konsoli Firebase kliknij ikonę Android, aby uruchomić proces konfiguracji.
- Wpisz identyfikator aplikacji w polu Nazwa pakietu na Androida. Pamiętaj, aby wpisać identyfikator używany przez aplikację, ponieważ po zarejestrowaniu aplikacji w projekcie Firebase nie możesz dodać ani zmodyfikować tej wartości.
- Identyfikator aplikacji jest czasami 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 podpisywania aplikacji przed debugowaniem. Ten klucz możesz wygenerować, wpisując w terminalu wiersza poleceń to polecenie:
keytool -alias androiddebugkey -keystore ~/.android/debug.keystore -list -v -storepass android
- Kliknij Zarejestruj aplikację.
Krok 3. Dodaj do projektu plik konfiguracji Firebase
Dodaj do aplikacji plik konfiguracyjny Firebase na Androida:
- Kliknij Pobierz google-services.json, aby pobrać plik konfiguracyjny Firebase na Androida (
google-services.json
).
- W każdej chwili możesz ponownie pobrać plik konfiguracyjny Firebase na Androida.
- Sprawdź, czy plik konfiguracyjny nie zawiera dodatkowych znaków. Powinien mieć nazwę
google-services.json
.
- Przenieś plik konfiguracyjny do katalogu modułu (na poziomie aplikacji).
Krok 4. Skonfiguruj projekt na Androida, aby włączyć usługi Firebase
- Aby włączyć usługi Firebase w aplikacji, dodaj wtyczkę usług Google do plików Gradle.
- W pliku Gradle na poziomie głównym (poziomie projektu) (
build.gradle
) dodaj reguły, aby uwzględnić wtyczkę Usług Google. Sprawdź też, czy masz repozytorium Google 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 na końcu wiersz.
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ść Firebase
W tym laboratorium głównym powodem integracji Firebase jest możliwość tworzenia użytkowników i zarządzania nimi. W tym celu musisz dodać bibliotekę Firebase, która umożliwia wdrożenie logowania.
- Dodaj do pliku
build.gradle (Module:app)
tę zależność, aby móc używać pakietu SDK w aplikacji. Pakiet SDKfirebase-auth
umożliwia zarządzanie uwierzytelnionymi użytkownikami aplikacji.
app/build.gradle:
implementation 'com.firebaseui:firebase-ui-auth:5.0.0'
- Zsynchronizuj projekt z plikami Gradle, aby mieć pewność, że wszystkie zależności są dostępne dla aplikacji. Jeśli nie pojawi się odpowiedni komunikat, wybierz Plik > Synchronizuj projekt z plikami Gradle w Android Studio lub na pasku narzędzi.
Krok 5. Uruchom aplikację i sprawdź kod
- Uruchom aplikację w emulatorze lub na urządzeniu fizycznym, aby sprawdzić, czy środowisko zostało prawidłowo skonfigurowane i możesz rozpocząć tworzenie aplikacji.
Jeśli się uda, na ekranie głównym pojawi się ciekawy fakt o Androidzie oraz przycisk logowania w lewym górnym rogu. Kliknięcie przycisku logowania nie powoduje jeszcze żadnej reakcji.
Jest to aplikacja z jedną aktywnością i wieloma fragmentami. Element MainFragment
zawiera wszystkie elementy interfejsu widoczne na ekranie poniżej. (W kolejnych ćwiczeniach z programowania będziesz pracować z LoginFragment
i SettingsFragment
).
- Zapoznaj się z kodem. Zwróć szczególną uwagę na te kwestie:
FirebaseUserLiveData
to klasa, którą zaimplementujesz, aby obserwować bieżącego użytkownika Firebase powiązanego z aplikacją. W późniejszym kroku użyjesz instancjiFirebaseAuth
jako punktu wejścia, aby uzyskać informacje o tym użytkowniku.- Urządzenie
MainFragment
jest powiązane z urządzeniemLoginViewModel
.LoginViewModel
to klasa, którą zaimplementujesz, aby użyćFirebaseUserLiveData
do utworzenia zmiennejauthenticationState
. Korzystając z tej zmiennejauthenticationState
,MainFragment
może obserwować wartość, aby odpowiednio zaktualizować interfejs.
W tym kroku skonfigurujesz w konsoli Firebase metody uwierzytelniania, które mają być obsługiwane przez Twoją aplikację. W tym laboratorium skupisz się na umożliwieniu użytkownikom logowania się za pomocą podanego przez nich adresu e-mail lub konta Google.
- Otwórz konsolę Firebase. (Uwaga: jeśli nadal jesteś w procesie dodawania Firebase, kliknij X w lewym górnym rogu, aby wrócić do konsoli.
- Wybierz projekt, jeśli nie jesteś jeszcze w nim.
- Otwórz menu po lewej stronie i wybierz Tworzenie > Uwierzytelnianie .
- Na pasku nawigacyjnym u góry kliknij kartę Metoda logowania.
- Kliknij wiersz E-mail/hasło.
- W wyskakującym okienku ustaw przełącznik Włączono i kliknij Zapisz.
- Podobnie kliknij wiersz Google.
- Ustaw przełącznik Włączono, wpisz adres e-mail pomocy dotyczącej projektu i kliknij Zapisz.
W tym zadaniu zaimplementujesz funkcję logowania dla użytkowników.
- Otwórz pokój
MainFragment.kt
. - W układzie
MainFragment
zwróć uwagę naauth_button
. Obecnie nie jest skonfigurowany do obsługi danych wprowadzanych przez użytkowników. - W
onViewCreated(),
dodajonClickListener
doauth_button
, aby zadzwonić na numerlaunchSignInFlow()
.
MainFragment.kt
binding.authButton.setOnClickListener { launchSignInFlow() }
- Znajdź metodę
launchSignInFlow()
wMainFragment.kt
. Obecnie zawieraTODO
. - Uzupełnij funkcję
launchSignInFlow()
, jak pokazano poniżej.
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
)
}
Umożliwia to użytkownikom rejestrowanie się i logowanie przy użyciu adresu e-mail lub konta Google. Jeśli użytkownik zdecyduje się zarejestrować za pomocą adresu e-mail, utworzona przez niego kombinacja adresu e-mail i hasła będzie unikalna dla Twojej aplikacji. Oznacza to, że będzie mógł logować się w Twojej aplikacji za pomocą tej kombinacji, ale nie będzie mógł logować się w żadnej innej aplikacji obsługiwanej przez Firebase przy użyciu tych samych danych logowania.
- W
MainFragment.kt
możesz nasłuchiwać wyniku procesu logowania, implementując metodęonActivityResult()
, jak pokazano poniżej. Ponieważ proces logowania został rozpoczęty za pomocąSIGN_IN_REQUEST_CODE
, możesz też odsłuchać jego wynik, filtrując moment, w którymSIGN_IN_REQUEST_CODE
jest przekazywany z powrotem doonActivityResult()
. Zacznij od dodania kilku instrukcji logowania, aby sprawdzić, czy użytkownik zalogował się prawidłowo.
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}")
}
}
}
Aplikacja powinna teraz obsługiwać rejestrację i logowanie użytkowników.
- Uruchom aplikację i sprawdź, czy po kliknięciu przycisku Zaloguj się pojawia się ekran logowania.
- Możesz się teraz zalogować, podając adres e-mail i hasło lub używając konta Google.
- Po zalogowaniu interfejs się nie zmieni (zaktualizujesz go w następnym kroku), ale jeśli wszystko działa prawidłowo, po przejściu procesu rejestracji powinna się pojawić wiadomość w dzienniku
Successfully signed in user ${your name}!
. - Możesz też otworzyć konsolę Firebase i kliknąć Tworzenie > Uwierzytelnianie > Użytkownicy, aby sprawdzić, czy aplikacja ma teraz 1 zarejestrowanego użytkownika.
- Pamiętaj, że gdy użytkownicy tworzą konto w Twojej aplikacji, jest ono powiązane tylko z nią, a nie z żadną inną aplikacją, która korzysta z Firebase do logowania.
W tym zadaniu zaimplementujesz aktualizowanie interfejsu na podstawie stanu uwierzytelniania. Gdy użytkownik jest zalogowany, możesz spersonalizować jego ekran główny, wyświetlając jego imię i nazwisko. Zaktualizujesz też przycisk Zaloguj się, aby po zalogowaniu użytkownika zmienić go na przycisk Wyloguj się.
- Otwórz klasę
FirebaseUserLiveData.kt
, która została już utworzona. Pierwszą rzeczą, którą musisz zrobić, jest zapewnienie innym klasom w aplikacji możliwości sprawdzenia, kiedy użytkownik się zalogował lub wylogował. Klasa nie robi jednak jeszcze nic, ponieważ wartośćLiveData
nie jest aktualizowana. - Ponieważ używasz biblioteki
FirebaseAuth
, możesz nasłuchiwać zmian zalogowanego użytkownika za pomocą wywołania zwrotnegoFirebaseUser.AuthStateListener
, które jest zaimplementowane w bibliotece FirebaseUI. To wywołanie zwrotne jest wywoływane za każdym razem, gdy użytkownik loguje się w aplikacji lub z niej wylogowuje. - Zwróć uwagę, że
FirebaseUserLiveData.kt
definiuje zmiennąauthStateListener
. Ta zmienna będzie służyć do przechowywania wartościLiveData
. ZmiennaauthStateListener
została utworzona, aby umożliwić Ci prawidłowe rozpoczęcie i zakończenie nasłuchiwania zmian stanu uwierzytelniania w zależności od stanu aplikacji. Jeśli na przykład użytkownik przełączy aplikację w tryb tła, powinna ona przestać nasłuchiwać zmian stanu uwierzytelniania, aby zapobiec potencjalnym wyciekom pamięci. - Zaktualizuj
authStateListener
, aby wartośćFirebaseUserLiveData
odpowiadała bieżącemu użytkownikowi Firebase.
FirebaseUserLiveData.kt
private val authStateListener = FirebaseAuth.AuthStateListener { firebaseAuth ->
value = firebaseAuth.currentUser
}
- Otwórz pokój
LoginViewModel.kt
. - W
LoginViewModel.kt
utwórz zmiennąauthenticationState
na podstawie obiektuFirebaseUserLiveData
, który właśnie został wdrożony. Dzięki utworzeniu tej zmiennejauthenticationState
inne klasy mogą teraz sprawdzać, czy użytkownik jest zalogowany, za pomocą zmiennejLoginViewModel
.
LoginViewModel.kt
val authenticationState = FirebaseUserLiveData().map { user ->
if (user != null) {
AuthenticationState.AUTHENTICATED
} else {
AuthenticationState.UNAUTHENTICATED
}
}
- Otwórz aplikację
MainFragment.kt.
- W
MainFragment.kt
observeAuthenticationState()
możesz użyć zmiennejauthenticationState
, którą właśnie dodano wLoginViewModel
, i odpowiednio zmienić interfejs. Jeśli użytkownik jest zalogowany, w miejscuauthButton
powinna się wyświetlać opcja Wyloguj.
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.
}
}
})
}
- Jeśli użytkownik jest zalogowany, możesz też dostosować wyświetlaną mu wiadomość powitalną za pomocą funkcji
getFactWithPersonalization()
dostępnej wMainFragment
.
MainFragment.kt
binding.welcomeText.text = getFactWithPersonalization(factToDisplay)
- Jeśli nie ma zalogowanego użytkownika (gdy
authenticationState
ma wartość inną niżLoginViewModel.AuthenticationState.AUTHENTICATED
),auth_button
powinno wyświetlać Zaloguj się i po kliknięciu uruchamiać ekran logowania. Wyświetlana wiadomość nie powinna być też spersonalizowana.
MainFragment.kt
binding.authButton.text = getString(R.string.login_button_text)
binding.authButton.setOnClickListener { launchSignInFlow() }
binding.welcomeText.text = factToDisplay
Po wykonaniu wszystkich czynności ostateczna metoda observeAuthenticationState()
powinna wyglądać podobnie do kodu poniżej.
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()
}
}
}
})
}
- Uruchom aplikację. Interfejs powinien się zaktualizować w zależności od tego, czy użytkownik jest zalogowany. Jeśli wszystko działa prawidłowo i jesteś zalogowany(-a), na ekranie głównym powinna się teraz wyświetlać Twoja nazwa oraz ciekawostka o Androidzie. Przycisk Zaloguj się powinien teraz wyświetlać Wyloguj się.
W tym zadaniu zaimplementujesz funkcję wylogowywania.
Skoro aplikacja umożliwia użytkownikom logowanie się, powinna też pozwalać im na wylogowanie się. Oto przykład wylogowania użytkownika za pomocą tylko 1 wiersza kodu:
AuthUI.getInstance().signOut(requireContext())
- Otwórz pokój
MainFragment.kt
. - W
MainFragment.kt
wobserveAuthenticationState()
dodaj logikę wylogowywania, aby funkcjaauth_button
działała prawidłowo, gdy użytkownik jest zalogowany. Ostateczny wynik metody wygląda jak poniższy kod.
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()
}
}
}
})
}
- Uruchom aplikację.
- Kliknij przycisk Wyloguj się i sprawdź, czy użytkownik został wylogowany, a stan przycisku zmienił się na Zaloguj się.
Ostateczną wersję gotowej aplikacji znajdziesz tutaj: https://github.com/googlecodelabs/android-kotlin-login.
Z tego przewodnika dowiedzieliśmy się:
- Jak dodać Firebase do projektu, dodając niezbędne zależności w pliku Gradle i konfigurując projekt w konsoli Firebase.
- Jak wdrożyć logowanie w aplikacji za pomocą biblioteki FirebaseUI i określić, w jaki sposób użytkownicy mają się logować. Pamiętaj, że każde konto utworzone przez użytkownika w Twojej aplikacji jest specyficzne tylko dla tej aplikacji i nie jest udostępniane wszystkim aplikacjom, które korzystają z Firebase do logowania.
- Jak sprawdzić bieżący stan uwierzytelniania aplikacji za pomocą
LiveData
. - Jak wylogować użytkowników.
W tym samouczku omówiliśmy podstawy obsługi logowania w aplikacji na Androida.
W tym laboratorium użytkownicy mogli rejestrować się i logować przy użyciu adresu e-mail. Jednak dzięki bibliotece FirebaseUI możesz też obsługiwać inne metody uwierzytelniania, takie jak logowanie się przy użyciu numeru telefonu. Aby dowiedzieć się więcej o możliwościach biblioteki FirebaseUI i korzystaniu z innych funkcji, zapoznaj się z tymi materiałami:
- Dokumentacja uwierzytelniania FirebaseUI
- Wersja demonstracyjna uwierzytelniania FirebaseUI i przykładowy kod
Więcej informacji o sprawdzonych metodach dotyczących logowania znajdziesz w tych materiałach:
Codelabs:
Dokumentacja dla deweloperów aplikacji na Androida:
Materiały wideo:
Linki do innych ćwiczeń z tego kursu znajdziesz na stronie docelowej ćwiczeń z zaawansowanego Androida w Kotlinie.