1. Zanim zaczniesz
Z tego Codelab dowiesz się, jak dodać uwierzytelnianie Firebase do aplikacji Flutter za pomocą pakietu FlutterFire UI. Dzięki temu pakietowi możesz dodać do aplikacji Flutter uwierzytelnianie za pomocą adresu e-mail i hasła oraz logowanie Google. Dowiesz się też, jak skonfigurować projekt Firebase i użyć wiersza poleceń FlutterFire do zainicjowania Firebase w aplikacji Flutter.
Wymagania wstępne
To ćwiczenie z programowania zakłada, że masz już pewne doświadczenie w używaniu Fluttera. Jeśli nie, warto najpierw zapoznać się z podstawami. Te linki mogą być przydatne:
- Zapoznaj się z ramką widgetów Fluttera
- Wypróbuj ćwiczenie Tworzenie pierwszej aplikacji Flutter, część 1.
Powinieneś/powinnaś też mieć pewne doświadczenie w korzystaniu z Firebase, ale nie ma problemu, jeśli nie dodawałeś/dodawałaś tej usługi do projektu Flutter. Jeśli nie znasz konsoli Firebase lub dopiero zaczynasz korzystać z tej platformy, zapoznaj się najpierw z tymi artykułami:
Co utworzysz
W tym laboratorium programistycznym znajdziesz instrukcje tworzenia przepływu uwierzytelniania w aplikacji Flutter za pomocą Firebase for Authentication. Aplikacja będzie zawierać ekran logowania, ekran rejestracji, ekran odzyskiwania hasła i ekran profilu użytkownika.
Czego się nauczysz
W tym ćwiczeniu omawiamy:
- Dodawanie Firebase do aplikacji Flutter
- Konfiguracja konsoli Firebase
- Dodawanie Firebase do aplikacji za pomocą wiersza poleceń Firebase
- Generowanie konfiguracji Firebase w języku Dart za pomocą wiersza poleceń FlutterFire
- Dodawanie Uwierzytelniania Firebase do aplikacji Flutter
- Konfigurowanie Uwierzytelniania Firebase w konsoli
- Dodawanie logowania za pomocą adresu e-mail i hasła w pakiecie
firebase_ui_auth
- Dodawanie rejestracji użytkownika w pakiecie
firebase_ui_auth
- Dodawanie strony „Nie pamiętasz hasła?”
- Dodawanie logowania przez Google za pomocą
firebase_ui_auth
- Skonfiguruj aplikację do współpracy z wieloma dostawcami logowania.
- Dodawanie ekranu profilu użytkownika do aplikacji za pomocą pakietu
firebase_ui_auth
Ten warsztat dotyczy głównie dodawania niezawodnego systemu uwierzytelniania za pomocą pakietu firebase_ui_auth
. Jak zobaczysz, całą aplikację ze wszystkimi wymienionymi funkcjami można zaimplementować za pomocą około 100 wierszy kodu.
Czego potrzebujesz
- Znajomość Fluttera i zainstalowanego pakietu SDK.
- edytor tekstu (Flutter obsługuje JetBrains IDE, Android Studio i VS Code);
- przeglądarka Google Chrome lub inny preferowany cel programowania dla Fluttera. (niektóre polecenia terminala w tym CodeLab będą zakładać, że aplikacja jest uruchamiana w Chrome)
2. Tworzenie i konfigurowanie projektu Firebase
Pierwszym zadaniem, które musisz wykonać, jest utworzenie projektu Firebase w konsoli internetowej Firebase.
Tworzenie projektu Firebase
- Zaloguj się w Firebase.
- W konsoli Firebase kliknij Dodaj projekt (lub Utwórz projekt) i wpisz nazwę projektu Firebase (np. „FlutterFire-UI-Codelab”).
- Przejrzyj opcje tworzenia projektu. Zaakceptuj warunki korzystania z Firebase, jeśli pojawi się taka prośba. Pomiń konfigurowanie Google Analytics, ponieważ nie będziesz używać tej usługi w przypadku tej aplikacji.
Więcej informacji o projektach Firebase znajdziesz w artykule Informacje o projektach Firebase.
Włączanie logowania za pomocą adresu e-mail w usłudze Uwierzytelnianie Firebase
Aplikacja, którą tworzysz, korzysta z usługi Uwierzytelnianie Firebase, aby umożliwić użytkownikom logowanie się w niej. Umożliwia też nowym użytkownikom rejestrację w aplikacji Flutter.
Uwierzytelnianie Firebase musi zostać włączone w konsoli Firebase, a po włączeniu wymaga specjalnej konfiguracji.
Aby umożliwić użytkownikom logowanie się w aplikacji internetowej, najpierw użyj metody logowania E-mail/hasło. Później dodasz metodę Logowania przez Google.
- W konsoli Firebase rozwiń w panelu po lewej stronie menu Kompilacja.
- Kliknij Uwierzytelnianie, a następnie kliknij przycisk Rozpocznij i kartę Metoda logowania (lub przejdź bezpośrednio do karty Metoda logowania).
- Na liście Dostawcy logowania kliknij E-mail/hasło, ustaw przełącznik Włącz w pozycji włączonej, a następnie kliknij Zapisz.
3. Konfigurowanie aplikacji Flutter
Zanim zaczniesz, musisz pobrać kod startowy i zainstalować wiersz poleceń Firebase.
Pobieranie kodu startowego
Sklonuj repozytorium GitHub z poziomu wiersza poleceń:
git clone https://github.com/flutter/codelabs.git flutter-codelabs
Jeśli masz zainstalowane narzędzie wiersza poleceń GitHub:
gh repo clone flutter/codelabs flutter-codelabs
Przykładowy kod należy sklonować do katalogu flutter-codelabs
na komputerze, który zawiera kod kolekcji Codelabs. Kod tego CodeLab znajduje się w podkatalogu flutter-codelabs/firebase-auth-flutterfire-ui
.
Katalog flutter-codelabs/firebase-auth-flutterfire-ui
zawiera 2 projekty Fluttera. Jedna to complete
, a druga start
. Katalog start
zawiera niekompletny projekt, na którym spędzisz najwięcej czasu.
cd flutter-codelabs/firebase-auth-flutterfire-ui/start
Jeśli chcesz przejść do następnego zadania lub sprawdzić, jak powinno wyglądać zadanie po jego ukończeniu, zajrzyj do katalogu o nazwie complete.
Jeśli chcesz wykonać ćwiczenie Codelab i sam dodać kod, zacznij od aplikacji Flutter (flutter-codelabs/firebase-auth-flutterfire-ui/start
) i dodawaj kod do tego projektu w trakcie wykonywania ćwiczenia. Otwórz ten katalog lub zaimportuj go do preferowanego środowiska IDE.
Zainstaluj wiersz poleceń Firebase
Wiersz poleceń Firebase zawiera narzędzia do zarządzania projektami Firebase. Interfejs wiersza poleceń jest wymagany do interfejsu wiersza poleceń FlutterFire, który zainstalujesz za chwilę.
Istnieją różne sposoby instalacji CLI. Wszystkie dostępne opcje dla swojego systemu operacyjnego znajdziesz na stronie firebase.google.com/docs/cli.
Po zainstalowaniu wiersza poleceń musisz się uwierzytelnić w Firebase.
- Zaloguj się w Firebase za pomocą konta Google, uruchamiając to polecenie:
firebase login
- To polecenie łączy Twój komputer lokalny z Firebase i daje Ci dostęp do projektów Firebase.
- Sprawdź, czy wiersz poleceń jest prawidłowo zainstalowany i czy ma dostęp do Twojego konta, wyświetlając listę projektów Firebase. Uruchom to polecenie:
firebase projects:list
- Wyświetlona lista powinna być taka sama jak projekty Firebase wymienione w konsoli Firebase. Powinieneś zobaczyć co najmniej
flutterfire-ui-codelab.
Instalowanie interfejsu wiersza poleceń FlutterFire
FlutterFire CLI to narzędzie, które ułatwia proces instalacji Firebase na wszystkich obsługiwanych platformach w aplikacji Flutter. Jest ono oparte na wierszu poleceń Firebase.
Najpierw zainstaluj interfejs wiersza poleceń:
dart pub global activate flutterfire_cli
Sprawdź, czy interfejs wiersza poleceń został zainstalowany. Uruchom to polecenie i sprawdź, czy interfejs wiersza poleceń wyświetla menu pomocy.
flutterfire --help
Dodawanie projektu Firebase do aplikacji Flutter
Konfigurowanie FlutterFire
Możesz użyć FlutterFire, aby wygenerować kod Dart potrzebny do korzystania z Firebase w aplikacji Flutter.
flutterfire configure
Gdy to polecenie zostanie wykonane, pojawi się prośba o wybranie projektu Firebase, którego chcesz użyć, i platform, które chcesz skonfigurować.
Na poniższych zrzutach ekranu widać prompty, na które musisz odpowiedzieć.
- Wybierz projekt, którego chcesz użyć. W tym przypadku użyj
flutterfire-ui-codelab
- Wybierz platformy, których chcesz używać. W tym laboratorium programistycznym znajdziesz instrukcje konfigurowania uwierzytelniania Firebase dla Fluttera na potrzeby wersji internetowej, iOS i Androida, ale możesz też skonfigurować projekt Firebase tak, aby korzystał ze wszystkich opcji.
- Ten zrzut ekranu przedstawia dane wyjściowe po zakończeniu procesu. Jeśli znasz Firebase, zauważysz, że nie musisz tworzyć aplikacji platformowych (np. aplikacji na Androida) w konsoli. Za Ciebie zrobił to interfejs wiersza poleceń FlutterFire.
Gdy to zrobisz, otwórz aplikację Flutter w edytorze tekstu. Interfejs wiersza poleceń FlutterFire zmodyfikował plik o nazwie firebase_options.dart
. Plik zawiera klasę o nazwie FirebaseOptions
, która ma zmienne statyczne zawierające konfigurację Firebase wymaganą na każdej platformie. Jeśli podczas wykonywania zapytania flutterfire configure
wybrano wszystkie platformy, zobaczysz wartości statyczne o nazwach web
, android
, ios
i macos
.
lib/firebase_options.dart
import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
import 'package:flutter/foundation.dart'
show defaultTargetPlatform, kIsWeb, TargetPlatform;
class DefaultFirebaseOptions {
static FirebaseOptions get currentPlatform {
if (kIsWeb) {
return web;
}
switch (defaultTargetPlatform) {
case TargetPlatform.android:
return android;
case TargetPlatform.iOS:
return ios;
case TargetPlatform.macOS:
return macos;
default:
throw UnsupportedError(
'DefaultFirebaseOptions are not supported for this platform.',
);
}
}
static const FirebaseOptions web = FirebaseOptions(
apiKey: 'AIzaSyCqFjCV_9CZmYeIvcK9FVy4drmKUlSaIWY',
appId: '1:963656261848:web:7219f7fca5fc70afb237ad',
messagingSenderId: '963656261848',
projectId: 'flutterfire-ui-codelab',
authDomain: 'flutterfire-ui-codelab.firebaseapp.com',
storageBucket: 'flutterfire-ui-codelab.firebasestorage.app',
measurementId: 'G-DGF0CP099H',
);
static const FirebaseOptions android = FirebaseOptions(
apiKey: 'AIzaSyDconZaCQpkxIJ5KQBF-3tEU0rxYsLkIe8',
appId: '1:963656261848:android:c939ccc86ab2dcdbb237ad',
messagingSenderId: '963656261848',
projectId: 'flutterfire-ui-codelab',
storageBucket: 'flutterfire-ui-codelab.firebasestorage.app',
);
static const FirebaseOptions ios = FirebaseOptions(
apiKey: 'AIzaSyBqLWsqFjYAdGyihKTahMRDQMo0N6NVjAs',
appId: '1:963656261848:ios:d9e01cfe8b675dfcb237ad',
messagingSenderId: '963656261848',
projectId: 'flutterfire-ui-codelab',
storageBucket: 'flutterfire-ui-codelab.firebasestorage.app',
iosClientId: '963656261848-v7r3vq1v6haupv0l1mdrmsf56ktnua60.apps.googleusercontent.com',
iosBundleId: 'com.example.complete',
);
static const FirebaseOptions macos = FirebaseOptions(
apiKey: 'AIzaSyBqLWsqFjYAdGyihKTahMRDQMo0N6NVjAs',
appId: '1:963656261848:ios:d9e01cfe8b675dfcb237ad',
messagingSenderId: '963656261848',
projectId: 'flutterfire-ui-codelab',
storageBucket: 'flutterfire-ui-codelab.firebasestorage.app',
iosClientId: '963656261848-v7r3vq1v6haupv0l1mdrmsf56ktnua60.apps.googleusercontent.com',
iosBundleId: 'com.example.complete',
);
}
Firebase używa słowa „aplikacja” w przypadku konkretnej kompilacji na określoną platformę w projekcie Firebase. Na przykład projekt Firebase o nazwie FlutterFire-ui-codelab zawiera kilka aplikacji: jedną na Androida, jedną na iOS, jedną na macOS i jedną na internet.
Metoda DefaultFirebaseOptions.currentPlatform
używa enumeracji TargetPlatform
udostępnianej przez Fluttera, aby wykryć platformę, na której działa aplikacja, a następnie zwraca wartości konfiguracji Firebase potrzebne do prawidłowego zastosowania Firebase.
Dodawanie pakietów Firebase do aplikacji Flutter
Ostatnim krokiem konfiguracji jest dodanie odpowiednich pakietów Firebase do projektu Flutter. Plik firebase_options.dart
powinien zawierać błędy, ponieważ korzysta z pakietów Firebase, które nie zostały jeszcze dodane. W terminalu upewnij się, że znajdujesz się w katalogu głównym projektu Flutter w pozycji flutter-codelabs/firebase-emulator-suite/start
. Następnie uruchom te 3 polecenia:
flutter pub add firebase_core firebase_auth firebase_ui_auth
Na tym etapie są to jedyne potrzebne pakiety.
Inicjowanie Firebase
Aby używać dodanych pakietów i funkcji DefaultFirebaseOptions.currentPlatform,
, zaktualizuj kod w funkcji main
w pliku main.dart
.
lib/main.dart
import 'package:firebase_core/firebase_core.dart'; // Add this import
import 'package:flutter/material.dart';
import 'app.dart';
import 'firebase_options.dart'; // And this import
// TODO(codelab user): Get API key
const clientId = 'YOUR_CLIENT_ID';
void main() async {
// Add from here...
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
// To here.
runApp(const MyApp(clientId: clientId));
}
Ten kod wykonuje 2 działania.
WidgetsFlutterBinding.ensureInitialized()
informuje Fluttera, aby nie uruchamiał kodu widżetu aplikacji, dopóki nie uruchomi się całkowicie framework Fluttera. Firebase korzysta z kanałów natywnych platform, które wymagają uruchomionego frameworku.Firebase.initializeApp
łączy aplikację Flutter z projektem Firebase. WartośćDefaultFirebaseOptions.currentPlatform
jest importowana z wygenerowanego plikufirebase_options.dart
. Ta wartość statyczna wykrywa, na jakiej platformie działasz, i przekazuje odpowiednie klucze Firebase.
4. Dodawanie początkowej strony uwierzytelniania w interfejsie Firebase
Interfejs Firebase dla usługi Uwierzytelnianie zawiera widżety, które reprezentują całe ekrany w aplikacji. Te ekrany obsługują różne procesy uwierzytelniania w aplikacji, takie jak logowanie, rejestracja, hasło zostało zapomniane czy profil użytkownika. Aby rozpocząć, dodaj do aplikacji stronę docelowa, która będzie pełnić funkcję zabezpieczenia uwierzytelniania dla aplikacji głównej.
Materiał lub aplikacja Cupertino
Aby korzystać z interfejsu FlutterFire, musisz owinąć aplikację w komponent MaterialApp
lub CupertinoApp
. W zależności od wybranej opcji interfejs będzie automatycznie odzwierciedlał różnice między widżetami Material i Cupertino. W tym ćwiczeniu użyj MaterialApp
, który został już dodany do aplikacji w wersji app.dart
.
lib/app.dart
import 'package:flutter/material.dart';
import 'auth_gate.dart';
class MyApp extends StatelessWidget {
const MyApp({super.key, required this.clientId});
final String clientId;
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
),
home: AuthGate(clientId: clientId),
);
}
}
Sprawdzanie stanu uwierzytelniania
Zanim wyświetlisz ekran logowania, musisz sprawdzić, czy użytkownik jest uwierzytelniony. Najczęstszym sposobem sprawdzenia tego jest odsłuchanie FirebaseAuth
authStateChanges
za pomocą wtyczki uwierzytelniania Firebase.
W przykładowym kodzie powyżej obiekt MaterialApp
tworzy widżet AuthGate
w metodzie build
. (to widżet niestandardowy, który nie jest dostarczany przez interfejs FlutterFire UI).
Widżet musi zostać zaktualizowany, aby uwzględniał strumień authStateChanges
.
Interfejs API authStateChanges
zwraca Stream
z bieżącym użytkownikiem (jeśli jest zalogowany) lub null, jeśli tak nie jest. Aby subskrybować ten stan w naszej aplikacji, możesz użyć widżetu StreamBuilder w Flutterze i przekazać do niego strumień.
StreamBuilder
to widżet, który sam się tworzy na podstawie najnowszego zrzutu danych ze strumienia, który mu przekazujesz. Jest ona automatycznie odtwarzana, gdy Stream
wyemituje nowy zrzut.
Zaktualizuj kod w auth_gate.dart
.
lib/auth_gate.dart
import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider; // Add this import
import 'package:firebase_ui_auth/firebase_ui_auth.dart'; // And this import
import 'package:flutter/material.dart';
import 'home.dart';
class AuthGate extends StatelessWidget {
const AuthGate({super.key, required this.clientId});
final String clientId;
@override
Widget build(BuildContext context) {
return StreamBuilder<User?>( // Modify from here...
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return SignInScreen(providers: []);
}
return const HomeScreen();
},
); // To here.
}
}
StreamBuilder.stream
przekazujeFirebaseAuth.instance.authStateChanged
, czyli wspomniany wcześniej strumień, który zwróci obiekt FirebaseUser
, jeśli użytkownik jest uwierzytelniony, w przeciwnym razie zwrócinull
.- Następnie kod używa funkcji
snapshot.hasData
, aby sprawdzić, czy wartość ze strumienia zawiera obiektUser
. - Jeśli nie ma żadnego, zwróci widżet
SignInScreen
. Na razie ten ekran nie będzie miał żadnego zastosowania. Zostanie zaktualizowany w następnym kroku. - W przeciwnym razie zwraca
HomeScreen
, czyli główną część aplikacji, do której dostęp mają tylko uwierzytelnieni użytkownicy.
SignInScreen
to widżet pochodzący z pakietu interfejsu użytkownika FlutterFire. Na tym skupimy się w następnym kroku tego ćwiczenia. Gdy uruchomisz aplikację, powinien pojawić się pusty ekran logowania.
5. Ekran logowania
Widżet SignInScreen
udostępniany przez interfejs FlutterFire UI umożliwia:
- Zezwalanie użytkownikom na logowanie
- Jeśli użytkownik zapomni hasło, może kliknąć „Nie pamiętam hasła?”, aby przejść do formularza resetowania hasła.
- Jeśli użytkownik nie jest jeszcze zarejestrowany, może kliknąć „Zarejestruj się” i zostanie przekierowany do innego formularza, który pozwoli mu się zarejestrować.
To wymaga tylko kilku linii kodu. Przypomnij kod w widżecie AuthGate
:
lib/auth_gate.dart
import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider;
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';
import 'home.dart';
class AuthGate extends StatelessWidget {
const AuthGate({super.key, required this.clientId});
final String clientId;
@override
Widget build(BuildContext context) {
return StreamBuilder<User?>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return SignInScreen(providers: [EmailAuthProvider()]); // Modify this line
}
return const HomeScreen();
},
);
}
}
Widget SignInScreen
i jego argument providers
to jedyny kod wymagany do uzyskania wszystkich wymienionych funkcji. Powinien wyświetlić się ekran logowania z polami tekstowymi „E-mail” i „Hasło” oraz przyciskiem „Zaloguj się”.
Chociaż jest funkcjonalna, brakuje jej stylu. Widget udostępnia parametry, które umożliwiają dostosowanie wyglądu ekranu logowania. Możesz na przykład dodać logo swojej firmy.
Dostosowywanie ekranu logowania
headerBuilder
Za pomocą argumentu SignInScreen.headerBuilder
możesz dodawać dowolne widżety nad formularzem logowania. Ten widżet jest wyświetlany tylko na wąskich ekranach, np. na urządzeniach mobilnych. Na szerokich ekranach możesz użyć SignInScreen.sideBuilder
, o którym mowa w dalszej części tego Codelab.
Zaktualizuj plik lib/auth_gate.dart
za pomocą tego kodu:
lib/auth_gate.dart
import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider;
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';
import 'home.dart';
class AuthGate extends StatelessWidget {
const AuthGate({super.key, required this.clientId});
final String clientId;
@override
Widget build(BuildContext context) {
return StreamBuilder<User?>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return SignInScreen( // Modify from here...
providers: [EmailAuthProvider()],
headerBuilder: (context, constraints, shrinkOffset) {
return Padding(
padding: const EdgeInsets.all(20),
child: AspectRatio(
aspectRatio: 1,
child: Image.asset('assets/flutterfire_300x.png'),
),
);
},
); // To here.
}
return const HomeScreen();
},
);
}
}```
The headerBuilder argument requires a function of the type HeaderBuilder, which
is defined in the FlutterFire UI package.
```dart
typedef HeaderBuilder = Widget Function(
BuildContext context,
BoxConstraints constraints,
double shrinkOffset,
);
Jest to funkcja zwracająca wartość, która udostępnia wartości, których możesz użyć, np. BuildContext
i BoxConstraints
, oraz wymaga zwrócenia widżetu. Wyświetli się wybrany widżet u góry ekranu. W tym przykładzie nowy kod dodaje obraz u góry ekranu. Twoja aplikacja powinna teraz wyglądać tak.
Subtitle Builder
Ekran logowania zawiera 3 dodatkowe parametry, które umożliwiają jego dostosowywanie: subtitleBuilder
, footerBuilder
i sideBuilder
.
Funkcja subtitleBuilder
różni się nieznacznie tym, że argumenty wywołania zwrotnego zawierają działanie o typie AuthAction
. AuthAction
to typ enumeracji, który umożliwia wykrycie, czy użytkownik znajduje się na ekranie logowania czy rejestracji.
Zaktualizuj kod w pliku auth_gate.dart, aby używać funkcji subtitleBuilder
.
lib/auth_gate.dart
import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider;
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';
import 'home.dart';
class AuthGate extends StatelessWidget {
const AuthGate({super.key, required this.clientId});
final String clientId;
@override
Widget build(BuildContext context) {
return StreamBuilder<User?>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return SignInScreen(
providers: [EmailAuthProvider()],
headerBuilder: (context, constraints, shrinkOffset) {
return Padding(
padding: const EdgeInsets.all(20),
child: AspectRatio(
aspectRatio: 1,
child: Image.asset('assets/flutterfire_300x.png'),
),
);
},
subtitleBuilder: (context, action) { // Add from here...
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: action == AuthAction.signIn
? const Text('Welcome to FlutterFire, please sign in!')
: const Text('Welcome to Flutterfire, please sign up!'),
);
}, // To here.
);
}
return const HomeScreen();
},
);
}
}
Kreator stopki
Argument footerBuilder jest taki sam jak argument subtitleBuilder. Nie zawiera ona tagów BoxConstraints
ani shrinkOffset
, ponieważ jest przeznaczona do tekstu, a nie obrazów. Możesz oczywiście dodać dowolny widżet.
Dodaj stopkę do ekranu logowania za pomocą tego kodu.
lib/auth_gate.dart
import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider;
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';
import 'home.dart';
class AuthGate extends StatelessWidget {
const AuthGate({super.key, required this.clientId});
final String clientId;
@override
Widget build(BuildContext context) {
return StreamBuilder<User?>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return SignInScreen(
providers: [EmailAuthProvider()],
headerBuilder: (context, constraints, shrinkOffset) {
return Padding(
padding: const EdgeInsets.all(20),
child: AspectRatio(
aspectRatio: 1,
child: Image.asset('assets/flutterfire_300x.png'),
),
);
},
subtitleBuilder: (context, action) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: action == AuthAction.signIn
? const Text('Welcome to FlutterFire, please sign in!')
: const Text('Welcome to Flutterfire, please sign up!'),
);
},
footerBuilder: (context, action) { // Add from here...
return const Padding(
padding: EdgeInsets.only(top: 16),
child: Text(
'By signing in, you agree to our terms and conditions.',
style: TextStyle(color: Colors.grey),
),
);
}, // To here.
);
}
return const HomeScreen();
},
);
}
}
Side Builder
Argument SignInScreen.sidebuilder akceptuje wywołanie zwrotne, a tym razem argumentami tego wywołania są BuildContext
i double shrinkOffset
. Widżet zwracany przez funkcję sideBuilder
będzie wyświetlany po lewej stronie formularza logowania i tylko na szerokich ekranach. Oznacza to, że widżet będzie wyświetlany tylko w aplikacjach internetowych i na komputerach.
Wewnętrznie interfejs FlutterFire używa punktu przełamania, aby określić, czy ma być wyświetlana zawartość nagłówka (na wysokich ekranach, np. na urządzeniach mobilnych) czy zawartość boczna (na szerokich ekranach, na komputerach lub w przeglądarce). Jeśli ekran ma więcej niż 800 pikseli szerokości, wyświetla się zawartość modułu Side Builder, a nie nagłówka. Jeśli ekran ma mniej niż 800 pikseli, jest odwrotnie.
Zaktualizuj kod w pliku auth_gate.dart, aby dodać widżety sideBuilder
.
lib/auth_gate.dart
import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider;
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';
import 'home.dart';
class AuthGate extends StatelessWidget {
const AuthGate({super.key, required this.clientId});
final String clientId;
@override
Widget build(BuildContext context) {
return StreamBuilder<User?>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return SignInScreen(
providers: [EmailAuthProvider()],
headerBuilder: (context, constraints, shrinkOffset) {
return Padding(
padding: const EdgeInsets.all(20),
child: AspectRatio(
aspectRatio: 1,
child: Image.asset('assets/flutterfire_300x.png'),
),
);
},
subtitleBuilder: (context, action) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: action == AuthAction.signIn
? const Text('Welcome to FlutterFire, please sign in!')
: const Text('Welcome to Flutterfire, please sign up!'),
);
},
footerBuilder: (context, action) {
return const Padding(
padding: EdgeInsets.only(top: 16),
child: Text(
'By signing in, you agree to our terms and conditions.',
style: TextStyle(color: Colors.grey),
),
);
},
sideBuilder: (context, shrinkOffset) {
return Padding(
padding: const EdgeInsets.all(20),
child: AspectRatio(
aspectRatio: 1,
child: Image.asset('flutterfire_300x.png'),
),
);
},
);
}
return const HomeScreen();
},
);
}
}
Po rozwinięciu okna aplikacja powinna wyglądać tak (jeśli używasz Fluttera w wersji internetowej lub na macOS).
Tworzenie konta użytkownika
Na tym etapie cały kod tego ekranu jest gotowy. Zanim się zalogujesz, musisz utworzyć użytkownika. Możesz to zrobić na ekranie „Zarejestruj się” lub utworzyć użytkownika w konsoli Firebase.
Aby korzystać z konsoli:
- W konsoli Firebase otwórz tabelę „Użytkownicy”. Wybierz „flutterfire-ui-codelab” lub inny projekt, jeśli użyłeś innej nazwy. Wyświetli się ta tabela:
- Kliknij przycisk „Dodaj użytkownika”.
- Wpisz adres e-mail i hasło nowego użytkownika. Może to być fałszywy adres e-mail i fałszywe hasło, jak widać na obrazku poniżej. To zadziała, ale funkcja „Nie pamiętam hasła” nie będzie działać, jeśli użyjesz fałszywego adresu e-mail.
- Kliknij „Dodaj użytkownika”
Teraz możesz wrócić do aplikacji Flutter i zalogować użytkownika na stronie logowania. Twoja aplikacja powinna wyglądać tak:
6. Ekran profilu
FlutterFire UI udostępnia też widżet ProfileScreen
, który zapewnia wiele funkcji w kilku liniach kodu.
Dodawanie widżetu ProfileScreen
W edytorze tekstu przejdź do pliku home.dart
. Zaktualizuj go za pomocą tego kodu:
lib/home.dart
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: [
IconButton(
icon: const Icon(Icons.person),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute<ProfileScreen>(
builder: (context) => const ProfileScreen(),
),
);
},
),
],
automaticallyImplyLeading: false,
),
body: Center(
child: Column(
children: [
SizedBox(width: 250, child: Image.asset('assets/dash.png')),
Text('Welcome!', style: Theme.of(context).textTheme.displaySmall),
const SignOutButton(),
],
),
),
);
}
}
Nowy kod to funkcja wywołania zwrotnego przekazana do metody IconButton.isPressed
. Gdy naciśniesz IconButton
, aplikacja utworzy nową anonimową trasę i przejdzie na nią. Ta ścieżka wyświetli widżet ProfileScreen
, który jest zwracany z trybu z powrotem MaterialPageRoute.builder
.
Ponownie uruchom aplikację i kliknij ikonę w prawym górnym rogu (na pasku aplikacji). Pojawi się strona:
Jest to standardowy interfejs użytkownika udostępniany przez stronę interfejsu FlutterFire. Wszystkie przyciski i pola tekstowe są połączone z usługą Uwierzytelnianie Firebase i działają od razu po zainstalowaniu. Możesz na przykład wpisać nazwę w polu tekstowym „Nazwa”, a interfejs FlutterFire wywoła metodę FirebaseAuth.instance.currentUser?.updateDisplayName
, która zapisze tę nazwę w Firebase.
Wyloguj się
Jeśli teraz naciśniesz przycisk „Wyloguj”, aplikacja nie ulegnie zmianie. Spowoduje to wylogowanie, ale nie wrócisz do widżetu AuthGate. Aby to zaimplementować, użyj parametru ProfileScreen.actions.
Najpierw zaktualizuj kod w pliku home.dart.
lib/home.dart
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: [
IconButton(
icon: const Icon(Icons.person),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute<ProfileScreen>(
builder: (context) => ProfileScreen(
actions: [
SignedOutAction((context) {
Navigator.of(context).pop();
}),
],
),
),
);
},
),
],
automaticallyImplyLeading: false,
),
body: Center(
child: Column(
children: [
SizedBox(width: 250, child: Image.asset('assets/dash.png')),
Text('Welcome!', style: Theme.of(context).textTheme.displaySmall),
const SignOutButton(),
],
),
),
);
}
}
Teraz, gdy tworzysz instancję ProfileScreen
, przekazujesz jej również listę działań do argumentu ProfileScreen.actions
. Te działania są typu FlutterFireUiAction
. Istnieje wiele różnych klas, które są podtypami klasy FlutterFireUiAction
. Zazwyczaj służą one do określania sposobu reakcji aplikacji na różne zmiany stanu uwierzytelniania. Funkcja SignedOutAction wywołuje funkcję wywołania zwrotnego, którą jej przekazujesz, gdy stan uwierzytelniania Firebase zmienia się na null dla bieżącego użytkownika.
Dodanie wywołania zwrotnego, które wywołuje funkcję Navigator.of(context).pop()
, gdy zostanie wywołana funkcja SignedOutAction
, spowoduje przejście aplikacji do poprzedniej strony. W tym przykładzie aplikacji jest tylko 1 stała ścieżka, która wyświetla ekran logowania, jeśli użytkownik nie jest zalogowany, lub stronę główną, jeśli jest zalogowany. Ponieważ dzieje się to, gdy użytkownik się wyloguje, aplikacja wyświetli ekran logowania.
Dostosowywanie strony profilu
Podobnie jak ekran logowania, stronę profilu można dostosować. Po pierwsze, na naszej obecnej stronie nie ma możliwości powrotu na stronę główną, gdy użytkownik znajdzie się na stronie profilu. Aby rozwiązać ten problem, dodaj do widżetu ProfileScreen pasek aplikacji.
lib/home.dart
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: [
IconButton(
icon: const Icon(Icons.person),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute<ProfileScreen>(
builder: (context) => ProfileScreen(
appBar: AppBar(title: const Text('User Profile')),
actions: [
SignedOutAction((context) {
Navigator.of(context).pop();
}),
],
),
),
);
},
),
],
automaticallyImplyLeading: false,
),
body: Center(
child: Column(
children: [
SizedBox(width: 250, child: Image.asset('assets/dash.png')),
Text('Welcome!', style: Theme.of(context).textTheme.displaySmall),
const SignOutButton(),
],
),
),
);
}
}
Argument ProfileScreen.appBar
przyjmuje widżet AppBar
z pakietu Flutter Material, więc można go traktować jak dowolny inny widżet AppBar
, który został utworzony i przekazany do Scaffold
. W tym przykładzie zachowano domyślną funkcję automatycznego dodawania przycisku „Wstecz”, a ekran ma teraz tytuł.
Dodawanie dzieci na ekranie profilu
Widget ProfileScreen
ma też opcjonalny argument o nazwie children. Ten argument akceptuje listę widżetów, które są umieszczane pionowo w widżecie Column
, które jest już używane wewnętrznie do tworzenia widżetu ProfileScreen
. Ten widget Column
w metodzie tworzenia ProfileScreen
umieści przekazywane przez Ciebie elementy nad przyciskiem „Wyloguj”.
Zaktualizuj kod w miejscu home.dart
, aby wyświetlić logo firmy, podobnie jak na ekranie logowania.
lib/home.dart
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: [
IconButton(
icon: const Icon(Icons.person),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute<ProfileScreen>(
builder: (context) => ProfileScreen(
appBar: AppBar(title: const Text('User Profile')),
actions: [
SignedOutAction((context) {
Navigator.of(context).pop();
}),
],
children: [
const Divider(),
Padding(
padding: const EdgeInsets.all(2),
child: AspectRatio(
aspectRatio: 1,
child: Image.asset('flutterfire_300x.png'),
),
),
],
),
),
);
},
),
],
automaticallyImplyLeading: false,
),
body: Center(
child: Column(
children: [
SizedBox(width: 250, child: Image.asset('assets/dash.png')),
Text('Welcome!', style: Theme.of(context).textTheme.displaySmall),
const SignOutButton(),
],
),
),
);
}
}
Załaduj ponownie aplikację. Na ekranie zobaczysz:
7. Logowanie przez Google na wielu platformach
FlutterFire UI udostępnia też widżety i funkcje umożliwiające uwierzytelnianie się u dostawców zewnętrznych, takich jak Google, Twitter, Facebook, Apple i GitHub.
Aby zintegrować się z uwierzytelnianiem Google, zainstaluj oficjalny wtyczek firebase_ui_oauth_google i jego zależności, które będą obsługiwać natywny proces uwierzytelniania. W terminalu przejdź do katalogu głównego projektu Flutter i wpisz to polecenie:
flutter pub add google_sign_in firebase_ui_oauth_google
Włącz dostawcę logowania przez Google
Następnie włącz dostawcę Google w konsoli Firebase:
- W konsoli otwórz ekran Dostawcy logowania z uwierzytelnianiem.
- Kliknij „Dodaj nowego dostawcę”.
- Wybierz „Google”.
- Przesuń przełącznik „Włącz” i kliknij „Zapisz”.
- Jeśli pojawi się okno z informacjami o pobieraniu plików konfiguracji, kliknij „Gotowe”.
- Sprawdź, czy dostawca logowania Google został dodany.
Dodawanie przycisku logowania przez Google
Gdy logowanie się w Google jest włączone, dodaj na ekranie logowania widżet, który wyświetla stylizowany przycisk logowania Google. Otwórz plik auth_gate.dart
i zaktualizuj kod, aby wyglądał tak:
lib/auth_gate.dart
import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider;
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:firebase_ui_oauth_google/firebase_ui_oauth_google.dart'; // Add this import
import 'package:flutter/material.dart';
import 'home.dart';
class AuthGate extends StatelessWidget {
const AuthGate({super.key, required this.clientId});
final String clientId;
@override
Widget build(BuildContext context) {
return StreamBuilder<User?>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return SignInScreen(
providers: [
EmailAuthProvider(),
GoogleProvider(clientId: clientId), // Add this line
],
headerBuilder: (context, constraints, shrinkOffset) {
return Padding(
padding: const EdgeInsets.all(20),
child: AspectRatio(
aspectRatio: 1,
child: Image.asset('assets/flutterfire_300x.png'),
),
);
},
subtitleBuilder: (context, action) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: action == AuthAction.signIn
? const Text('Welcome to FlutterFire, please sign in!')
: const Text('Welcome to Flutterfire, please sign up!'),
);
},
footerBuilder: (context, action) {
return const Padding(
padding: EdgeInsets.only(top: 16),
child: Text(
'By signing in, you agree to our terms and conditions.',
style: TextStyle(color: Colors.grey),
),
);
},
sideBuilder: (context, shrinkOffset) {
return Padding(
padding: const EdgeInsets.all(20),
child: AspectRatio(
aspectRatio: 1,
child: Image.asset('flutterfire_300x.png'),
),
);
},
);
}
return const HomeScreen();
},
);
}
}
Jedynym nowym kodem jest GoogleProvider(clientId: "YOUR_WEBCLIENT_ID")
dodany do konfiguracji widżetu SignInScreen
.
Po dodaniu tego elementu ponownie załaduj aplikację. Zobaczysz przycisk logowania w Google.
Konfigurowanie przycisku logowania
Przycisk nie działa bez dodatkowej konfiguracji. Jeśli tworzysz aplikację za pomocą Flutter Web, to jest jedyny krok, który musisz wykonać. Inne platformy wymagają wykonania dodatkowych czynności, które opisujemy poniżej.
- W konsoli Firebase otwórz stronę Dostawcy uwierzytelniania.
- Kliknij dostawcę Google.
- Kliknij panel „Konfiguracja pakietu SDK dla klienta internetowego”.
- Skopiuj wartość z pola „Identyfikator klienta internetowego”.
- Wróć do edytora tekstu i zaktualizuj wystąpienie
GoogleProvider
w plikuauth_gate.dart
, przekazując ten identyfikator do parametru o nazwieclientId
.
GoogleProvider(
clientId: "YOUR_WEBCLIENT_ID"
)
Po wpisaniu identyfikatora klienta internetowego ponownie załaduj aplikację. Jeśli korzystasz z wersji internetowej, po naciśnięciu przycisku „Zaloguj się przez Google” pojawi się nowe okno, które przeprowadzi Cię przez proces logowania w Google. Początkowo wygląda to tak:
Konfigurowanie iOS
Aby funkcja działała na iOS, musisz wykonać dodatkowy proces konfiguracji.
- W konsoli Firebase otwórz ekran Ustawienia projektu. Na karcie zobaczysz listę aplikacji Firebase, która będzie wyglądać tak:
- Wybierz iOS. Pamiętaj, że nazwa Twojej aplikacji będzie inna niż widoczna na zrzucie ekranu. Jeśli podczas wykonywania tego ćwiczenia korzystasz z projektu
flutter-codelabs/firebase-auth-flutterfire-ui/start
, w miejscu „complete” (ukończono) zobaczysz „start” (rozpoczęto). - Aby pobrać potrzebny plik konfiguracji, kliknij przycisk
GoogleServices-Info.plist
. - Przeciągnij pobrany plik do katalogu
/ios/Runner
w projekcie Flutter. - Otwórz Xcode, uruchamiając to polecenie w terminalu w katalogu głównym projektu:
open ios/Runner.xcworkspace
- Kliknij prawym przyciskiem myszy katalog Runner i wybierz Dodaj pliki do „Runner”.
- W menedżerze plików wybierz
GoogleService-Info.plist
. - W edytorze tekstu (który nie jest Xcode) dodaj atrybuty
CFBundleURLTypes
podane poniżej do plikuios/Runner/Info.plist
.<!-- Put me in the [my_project]/ios/Runner/Info.plist file --> <!-- Google Sign-in Section --> <key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleTypeRole</key> <string>Editor</string> <key>CFBundleURLSchemes</key> <array> <!-- TODO Replace this value: --> <!-- Copied from GoogleService-Info.plist key REVERSED_CLIENT_ID --> <string>com.googleusercontent.apps.861823949799-vc35cprkp249096uujjn0vvnmcvjppkn</string> </array> </dict> </array> <!-- End of the Google Sign-in Section -->
- Musisz zastąpić wartość
GoogleProvider.clientId
dodaną w konfiguracji internetowej identyfikatorem klienta powiązanym z Twoim identyfikatorem klienta Firebase na iOS. Najpierw możesz znaleźć ten identyfikator w plikufirebase_options.dart
jako część stałejiOS
. Skopiuj wartość przekazaną doiOSClientId
.static const FirebaseOptions ios = FirebaseOptions( apiKey: 'YOUR API KEY', appId: 'YOUR APP ID', messagingSenderId: '', projectId: 'PROJECT_ID', storageBucket: 'PROJECT_ID.firebasestorage.app', iosClientId: 'IOS CLIENT ID', // Find your iOS client Id here. iosBundleId: 'com.example.BUNDLE', );
- Wklej tę wartość w zmiennej
clientId
w plikulib/main.dart
.
lib/main.dart
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'app.dart';
import 'firebase_options.dart';
const clientId = 'YOUR_CLIENT_ID'; // Replace this value with your Client ID.
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
runApp(const MyApp(clientId: clientId));
}
Jeśli aplikacja Flutter jest już uruchomiona na iOS, musisz ją całkowicie zamknąć, a potem ponownie uruchomić. W przeciwnym razie uruchom aplikację na iOS.
8. Gratulacje!
Udało Ci się ukończyć ćwiczenie dotyczące interfejsu Firebase Auth dla Fluttera . Gotowy kod tego ćwiczenia z programowania znajdziesz w katalogu firebase-auth-flutterfire-ui/complete
na GitHubie.
Omówione zagadnienia
- Konfigurowanie aplikacji Flutter pod kątem używania Firebase
- Konfigurowanie projektu Firebase w konsoli Firebase
- FlutterFire CLI
- wiersz poleceń Firebase
- Korzystanie z Uwierzytelniania Firebase
- Zarządzanie uwierzytelnianiem Firebase w aplikacji Flutter za pomocą interfejsu FlutterFire
Następne kroki
- Dowiedz się więcej o używaniu Firestore i uwierzytelniania w Flutterze: Poznaj Firebase w ramach Codelab dla Fluttera.
- Poznaj inne narzędzia Firebase do tworzenia aplikacji Flutter:
Więcej informacji
- Strona Firebase: firebase.google.com
- Witryna Flutter: flutter.dev
- Widgety FlutterFire Firebase Flutter: firebase.flutter.dev
- Kanał Firebase w YouTube
- Kanał Flutter w YouTube
Sparky jest tutaj, aby świętować z Tobą!