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 sia l'autenticazione email/password sia l'autenticazione Accedi con Google a un'app Flutter. Imparerai anche a configurare un progetto Firebase e a utilizzare l'interfaccia a riga di comando FlutterFire per inizializzare Firebase nell'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 un po' di esperienza con Firebase, ma non è un problema se non hai mai aggiunto Firebase a un progetto Flutter. Se non hai dimestichezza con la console Firebase o se sei completamente nuovo a Firebase, consulta prima i seguenti link:

Che cosa creerai

Questo codelab ti guida nella creazione del flusso di autenticazione per un'app Flutter utilizzando Firebase for Authentication. 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 una configurazione Firebase in Dart
  • Aggiunta di Firebase Authentication all'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 della pagina "Password dimenticata?"
  • Aggiunta di Accedi con Google con firebase_ui_auth
  • Configurazione dell'app in modo che funzioni con più provider di accesso.
  • Aggiunta della schermata di un profilo utente alla tua 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)
  • il browser Google Chrome o il tuo altro target di sviluppo preferito per Flutter. (Alcuni comandi del terminale in questo codelab presuppongono che tu stia eseguendo la tua app su Chrome)

2. Crea e configura un progetto Firebase

La prima attività da completare è la creazione di 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.

Abilita l'accesso via email per Firebase Authentication

L'app che stai creando utilizza Firebase Authentication per consentire ai tuoi utenti di accedere alla tua app. Inoltre, consente ai nuovi utenti di registrarsi dall'applicazione Flutter.

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

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

  1. Nella console Firebase, espandi il menu Build nel riquadro a sinistra.
  2. Fai clic su Autenticazione, quindi sul pulsante Inizia, quindi sulla scheda Metodo di accesso (oppure 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 Abilita su On e fai clic su Salva. 58e3e3e23c2f16a4.png

3. Configurare l'app Flutter

Prima di iniziare, dovrai 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 dell'interfaccia a riga di comando 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 una volta completato, cerca nella directory denominata complete per eseguire un controllo 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 nel tuo IDE preferito.

Installa l'interfaccia a riga di comando di Firebase

L'interfaccia a riga di comando di Firebase fornisce strumenti per gestire i progetti Firebase. L'interfaccia a riga di comando è necessaria per l'interfaccia a riga di comando FlutterFire, che installerai tra poco.

Esistono diversi modi per installare l'interfaccia a riga di comando. 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 questo comando:
firebase login
  1. Questo comando connette la tua macchina locale a Firebase e ti garantisce 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 deve corrispondere ai progetti Firebase elencati nella Console di 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 il processo di installazione di Firebase su tutte le piattaforme supportate nella tua app Flutter. Si basa 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 tuo progetto Firebase all'app Flutter

Configura 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 previsti passaggi per configurare Firebase Authentication per Flutter per web, iOS e Android, ma puoi impostare 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 per la 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 chiamato firebase_options.dart. Questo file contiene una classe denominata FirebaseOptions, con variabili statiche che contengono la configurazione 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.ARROW

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 il termine applicazione per fare riferimento a build specifiche di una specifica piattaforma in un progetto Firebase. Ad esempio, il progetto Firebase chiamato 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.

Aggiungi 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 ancora stati aggiunti. Nel terminale, assicurati di essere nella directory principale del progetto Flutter all'indirizzo flutter-codelabs/firebase-emulator-suite/start. Quindi, esegui questi tre comandi:

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 a questo punto.

Inizializza Firebase

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

main.dardi

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 canali della piattaforma nativi, 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 è in esecuzione e trasmette le chiavi Firebase corrispondenti.

4. Aggiungi la pagina iniziale di Firebase UI Auth

La UI di Firebase per Auth fornisce widget che rappresentano schermi interi dell'applicazione. Queste schermate gestiscono diversi flussi di autenticazione all'interno dell'applicazione, ad esempio Accesso, Registrazione, Password dimenticata, Profilo utente e altro ancora. Per iniziare, aggiungi all'app una pagina di destinazione che funga da protezione dell'autenticazione per l'applicazione principale.

App Material o Cupertino

L'interfaccia utente di FlutterFire richiede il wrapping dell'applicazione in MaterialApp o CupertinoApp. A seconda della tua scelta, nell'interfaccia utente le differenze tra i widget Material e Cupertino verranno mostrate automaticamente. Per questo codelab, utilizza MaterialApp, che è già stato aggiunto all'app in app.dart.

app.arrow

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

Controlla 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 proprio metodo di build. 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 abbonarti a questo stato nella nostra applicazione, puoi usare il widget StreamBuilder di Flutter e trasmettergli lo stream.

StreamBuilder è un widget che si crea in base all'ultimo snapshot dei dati di uno stream che gli hai passato. Si ricrea 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();
      },
    );
  }
}
  • StreamBuilder.stream viene passato FirebaseAuth.instance.authStateChanged, il suddetto flusso, che restituirà un oggetto Firebase User se l'utente si è autenticato. In caso contrario, restituirà null.
  • Successivamente, il codice utilizza snapshot.hasData per verificare se il valore del flusso contiene l'oggetto User.
  • In caso contrario, ti verrà restituito un widget SignInScreen. Al momento, quella schermata non funziona. Questa informazione verrà aggiornata 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 dimenticano la password, possono toccare "Password dimenticata?" e aprire un modulo per reimpostare la password.
  • Se un utente non è ancora registrato, può toccare "Registrati" per visualizzare un altro modulo che gli consente di registrarsi.

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

auth_gate.ARROW

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 suo argomento providers, è l'unico codice necessario per ottenere tutte le funzionalità sopra citate. A questo punto dovresti visualizzare una schermata di accesso con input 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.

Personalizza 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, definito nel pacchetto dell'interfaccia utente di FlutterFire.

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

Poiché si tratta di un callback, espone i valori che potresti usare, come BuildContext e BoxConstraints, e richiede la restituzione di 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 mostra tre parametri aggiuntivi che ti consentono di personalizzare la schermata: subtitleBuilder, footerBuilder e sideBuilder.

subtitleBuilder è leggermente diverso in quanto gli argomenti di 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.ARROW

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 è uguale all'argomento 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 su app desktop e web.

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.ARROW per aggiungere widget sideBuilder.

auth_gate.ARROW

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 l'app dovrebbe avere l'aspetto seguente 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 usato 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 email e 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 all'applicazione Flutter e accedere a un utente tramite la pagina di accesso. L'app dovrebbe avere il seguente aspetto:

dd43d260537f3b1a.png

6. Schermata profilo

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

Aggiungere il widget ProfileScreen

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

home.ARROW

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. Questo percorso mostrerà il widget ProfileScreen, restituito dal callback MaterialPageRoute.builder.

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

36487fc4ab4f26a7.png

Questa è l&#39;interfaccia utente standard fornita dalla pagina dell&#39;interfaccia utente di FlutterFire. Tutti i pulsanti e i campi di testo sono collegati a Firebase Auth e sono subito pronti all'uso. 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 "Esci", l'app non cambierà. Ti disconnetterà, ma non ti reindirizzerà al widget AuthGate. Per implementare questa funzionalità, utilizza il parametro ProfileScreen.actions.

Innanzitutto, aggiorna il codice in home.ARROW.

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 del tipo FlutterFireUiAction. Esistono molte classi diverse che sono sottotipi di FlutterFireUiAction e in generale le utilizzi per indicare alla tua app di reagire ai diversi cambiamenti dello stato di autorizzazione. SignedOutAction chiama una funzione di callback da te assegnata quando lo stato di autenticazione Firebase cambia e il valore currentUser è null.

Se aggiungi un callback che chiama Navigator.of(context).pop() quando si attiva SignedOutAction, l'app passerà 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 esce dall'app, nell'app viene visualizzata la pagina di accesso.

Personalizzare la pagina del profilo

Come la pagina di accesso, la pagina del profilo è personalizzabile. In primo luogo, nella pagina attuale non è possibile tornare alla home page una volta che l'utente si trova sulla pagina del profilo. Per risolvere il problema, assegna al widget ProfileScreen un'AppBar.

home.ARROW

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, viene mantenuta la funzionalità predefinita di aggiunta automatica di un pulsante "Indietro" e allo schermo viene ora assegnato 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 ProfileScreen. Questo widget Colonna nel metodo di creazione ProfileScreen collocherà i bambini che lo passi sopra il pulsante "Esci".

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 la tua app, vedrai questo sullo schermo:

ebe5792b765dbf87.png

7. Accesso di 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

A questo punto, attiva 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 a Google sia stato aggiunto. 5329ce0543c90d95.png

Aggiungere il pulsante di accesso con Google

Con l&#39;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.arrow

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&#39;accesso

Il pulsante non funziona senza una configurazione aggiuntiva. Se stai sviluppando con Flutter Web, questo è l'unico passaggio che devi aggiungere affinché questa operazione funzioni. Altre piattaforme richiedono passaggi aggiuntivi, che verranno discussi a breve.

  1. Vai alla pagina Provider 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

Configura iOS

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

  1. Vai alla schermata Impostazioni progetto nella Console Firebase. Visualizzerai una scheda con l'elenco delle 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 "Completato" 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 questo comando del terminale dalla directory 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 di 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 l'interfaccia utente di Firebase Auth per il codelab Flutter . Puoi trovare il codice completato per 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
  • Utilizzo dell'interfaccia utente di FlutterFire per gestire facilmente l'autenticazione Firebase nell'app Flutter

Passaggi successivi

Scopri di più

Sparky è qui per festeggiare con te!

2a0ad195769368b1.gif