Aggiungere un flusso di autenticazione utente a un'app Flutter utilizzando FirebaseUI

1. Prima di iniziare

In questo codelab imparerai ad aggiungere Firebase Authentication alla tua app Flutter utilizzando il pacchetto FlutterFire UI. Con questo pacchetto, aggiungerai l'autenticazione email/password e l'autenticazione di Google Sign In a un'app Flutter. Scoprirai inoltre come configurare un progetto Firebase e utilizzare l'interfaccia a riga di comando FlutterFire per inizializzare Firebase nella tua app Flutter.

Prerequisiti

Questo codelab presuppone che tu abbia una certa esperienza con Flutter. In caso contrario, ti consigliamo di apprendere prima le nozioni di base. I seguenti link sono utili:

Dovresti anche avere una certa esperienza con Firebase, ma non preoccuparti se non hai mai aggiunto Firebase a un progetto Flutter. Se non hai dimestichezza con la Console Firebase o se non hai mai utilizzato Firebase, consulta prima i seguenti link:

Cosa creerai

Questo codelab ti guida nella creazione del flusso di autenticazione per un'app Flutter utilizzando Firebase per l'autenticazione. L'applicazione avrà una schermata di accesso, una schermata "Registrati", una schermata di recupero della password e una schermata del profilo utente.

6604fc9157f2c6ae.png eab9509a41074930.png da49189a5838e0bb.png b2ccfb3632b77878.png

Obiettivi didattici

Questo codelab illustra:

  • Aggiunta di Firebase a un'app Flutter
  • Configurazione della console Firebase
  • Utilizzo dell'interfaccia a riga di comando di Firebase per aggiungere Firebase all'applicazione
  • Utilizzo dell'interfaccia a riga di comando FlutterFire per generare la configurazione di Firebase in Dart
  • Aggiunta di Firebase Authentication alla tua app Flutter
  • Configurazione di Firebase Authentication nella console
  • Aggiunta dell'accesso con email e password con il pacchetto firebase_ui_auth
  • Aggiunta della registrazione utente con il pacchetto firebase_ui_auth
  • Aggiunta di una pagina "Password dimenticata?"
  • Aggiunta di Accedi con Google con firebase_ui_auth
  • Configurare l'app in modo che funzioni con più provider di accesso.
  • Aggiunta di una schermata del profilo utente all'applicazione con il pacchetto firebase_ui_auth

Questo codelab riguarda in modo specifico l'aggiunta di un sistema di autenticazione solido utilizzando il pacchetto firebase_ui_auth. Come vedrai, l'intera app, con tutte le funzionalità sopra indicate, può essere implementata con circa 100 righe di codice.

Che cosa ti serve

  • Conoscenza pratica di Flutter e dell'SDK installato
  • Un editor di testo (IDE JetBrains, Android Studio e VS Code sono supportati da Flutter)
  • Browser Google Chrome o un altro target di sviluppo preferito per Flutter. (alcuni comandi del terminale in questo codelab presuppongono che tu stia eseguendo l'app su Chrome)

2. Crea e configura un progetto Firebase

La prima operazione da completare è creare un progetto Firebase nella console web di Firebase.

Crea un progetto Firebase

  1. Accedi a Firebase.
  2. Nella Console Firebase, fai clic su Aggiungi progetto (o Crea un progetto) e inserisci un nome per il progetto Firebase (ad esempio "FlutterFire-UI-Codelab").

df42a5e3d9584b48.png

  1. Fai clic sulle opzioni di creazione del progetto. Accetta i Termini di Firebase, se richiesto. Salta la configurazione di Google Analytics perché non utilizzerai Analytics per questa app.

d1fcec48bf251eaa.png

Per scoprire di più sui progetti Firebase, consulta Informazioni sui progetti Firebase.

Attivare l'accesso con email per Firebase Authentication

L'app che stai creando utilizza Firebase Authentication per consentire agli utenti di accedere alla tua app. Consente inoltre ai nuovi utenti di registrarsi dall'applicazione Flutter.

Firebase Authentication deve essere attivata utilizzando la console Firebase e, una volta attivata, richiede una configurazione speciale.

Per consentire agli utenti di accedere all'app web, utilizza innanzitutto il metodo di accesso Email/password. In un secondo momento, aggiungerai il metodo Accedi con Google.

  1. Nella console Firebase, espandi il menu Build nel riquadro a sinistra.
  2. Fai clic su Autenticazione, poi sul pulsante Inizia e infine sulla scheda Metodo di accesso (o fai clic qui per andare direttamente alla scheda Metodo di accesso).
  3. Fai clic su Email/Password nell'elenco Provider di accesso, imposta l'opzione Attiva su On e poi fai clic su Salva. 58e3e3e23c2f16a4.png

3. Configurare l'app Flutter

Prima di iniziare, devi scaricare il codice di avvio e installare l'interfaccia a riga di comando di Firebase.

Ottieni il codice di avvio

Clona il repository GitHub dalla riga di comando:

git clone https://github.com/flutter/codelabs.git flutter-codelabs

In alternativa, se hai installato lo strumento CLI di GitHub :

gh repo clone flutter/codelabs flutter-codelabs

Il codice di esempio deve essere clonato nella directory flutter-codelabs del computer, che contiene il codice di una raccolta di codelab. Il codice di questo codelab si trova nella sottodirectory flutter-codelabs/firebase-auth-flutterfire-ui.

La directory flutter-codelabs/firebase-auth-flutterfire-ui contiene due progetti Flutter. Uno si chiama complete e l'altro start. La directory start contiene un progetto incompleto ed è qui che passerai più tempo.

cd flutter-codelabs/firebase-auth-flutterfire-ui/start

Se vuoi andare avanti o vedere come dovrebbe apparire qualcosa al termine, cerca nella directory denominata completa per il riferimento incrociato.

Se vuoi seguire il codelab e aggiungere del codice, devi iniziare con l'app Flutter in flutter-codelabs/firebase-auth-flutterfire-ui/start e aggiungere codice al progetto durante il codelab. Apri o importa la directory nell'IDE che preferisci.

Installa l'interfaccia a riga di comando di Firebase

L'interfaccia a riga di comando di Firebase fornisce strumenti per la gestione dei progetti Firebase. L'interfaccia a riga di comando è necessaria per l'interfaccia a riga di comando FlutterFire, che installerai a breve.

Esistono diversi modi per installare la CLI. Il modo più semplice, se utilizzi MacOS o Linux, è eseguire questo comando dal terminale:

curl -sL https://firebase.tools | bash

Dopo aver installato l'interfaccia a riga di comando, devi autenticarti con Firebase.

  1. Accedi a Firebase utilizzando il tuo Account Google eseguendo il seguente comando:
firebase login
  1. Questo comando connette il computer locale a Firebase e ti concede l'accesso ai tuoi progetti Firebase.
  1. Verifica che l'interfaccia a riga di comando sia installata correttamente e abbia accesso al tuo account elencando i tuoi progetti Firebase. Esegui questo comando:
firebase projects:list
  1. L'elenco visualizzato dovrebbe essere uguale a quello dei progetti Firebase elencati nella Console Firebase. Dovresti vedere almeno flutterfire-ui-codelab.

Installa l'interfaccia a riga di comando FlutterFire

L'interfaccia a riga di comando FlutterFire è uno strumento che semplifica la procedura di installazione di Firebase su tutte le piattaforme supportate nella tua app Flutter. È basata sull'interfaccia a riga di comando di Firebase.

Innanzitutto, installa l'interfaccia a riga di comando:

dart pub global activate flutterfire_cli

Assicurati che la CLI sia stata installata. Esegui il seguente comando e assicurati che l'interfaccia a riga di comando mostri il menu di aiuto.

flutterfire -—help

Aggiungi il progetto Firebase all'app Flutter

Configurare FlutterFire

Puoi utilizzare FlutterFire per generare il codice Dart necessario per utilizzare Firebase nella tua app Flutter.

flutterfire configure

Quando viene eseguito questo comando, ti verrà chiesto di selezionare il progetto Firebase che vuoi utilizzare e le piattaforme che vuoi configurare.

Gli screenshot seguenti mostrano i prompt a cui dovrai rispondere.

  1. Seleziona il progetto che vuoi utilizzare. In questo caso, utilizza flutterfire-ui-codelab 1359cdeb83204baa.png
  2. Seleziona le piattaforme che vuoi utilizzare. In questo codelab sono descritti i passaggi per configurare Firebase Authentication per Flutter per web, iOS e Android, ma puoi configurare il tuo progetto Firebase in modo da utilizzare tutte le opzioni. 301c9534f594f472.png
  3. Questo screenshot mostra l'output al termine del processo. Se hai dimestichezza con Firebase, noterai che non hai dovuto creare applicazioni di piattaforma (ad esempio un'applicazione per Android) nella console, ma che è stato FlutterFire CLI a farlo per te. 12199a85ade30459.png

Al termine, controlla l'app Flutter nell'editor di testo. L'interfaccia a riga di comando FlutterFire ha generato un nuovo file denominato firebase_options.dart. Questo file contiene una classe denominata FirebaseOptions, che ha variabili statiche che contengono la configurazione di Firebase necessaria per ogni piattaforma. Se hai selezionato tutte le piattaforme quando hai eseguito flutterfire configure, vedrai valori statici denominati web, android, ios e macos.

firebase_options.dart

import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
import 'package:flutter/foundation.dart'
   show defaultTargetPlatform, kIsWeb, TargetPlatform;

/// Default [FirebaseOptions] for use with your Firebase apps.
///
/// Example:
/// ```dart
/// import 'firebase_options.dart';
/// // ...
/// await Firebase.initializeApp(
///   options: DefaultFirebaseOptions.currentPlatform,
/// );
/// ```
class DefaultFirebaseOptions {
 static FirebaseOptions get currentPlatform {
   if (kIsWeb) {
     return web;
   }
   // ignore: missing_enum_constant_in_switch
   switch (defaultTargetPlatform) {
     case TargetPlatform.android:
       return android;
     case TargetPlatform.iOS:
       return ios;
     case TargetPlatform.macOS:
       return macos;
   }

   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 utilizza la parola applicazione per fare riferimento a una build specifica per una piattaforma specifica in un progetto Firebase. Ad esempio, il progetto Firebase denominato FlutterFire-ui-codelab ha più applicazioni: una per Android, una per iOS, una per macOS e una per il web.

Il metodo DefaultFirebaseOptions.currentPlatform utilizza l'enum TargetPlatform esposto da Flutter per rilevare la piattaforma su cui è in esecuzione l'app e restituisce i valori di configurazione di Firebase necessari per l'applicazione Firebase corretta.

Aggiungere i pacchetti Firebase all'app Flutter

Il passaggio di configurazione finale consiste nell'aggiungere i pacchetti Firebase pertinenti al progetto Flutter. Il file firebase_options.dart dovrebbe contenere errori, perché si basa su pacchetti Firebase che non sono stati ancora aggiunti. Nel terminale, assicurati di trovarti nella directory principale del progetto Flutter in flutter-codelabs/firebase-emulator-suite/start. Poi, esegui i tre comandi che seguono:

flutter pub add firebase_core
flutter pub add firebase_auth
flutter pub add firebase_ui_auth

Questi sono gli unici pacchetti di cui hai bisogno in questo momento.

Inizializza Firebase

Per utilizzare i pacchetti aggiunti e DefaultFirebaseOptions.currentPlatform,, aggiorna il codice nella funzione main nel file main.dart.

main.dart

void main() async {
 WidgetsFlutterBinding.ensureInitialized();
 await Firebase.initializeApp(
   options: DefaultFirebaseOptions.currentPlatform,
 );


 runApp(const MyApp());
}

Questo codice fa due cose.

  1. WidgetsFlutterBinding.ensureInitialized() indica a Flutter di non iniziare a eseguire il codice del widget dell'applicazione finché il framework Flutter non è completamente avviato. Firebase utilizza i canali della piattaforma nativa, che richiedono l'esecuzione del framework.
  2. Firebase.initializeApp configura una connessione tra la tua app Flutter e il tuo progetto Firebase. DefaultFirebaseOptions.currentPlatform viene importato dal file firebase_options.dart generato. Questo valore statico rileva la piattaforma su cui stai eseguendo l'app e passa le chiavi Firebase corrispondenti.

4. Aggiungi la pagina iniziale di Firebase UI Auth

Firebase UI for Auth fornisce widget che rappresentano intere schermate dell'applicazione. Queste schermate gestiscono diversi flussi di autenticazione nell'applicazione, ad esempio Accesso, Registrazione, Password dimenticata, Profilo utente e altro ancora. Per iniziare, aggiungi una pagina di destinazione alla tua app che agisca come guardia di autenticazione per l'applicazione principale.

App Material o Cupertino

L'interfaccia utente di FlutterFire richiede che l'applicazione sia racchiusa in MaterialApp o CupertinoApp. A seconda della tua scelta, l'interfaccia utente rifletterà automaticamente le differenze dei widget Material o Cupertino. Per questo codelab, utilizza MaterialApp, che è già stato aggiunto all'app in app.dart.

app.dart

import 'package:flutter/material.dart';
import 'auth_gate.dart';

class MyApp extends StatelessWidget {
 const MyApp({super.key});
 @override
 Widget build(BuildContext context) {
   return MaterialApp(
     theme: ThemeData(
       primarySwatch: Colors.blue,
     ),
     home: const AuthGate(),
   );
 }
}

Controllare lo stato dell'autenticazione

Prima di poter mostrare una schermata di accesso, devi determinare se l'utente è attualmente autenticato. Il modo più comune per verificare questo problema è ascoltare authStateChanges di FirebaseAuth utilizzando il plug-in Firebase Auth.

Nell'esempio di codice riportato sopra, MaterialApp sta creando un widget AuthGate nel suo metodo di compilazione. Si tratta di un widget personalizzato, non fornito dall'interfaccia utente di FlutterFire.

Il widget deve essere aggiornato per includere lo stream authStateChanges.

L'API authStateChanges restituisce un Stream con l'utente corrente (se ha eseguito l'accesso) o null se non l'ha fatto. Per iscriverti a questo stato nella nostra applicazione, puoi utilizzare il widget StreamBuilder di Flutter e passargli lo stream.

StreamBuilder è un widget che si crea in base all'ultimo snapshot dei dati di uno stream che gli hai passato. Viene ricostruito automaticamente quando lo stream emette un nuovo snapshot.

Aggiorna il codice in auth_gate.dart.

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});

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<User?>(
      stream: FirebaseAuth.instance.authStateChanges(),
      builder: (context, snapshot) {
        if (!snapshot.hasData) {
          return SignInScreen(
            providers: [],
          );
        }

        return const HomeScreen();
      },
    );
  }
}
  • A StreamBuilder.stream viene passato FirebaseAuth.instance.authStateChanged, lo stream sopra menzionato, che restituirà un oggetto User di Firebase se l'utente ha eseguito l'autenticazione. In caso contrario, restituirà null.
  • Successivamente, il codice utilizza snapshot.hasData per verificare se il valore dello stream contiene l'oggetto User.
  • In caso contrario, restituirà un widget SignInScreen. Al momento, questa schermata non fa nulla. Questo valore verrà aggiornato nel passaggio successivo.
  • In caso contrario, restituisce un HomeScreen, ovvero la parte principale dell'applicazione a cui solo gli utenti autenticati possono accedere.

SignInScreen è un widget del pacchetto FlutterFire UI. Questo sarà l'obiettivo del passaggio successivo di questo codelab. A questo punto, quando esegui l'app, dovresti visualizzare una schermata di accesso vuota.

5. Schermata di accesso

Il widget SignInScreen, fornito dall'interfaccia utente di FlutterFire, aggiunge le seguenti funzionalità:

  • Consente agli utenti di accedere
  • Se gli utenti hanno dimenticato la password, possono toccare "Password dimenticata?" e aprire un modulo per reimpostarla.
  • Se un utente non ha ancora effettuato la registrazione, può toccare "Registrati" e verrà indirizzato a un altro modulo che gli consente di registrarsi.

Anche in questo caso, sono necessarie solo un paio di righe di codice. Ricorda il codice nel widget AuthGate:

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});

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<User?>(
      stream: FirebaseAuth.instance.authStateChanges(),
      builder: (context, snapshot) {
        if (!snapshot.hasData) {
          return SignInScreen(
            providers: [
              EmailAuthProvider(), // new
            ],
          );
        }

        return const HomeScreen();
      },
    );
  }
}

Il widget SignInScreen e il relativo argomento providers sono l'unico codice necessario per ottenere tutte le funzionalità sopra menzionate. Dovresti visualizzare una schermata di accesso con campi di testo "Email" e "Password", nonché un pulsante "Accedi".

Sebbene sia funzionale, manca di stile. Il widget espone i parametri per personalizzare l'aspetto della schermata di accesso. Ad esempio, potresti voler aggiungere il logo della tua azienda.

Personalizzare la schermata di accesso

headerBuilder

Utilizzando l'argomento SignInScreen.headerBuilder, puoi aggiungere i widget che preferisci sopra il modulo di accesso. Questo widget viene visualizzato solo su schermi stretti, come i dispositivi mobili. Su schermi ampi, puoi utilizzare SignInScreen.sideBuilder, di cui parleremo più avanti in questo codelab.

Aggiorna il file auth_gate.dart con questo codice:

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});

 @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'),
               ),
             );
           },
         );
       }

       return const HomeScreen();
     },
   );
 }
}

L'argomento headerBuilder richiede una funzione di tipo HeaderBuilder, definita nel pacchetto FlutterFire UI.

typedef HeaderBuilder = Widget Function(
 BuildContext context,
 BoxConstraints constraints,
 double shrinkOffset,
);

Poiché si tratta di un callback, espone i valori che potresti utilizzare, come BuildContext e BoxConstraints, e richiede di restituire un widget. Il widget restituito viene visualizzato nella parte superiore dello schermo. In questo esempio, il nuovo codice aggiunge un'immagine nella parte superiore dello schermo. La tua applicazione dovrebbe avere il seguente aspetto.

73d7548d91bbd2ab.png

Subtitle Builder

La schermata di accesso espone tre parametri aggiuntivi che ti consentono di personalizzarla: subtitleBuilder, footerBuilder e sideBuilder.

subtitleBuilder è leggermente diverso in quanto gli argomenti del callback includono un'azione di tipo AuthAction. AuthAction è un enum che puoi utilizzare per rilevare se la schermata in cui si trova l'utente è quella di "accesso" o quella di "registrazione".

Aggiorna il codice in auth_gate.dart per utilizzare subtitleBuilder.

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});

 @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('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!'),
             );
           },
         );
       }

       return const HomeScreen();
     },
   );
 }
}

Ricarica l'applicazione, che dovrebbe avere il seguente aspetto

L'argomento footerBuilder è lo stesso di subtitleBuilder. Non espone BoxConstraints o shrinkOffset, in quanto è destinato al testo anziché alle immagini. (anche se puoi aggiungere qualsiasi widget).

Aggiungi un piè di pagina alla schermata di accesso con questo codice.

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});

 @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('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),
               ),
             );
           },
         );
       }

       return const HomeScreen();
     },
   );
 }}

Side Builder

L'argomento SignInScreen.sidebuilder accetta un callback e questa volta gli argomenti di questo callback sono BuildContext e double shrinkOffset. Il widget restituito da sideBuilder verrà visualizzato a sinistra del modulo di accesso e solo su schermi ampi. Ciò significa che il widget verrà visualizzato solo sulle app web e desktop.

Internamente, l'interfaccia utente di FlutterFire utilizza un punto di interruzione per determinare se devono essere visualizzati i contenuti dell'intestazione (su schermi alti, come i dispositivi mobili) o i contenuti laterali (su schermi ampi, computer o web). Nello specifico, se una schermata è larga più di 800 pixel, vengono visualizzati i contenuti del riquadro del generatore e non quelli dell'intestazione. Se lo schermo è largo meno di 800 pixel, vale il contrario.

Aggiorna il codice in auth_gate.dart per aggiungere i widget sideBuilder.

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});

 @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('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();
     },
   );
 }
}

Ora la tua app dovrebbe avere questo aspetto quando espandi la larghezza della finestra (se utilizzi Flutter web o macOS).

8dc60b4e5d7dd2d0.png

Crea un utente

A questo punto, tutto il codice per questa schermata è stato completato. Tuttavia, prima di poter accedere, devi creare un utente. Puoi farlo con la schermata "Registrazione" oppure creare un utente nella Console Firebase.

Per utilizzare la console:

  1. Vai alla tabella "Utenti" nella Console Firebase.
  2. Fai clic qui
  3. Seleziona "flutterfire-ui-codelab" (o un altro progetto se hai utilizzato un nome diverso). Vedrai questa tabella:

f038fd9a58ed60d9.png

  1. Fai clic sul pulsante "Aggiungi utente".

2d78390d4c5dbbfa.png

  1. Inserisci un indirizzo email e una password per il nuovo utente. Possono essere un'email e una password false, come ho inserito nell'immagine di seguito. Funziona, ma la funzionalità "Hai dimenticato la password" non funziona se utilizzi un indirizzo email falso.

62ba0feb33d54add.png

  1. Fai clic su "Aggiungi utente"

32b236b3ef94d4c7.png

Ora puoi tornare alla tua applicazione Flutter e far accedere un utente tramite la pagina di accesso. L'app dovrebbe avere il seguente aspetto:

dd43d260537f3b1a.png

6. Schermata del profilo

L'interfaccia utente di FlutterFire fornisce anche un widget ProfileScreen, che offre molte funzionalità in poche righe di codice.

Aggiungere il widget ProfileScreen

Vai al file home.dart nell'editor di testo. Aggiornalo con questo codice:

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: [
            Image.asset('dash.png'),
            Text(
              'Welcome!',
              style: Theme.of(context).textTheme.displaySmall,
            ),
            const SignOutButton(),
          ],
        ),
      ),
    );
  }
}

Il nuovo codice della nota è il callback passato al pulsante IconButton.isPressed method.. Quando viene premuto IconButton.isPressed method., l'applicazione crea un nuovo percorso anonimo e vi accede.IconButton Questo percorso mostrerà il widget ProfileScreen, restituito dal callback MaterialPageRoute.builder.

Ricarica l'app e premi l'icona in alto a destra (nella barra dell'app). Viene visualizzata una pagina come questa:

36487fc4ab4f26a7.png

Questa è l'interfaccia utente standard fornita dalla pagina dell'interfaccia utente di FlutterFire. Tutti i pulsanti e i campi di testo sono collegati a Firebase Auth e funzionano immediatamente. Ad esempio, puoi inserire un nome nel campo di testo "Nome" e l'interfaccia utente di FlutterFire chiamerà il metodo FirebaseAuth.instance.currentUser?.updateDisplayName, che salverà il nome in Firebase.

Disconnessione

Al momento, se premi il pulsante "Uscire", l'app non cambia. Ti disconnetterà, ma non ti reindirizzerà al widget AuthGate. Per implementare questa funzionalità, utilizza il parametro ProfileScreen.actions.

Innanzitutto, aggiorna il codice in home.dart.

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: [
            Image.asset('dash.png'),
            Text(
              'Welcome!',
              style: Theme.of(context).textTheme.displaySmall,
            ),
            const SignOutButton(),
          ],
        ),
      ),
    );
  }
}

Ora, quando crei un'istanza di ProfileScreen, passi anche un elenco di azioni all'argomento ProfileScreen.actions. Queste azioni sono di tipo FlutterFireUiAction. Esistono molti tipi di classi che sono sottotipi di FlutterFireUiAction e, in genere, li utilizzi per indicare all'app di reagire a diverse modifiche dello stato di autenticazione. SignedOutAction chiama una funzione di callback che fornisci quando lo stato di autenticazione di Firebase cambia in modo che currentUser sia nullo.

Aggiungendo un callback che chiama Navigator.of(context).pop() quando viene attivato SignedOutAction, l'app passa alla pagina precedente. In questa app di esempio esiste un solo percorso permanente, che mostra la pagina di accesso se non è presente un utente che ha eseguito l'accesso e la home page se è presente un utente. Poiché questo accade quando l'utente si disconnette, l'app mostrerà la pagina di accesso.

Personalizzare la pagina del profilo

Come la pagina di accesso, anche la pagina del profilo è personalizzabile. Innanzitutto, la nostra pagina attuale non consente di tornare alla home page una volta che un utente è nella pagina del profilo. Per risolvere il problema, aggiungi un'AppBar al widget ProfileScreen.

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: [
           Image.asset('dash.png'),
           Text(
             'Welcome!',
             style: Theme.of(context).textTheme.displaySmall,
           ),
           const SignOutButton(),
         ],
       ),
     ),
   );
 }
}

L'argomento ProfileScreen.appBar accetta un widget AppBar dal pacchetto Flutter Material, quindi può essere trattato come qualsiasi altro AppBar che hai creato e passato a un Scaffold. In questo esempio, la funzionalità predefinita di aggiunta automatica di un pulsante "Indietro" viene mantenuta e la schermata ora ha un titolo.

Aggiungere bambini alla schermata del profilo

Il widget ProfileScreen ha anche un argomento facoltativo denominato children. Questo argomento accetta un elenco di widget, che verranno posizionati verticalmente all'interno di un widget Colonna già utilizzato internamente per creare la schermata Profilo. Questo widget Colonna nel metodo di compilazione ProfileScreen posiziona i figli che gli passi sopra il pulsante "Uscire".

Aggiorna il codice in home.dart per mostrare il logo dell'azienda qui, in modo simile alla schermata di accesso.

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: [
            Image.asset('dash.png'),
            Text(
              'Welcome!',
              style: Theme.of(context).textTheme.displaySmall,
            ),
            const SignOutButton(),
          ],
        ),
      ),
    );
  }
}

Ricarica l'app e vedrai questo messaggio sullo schermo:

ebe5792b765dbf87.png

7. Accesso con autenticazione Google multipiattaforma

L'interfaccia utente di FlutterFire fornisce anche widget e funzionalità per l'autenticazione con provider di terze parti, come Google, Twitter, Facebook, Apple e GitHub.

Per l'integrazione con l'autenticazione Google, installa il plug-in ufficiale firebase_ui_oauth_google e le relative dipendenze, che gestiranno il flusso di autenticazione nativo. Nel terminale, vai alla directory principale del progetto Flutter e inserisci il seguente comando:

flutter pub add google_sign_in
flutter pub add firebase_ui_oauth_google

Attivare il provider di accesso con Google

Poi, abilita il provider Google nella Console Firebase:

  1. Vai alla schermata Provider di accesso per l'autenticazione nella console.
  2. Fai clic su "Aggiungi nuovo fornitore". 8286fb28be94bf30.png
  3. Seleziona "Google". c4e28e6f4974be7f.png
  4. Attiva/disattiva l'opzione "Attiva" e premi "Salva". e74ff86990763826.png
  5. Se viene visualizzata una finestra modale con informazioni sul download dei file di configurazione, fai clic su "Fine".
  6. Verifica che il provider di accesso con Google sia stato aggiunto. 5329ce0543c90d95.png

Aggiungere il pulsante di accesso con Google

Con l'accesso con Google abilitato, aggiungi alla pagina di accesso il widget necessario per visualizzare un pulsante di accesso con Google stilizzato. Vai al file auth_gate.dart e aggiorna il codice come segue:

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'; // new
import 'package:flutter/material.dart';

import 'home.dart';

class AuthGate extends StatelessWidget {
 const AuthGate({super.key});

 @override
 Widget build(BuildContext context) {
   return StreamBuilder<User?>(
     stream: FirebaseAuth.instance.authStateChanges(),
     builder: (context, snapshot) {
       if (!snapshot.hasData) {
         return SignInScreen(
           providers: [
             EmailAuthProvider(),
             GoogleProvider(clientId: "YOUR_WEBCLIENT_ID"),  // new
           ],
           headerBuilder: (context, constraints, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('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();
     },
   );
 }
}

L'unico codice nuovo è l'aggiunta di GoogleProvider(clientId: "YOUR_WEBCLIENT_ID") alla configurazione del widget SignInScreen.

Dopo aver aggiunto questo codice, ricarica l'app e vedrai un pulsante di accesso con Google.

aca71a46a011bfb5.png

Pulsante Configura l'accesso

Il pulsante non funziona senza una configurazione aggiuntiva. Se stai sviluppando con Flutter Web, questo è l'unico passaggio da aggiungere per farlo funzionare. Altre piattaforme richiedono passaggi aggiuntivi, che verranno discussi a breve.

  1. Vai alla pagina Fornitori di autenticazione nella console Firebase.
  2. Fai clic sul provider Google. 9b3a325c5eca6e49.png
  3. Fai clic sul riquadro espandibile "Configurazione SDK web".
  4. Copia il valore da "ID client web" 711a79f0d931c60f.png
  5. Torna all'editor di testo e aggiorna l'istanza di GoogleProvider nel file auth_gate.dart passando questo ID al parametro denominato clientId.
GoogleProvider(
   clientId: "YOUR_WEBCLIENT_ID"
)

Dopo aver inserito l'ID client web, ricarica l'app. Quando premi il pulsante "Accedi con Google", viene visualizzata una nuova finestra (se utilizzi il web) che ti guida nella procedura di accesso con Google. Inizialmente avrà il seguente aspetto:

14e73e3c9de704bb.png

Configurare iOS

Affinché funzioni su iOS, è necessaria un'ulteriore procedura di configurazione.

  1. Vai alla schermata Impostazioni progetto nella Console Firebase. Vedrai una scheda che elenca le tue app Firebase, simile alla seguente: fefa674acbf213cc.png
  2. Fai clic su iOS. Tieni presente che il nome della tua applicazione sarà diverso dal mio. Se hai utilizzato il progetto flutter-codelabs/firebase-auth-flutterfire-ui/start per seguire questo codelab, al posto di "Completa" vedrai "Inizia".
  3. Fai clic sul pulsante "GoogleServices-Info.plist" per scaricare il file di configurazione necessario. f89b3192871dfbe3.png
  4. Trascina il file scaricato nella directory denominata/ios/Runner nel tuo progetto Flutter.
  5. Apri Xcode eseguendo il seguente comando del terminale dalla radice del progetto: open ios/Runner.xcworkspace
  6. Fai clic con il tasto destro del mouse sulla directory del programma di esecuzione e seleziona Aggiungi file a "Runner". 858986063a4c5201.png
  7. Seleziona GoogleService-Info.plist dal gestore file.
  8. Torna nell'editor di testo (diverso da Xcode) e aggiungi gli attributi CFBundleURLTypes riportati di seguito nel file [my_project]/ios/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 -->
  1. Devi sostituire il valore GoogleProvider.clientId che hai aggiunto nella configurazione web con l'ID cliente associato al tuo ID cliente Firebase per iOS. Innanzitutto, puoi trovare questo ID nel file firebase_options.dart, all'interno della costante iOS. Copia il valore passato a iOSClientId.
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',
);
  1. Incolla questo valore nell'argomento GoogleProvider.clientId nel widget AuthGate.
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';
import 'package:flutter/material.dart';

import 'home.dart';


class AuthGate extends StatelessWidget {
 const AuthGate({super.key});

 @override
 Widget build(BuildContext context) {
   return StreamBuilder<User?>(
     stream: FirebaseAuth.instance.authStateChanges(),
     builder: (context, snapshot) {
       if (!snapshot.hasData) {
         return SignInScreen(
           providers: [
             EmailAuthProvider(),
             GoogleProvider(clientId: "YOUR IOS CLIENT ID"),  // replace String
           ],
           headerBuilder: (context, constraints, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('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();
     },
   );
 }
}

Se la tua app Flutter è già in esecuzione su iOS, devi chiuderla completamente e poi eseguire di nuovo l'applicazione. In caso contrario, esegui l'app su iOS.

8. Complimenti!

Hai completato il codelab sull'interfaccia utente di Firebase Auth per Flutter . Puoi trovare il codice completo di questo codelab nella directory "complete" su GitHub: Flutter Codelabs

Argomenti trattati

  • Configurare un'app Flutter per l'utilizzo di Firebase
  • Configurare un progetto Firebase nella Console Firebase
  • Interfaccia a riga di comando FlutterFire
  • interfaccia a riga di comando di Firebase
  • Utilizzo di Firebase Authentication
  • Utilizzare la UI di FlutterFire per gestire facilmente l'autenticazione Firebase nella tua app Flutter

Passaggi successivi

Scopri di più

Sparky è qui per festeggiare con te.

2a0ad195769368b1.gif