Добавьте поток аутентификации пользователя в приложение Flutter с помощью FirebaseUI.

1. Прежде чем начать

В этой лабораторной работе вы узнаете, как добавить проверку подлинности Firebase в ваше приложение Flutter с помощью пакета пользовательского интерфейса FlutterFire. С помощью этого пакета вы добавите в приложение Flutter как аутентификацию по электронной почте/паролю, так и аутентификацию для входа в Google. Вы также узнаете, как настроить проект Firebase и использовать интерфейс командной строки FlutterFire для инициализации Firebase в вашем приложении Flutter.

Предварительные условия

В этой кодовой лаборатории предполагается, что у вас есть некоторый опыт работы с Flutter. Если нет, возможно, вы захотите сначала изучить основы. Следующие ссылки полезны:

У вас также должен быть некоторый опыт работы с Firebase, но ничего страшного, если вы никогда не добавляли Firebase в проект Flutter. Если вы не знакомы с консолью Firebase или вообще не знакомы с Firebase, сначала просмотрите следующие ссылки:

Что вы создадите

Эта лаборатория кода поможет вам создать поток аутентификации для приложения Flutter с использованием Firebase для аутентификации. Приложение будет иметь экран входа в систему, экран «Регистрация», экран восстановления пароля и экран профиля пользователя.

6604fc9157f2c6ae.pngeab9509a41074930.pngda49189a5838e0bb.pngb2ccfb3632b77878.png

Что вы узнаете

Эта кодовая лаборатория охватывает:

  • Добавление Firebase в приложение Flutter
  • Настройка консоли Firebase
  • Использование Firebase CLI для добавления Firebase в ваше приложение
  • Использование FlutterFire CLI для создания конфигурации Firebase в Dart
  • Добавление аутентификации Firebase в ваше приложение Flutter
  • Настройка аутентификации Firebase в консоли
  • Добавление входа в систему по электронной почте и паролю с помощью пакета firebase_ui_auth
  • Добавление регистрации пользователя с помощью пакета firebase_ui_auth
  • Добавление «Забыли пароль?» страница
  • Добавление входа в Google с помощью firebase_ui_auth
  • Настройка приложения для работы с несколькими поставщиками входа.
  • Добавление экрана профиля пользователя в ваше приложение с помощью пакета firebase_ui_auth

Эта кодовая лаборатория специально посвящена добавлению надежной системы аутентификации с использованием пакета firebase_ui_auth . Как вы увидите, все это приложение со всеми вышеперечисленными функциями может быть реализовано с помощью примерно 100 строк кода.

Что вам понадобится

  • Знание Flutter и установленного SDK.
  • Текстовый редактор (Flutter поддерживает JetBrains IDE, Android Studio и VS Code)
  • Браузер Google Chrome или другая предпочитаемая вами цель разработки для Flutter. (Некоторые команды терминала в этой лаборатории предполагают, что вы запускаете свое приложение в Chrome)

2. Создайте и настройте проект Firebase.

Первая задача, которую вам необходимо выполнить, — это создать проект Firebase в веб-консоли Firebase.

Создать проект Firebase

  1. Войдите в Firebase .
  2. В консоли Firebase нажмите «Добавить проект» (или «Создать проект» ) и введите имя вашего проекта Firebase (например, « FlutterFire-UI-Codelab »).

df42a5e3d9584b48.png

  1. Просмотрите параметры создания проекта. Примите условия Firebase, если будет предложено. Пропустите настройку Google Analytics, поскольку вы не будете использовать Analytics для этого приложения.

d1fcec48bf251eaa.png

Дополнительные сведения о проектах Firebase см. в разделе Общие сведения о проектах Firebase .

Приложение, которое вы создаете, использует проверку подлинности Firebase , чтобы позволить вашим пользователям входить в ваше приложение. Это также позволяет новым пользователям регистрироваться из приложения Flutter.

Аутентификацию Firebase необходимо включить с помощью консоли Firebase, и после ее включения требуется специальная настройка.

Включить вход по электронной почте для аутентификации Firebase

Чтобы разрешить пользователям входить в веб-приложение, сначала используйте метод входа по электронной почте и паролю . Позже вы добавите метод входа в Google .

  1. В консоли Firebase разверните меню «Сборка» на левой панели.
  2. Нажмите «Аутентификация» , затем нажмите кнопку «Начать» и выберите вкладку «Метод входа » (или нажмите здесь , чтобы перейти непосредственно на вкладку «Метод входа» ).
  3. Нажмите «Электронная почта/пароль» в списке «Поставщики входа» , установите переключатель « Включить» во включенное положение, а затем нажмите «Сохранить» . 58e3e3e23c2f16a4.png

3. Настройте приложение Flutter.

Прежде чем мы начнем, вам нужно будет скачать стартовый код и установить интерфейс командной строки Firebase.

Получить стартовый код

Клонируйте репозиторий GitHub из командной строки:

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

Альтернативно, если у вас установлен инструмент CLI GitHub :

gh repo clone flutter/codelabs flutter-codelabs

Пример кода следует клонировать в каталог flutter-codelabs на вашем компьютере, который содержит код для коллекции codelabs. Код этой лаборатории находится в подкаталоге flutter-codelabs/firebase-auth-flutterfire-ui .

Каталог flutter-codelabs/firebase-auth-flutterfire-ui содержит два проекта Flutter. Один называется complete , а другой — start . start каталог содержит незавершенный проект, и именно здесь вы проведете больше всего времени.

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

Если вы хотите пропустить вперед или посмотреть, как что-то должно выглядеть после завершения, посмотрите в каталоге с именем Complete для перекрестной ссылки.

Если вы хотите следовать кодовой лаборатории и добавлять код самостоятельно, вам следует начать с приложения Flutter по адресу flutter-codelabs/firebase-auth-flutterfire-ui/start и добавлять код в этот проект по всей кодовой лаборатории. Откройте или импортируйте этот каталог в предпочитаемую вами среду IDE.

Установите интерфейс командной строки Firebase

Интерфейс командной строки Firebase предоставляет инструменты для управления вашими проектами Firebase. Интерфейс командной строки необходим для интерфейса командной строки FlutterFire, который вы установите немного позже.

Существует множество способов установки CLI. Самый простой способ, если вы используете MacOS или Linux, — запустить эту команду со своего терминала:

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

После установки CLI вы должны пройти аутентификацию в Firebase.

  1. Войдите в Firebase, используя свою учетную запись Google, выполнив следующую команду:
firebase login
  1. Эта команда подключает ваш локальный компьютер к Firebase и предоставляет вам доступ к вашим проектам Firebase.
  1. Проверьте, правильно ли установлен интерфейс командной строки и имеет ли он доступ к вашей учетной записи, перечислив свои проекты Firebase. Выполните следующую команду:
firebase projects:list
  1. Отображаемый список должен быть таким же, как проекты Firebase, перечисленные в консоли Firebase . Вы должны увидеть хотя бы flutterfire-ui-codelab.

Установите интерфейс командной строки FlutterFire.

FlutterFire CLI — это инструмент, который помогает упростить процесс установки Firebase на всех поддерживаемых платформах в вашем приложении Flutter. Он построен на основе интерфейса командной строки Firebase.

Сначала установите CLI:

dart pub global activate flutterfire_cli

Убедитесь, что CLI установлен. Запустите следующую команду и убедитесь, что CLI выводит меню справки.

flutterfire -—help

Добавьте свой проект Firebase в свое приложение Flutter.

Настроить FlutterFire

Вы можете использовать FlutterFire для создания необходимого кода Dart для использования Firebase в вашем приложении Flutter.

flutterfire configure

При запуске этой команды вам будет предложено выбрать, какой проект Firebase вы хотите использовать и какие платформы вы хотите настроить.

На следующих снимках экрана показаны запросы, на которые вам нужно будет ответить.

  1. Выберите проект, который вы хотите использовать. В этом случае используйте flutterfire-ui-codelab 1359cdeb83204baa.png
  2. Выберите, какие платформы вы хотите использовать. В этой лаборатории кода описаны шаги по настройке аутентификации Firebase для Flutter для Интернета, iOS и Android, но вы можете настроить свой проект Firebase для использования всех параметров. 301c9534f594f472.png
  3. На этом снимке экрана показан результат завершения процесса. Если вы знакомы с Firebase, вы заметите, что вам не нужно создавать платформенные приложения (например, приложение Android) в консоли, и интерфейс командной строки FlutterFire сделал это за вас. 12199a85ade30459.png

Когда все будет готово, посмотрите приложение Flutter в текстовом редакторе. FlutterFire CLI сгенерировал новый файл с именем firebase_options.dart . Этот файл содержит класс FirebaseOptions, который имеет статические переменные, содержащие конфигурацию Firebase, необходимую для каждой платформы. Если вы выбрали все платформы при запуске flutterfire configure , вы увидите статические значения с именами web , android , ios и 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.appspot.com',
   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.appspot.com',
 );

 static const FirebaseOptions ios = FirebaseOptions(
   apiKey: 'AIzaSyBqLWsqFjYAdGyihKTahMRDQMo0N6NVjAs',
   appId: '1:963656261848:ios:d9e01cfe8b675dfcb237ad',
   messagingSenderId: '963656261848',
   projectId: 'flutterfire-ui-codelab',
   storageBucket: 'flutterfire-ui-codelab.appspot.com',
   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.appspot.com',
   iosClientId: '963656261848-v7r3vq1v6haupv0l1mdrmsf56ktnua60.apps.googleusercontent.com',
   iosBundleId: 'com.example.complete',
 );
}

Firebase использует слово «приложение» для обозначения конкретной сборки для конкретной платформы в проекте Firebase. Например, проект Firebase под названием FlutterFire-ui-codelab имеет несколько приложений: одно для Android, одно для iOS, одно для MacOS и одно для Интернета.

Метод DefaultFirebaseOptions.currentPlatform использует перечисление TargetPlatform , предоставляемое Flutter, для определения платформы, на которой работает ваше приложение, а затем возвращает значения конфигурации Firebase, необходимые для правильного приложения Firebase.

Добавьте пакеты Firebase в приложение Flutter

Последний шаг настройки — добавить соответствующие пакеты Firebase в ваш проект Flutter. В файле firebase_options.dart должны быть ошибки, поскольку он основан на еще не добавленных пакетах Firebase. В терминале убедитесь, что вы находитесь в корне проекта Flutter по адресу flutter-codelabs/firebase-emulator-suite/start . Затем выполните три следующие команды:

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

Это единственные пакеты, которые вам нужны на данный момент.

Инициализировать Firebase

Чтобы использовать добавленные пакеты и DefaultFirebaseOptions.currentPlatform, обновите код main функции в файле main.dart .

main.dart

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


 runApp(const MyApp());
}

Этот код делает две вещи.

  1. WidgetsFlutterBinding.ensureInitialized() сообщает Flutter не запускать код виджета приложения до полной загрузки платформы Flutter. Firebase использует собственные каналы платформы, для которых требуется запуск платформы.
  2. Firebase.initializeApp устанавливает соединение между вашим приложением Flutter и вашим проектом Firebase. DefaultFirebaseOptions.currentPlatform импортируется из созданного нами файла firebase_options.dart . Это статическое значение определяет, на какой платформе вы работаете, и передает соответствующие ключи Firebase.

4. Добавьте начальную страницу аутентификации Firebase UI.

Пользовательский интерфейс Firebase для Auth предоставляет виджеты, которые представляют целые экраны вашего приложения. Эти экраны обрабатывают различные процессы аутентификации в вашем приложении, такие как вход в систему, регистрация, забытый пароль, профиль пользователя и т. д. Для начала добавьте в свое приложение целевую страницу, которая действует как защита аутентификации для основного приложения.

Материал или приложение Купертино

Пользовательский интерфейс FlutterFire требует, чтобы ваше приложение было обернуто либо в MaterialApp, либо в CupertinoApp. В зависимости от вашего выбора пользовательский интерфейс автоматически отразит различия виджетов Material или Cupertino. Для этой лаборатории кода используйте MaterialApp , который уже добавлен в приложение в app.dart .

приложение.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(),
   );
 }
}

Проверьте состояние аутентификации

Прежде чем вы сможете отобразить экран входа в систему, вам необходимо определить, прошел ли пользователь проверку подлинности в данный момент. Самый распространенный способ проверить это — прослушать authStateChanges FirebaseAuth с помощью плагина Firebase Auth .

В приведенном выше примере кода MaterialApp создает виджет AuthGate в своем методе сборки. (Это пользовательский виджет, не предоставляемый пользовательским интерфейсом FlutterFire.)

Этот виджет необходимо обновить, чтобы включить поток authStateChanges .

API authStateChanges возвращает Stream либо с текущим пользователем (если он вошел в систему), либо с нулевым значением, если он не выполнен. Чтобы подписаться на это состояние в нашем приложении, вы можете использовать виджет Flutter StreamBuilder и передать ему поток.

StreamBuilder — это виджет, который строится на основе последнего снимка данных из потока , который вы ему передаете. Он автоматически перестраивается, когда Stream создает новый снимок.

Обновите код в 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 передается FirebaseAuth.instance.authStateChanged , вышеупомянутый поток, который вернет объект Firebase User , если пользователь прошел аутентификацию. (В противном случае он вернет null .)
  • Далее код использует snapshot.hasData , чтобы проверить, содержит ли значение из потока объект User .
  • Если его нет, он вернет виджет SignInScreen . В настоящее время этот экран ничего не делает. Это будет обновлено на следующем этапе.
  • В противном случае он возвращает HomeScreen , который является основной частью приложения, доступ к которой могут получить только прошедшие проверку подлинности пользователи.

SignInScreen — это виджет, который входит в пакет пользовательского интерфейса FlutterFire. Это будет в центре внимания следующего шага этой лаборатории кода. Когда вы запустите приложение на этом этапе, вы должны увидеть пустой экран входа в систему.

5. Экран входа в систему

Виджет SignInScreen , предоставляемый пользовательским интерфейсом FlutterFire, добавляет следующие функции:

  • Позволяет пользователям входить в систему
  • Если пользователи забыли свой пароль, они могут нажать «Забыли пароль?» и перейдете к форме для сброса пароля
  • Если пользователь еще не зарегистрирован, он может нажать «Зарегистрироваться» и перейти к другой форме, позволяющей ему зарегистрироваться.

Опять же, для этого требуется всего пара строк кода. Напомним код виджета 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();
      },
    );
  }
}

Виджет SignInScreen и его аргумент providers — единственный код, необходимый для получения всех вышеупомянутых функций. Теперь вы должны увидеть экран входа в систему с текстовыми вводами «электронная почта» и «пароль», а также кнопку «Войти».

Несмотря на функциональность, ему не хватает стиля. Виджет предоставляет параметры для настройки внешнего вида экрана входа. Например, вы можете добавить логотип своей компании.

Настройте экран входа в систему

заголовокBuilder

Используя аргумент SignInScreen.headerBuilder , вы можете добавить любые виджеты над формой входа. Обновите файл 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: [
             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();
     },
   );
 }
}

Аргумент headerBuilder требует функции типа HeaderBuilder, которая определена в пакете пользовательского интерфейса FlutterFire.

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

Поскольку это обратный вызов, он предоставляет значения, которые вы можете использовать, например BuildContext и BoxConstraints , и требует возврата виджета. Какой бы виджет вы ни вернули, он отображается в верхней части экрана. В этом примере новый код добавляет изображение в верхнюю часть экрана. Теперь ваше приложение должно выглядеть так.

73d7548d91bbd2ab.png

Построитель субтитров

Экран входа предоставляет три дополнительных параметра, которые позволяют настроить экран: subtitleBuilder , footerBuilder sideBuilder .

subtitleBuilder немного отличается тем, что аргументы обратного вызова включают действие типа AuthAction . AuthAction — это перечисление, которое можно использовать, чтобы определить, является ли экран, на котором находится пользователь, экраном «входа» или экраном «регистрации».

Обновите код в auth_gate.dart, чтобы использовать 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();
     },
   );
 }
}

Перезагрузите приложение, и оно должно выглядеть так

Аргумент footerBuilder такой же, как и аргумент subtitleBuilder. Он не предоставляет BoxConstraints или shrinkOffset , поскольку предназначен для текста, а не изображений. (Хотя вы можете добавить любой виджет, какой захотите.)

Добавьте нижний колонтитул на экран входа с помощью этого кода.

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

Сторонний строитель

Аргумент SignInScreen.sidebuilder принимает обратный вызов, и на этот раз аргументами этого обратного вызова являются BuildContext и double shrinkOffset . Виджет, возвращаемый SideBuilder, будет отображаться слева от формы входа и только на широких экранах. Фактически это означает, что виджет будет отображаться только в настольных и веб-приложениях.

Внутренний интерфейс FlutterFire использует точку останова, чтобы определить, следует ли отображать содержимое заголовка (на высоких экранах, например мобильных устройствах) или побочный контент (на широких экранах, настольных компьютерах или в Интернете). В частности, если ширина экрана превышает 800 пикселей, содержимое бокового компоновщика отображается, а содержимое заголовка — нет. Если ширина экрана меньше 800 пикселей, все наоборот.

Обновите код в auth_gate.dart, чтобы добавить виджеты 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();
     },
   );
 }
}

Теперь ваше приложение должно выглядеть так, когда вы увеличиваете ширину окна (если вы используете Flutter Web или MacOS).

8dc60b4e5d7dd2d0.png

Создать пользователя

На этом этапе весь код для этого экрана готов. Однако прежде чем вы сможете войти в систему, вам необходимо создать пользователя. Вы можете сделать это на экране «Регистрация» или создать пользователя в консоли Firebase.

Чтобы использовать консоль:

  1. Перейдите в таблицу «Пользователи» в консоли Firebase.
  2. кликните сюда
  3. Выберите «flutterfire-ui-codelab» (или другой проект, если вы использовали другое имя). Вы увидите эту таблицу:

f038fd9a58ed60d9.png

  1. Нажмите кнопку «Добавить пользователя».

2d78390d4c5dbbfa.png

  1. Введите адрес электронной почты и пароль для нового пользователя. Это могут быть поддельные адрес электронной почты и пароль, как я ввел на изображении ниже. Это будет работать, но функция «Забыли пароль» не будет работать, если вы используете поддельный адрес электронной почты.

62ba0feb33d54add.png

  1. Нажмите «Добавить пользователя»

32b236b3ef94d4c7.png

Теперь вы можете вернуться в свое приложение Flutter и войти в систему через страницу входа. Ваше приложение должно выглядеть так:

dd43d260537f3b1a.png

6. Экран профиля

Пользовательский интерфейс FlutterFire также предоставляет виджет ProfileScreen , который, опять же, предоставляет вам множество функций в нескольких строках кода.

Добавить виджет 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) => const ProfileScreen(),
                ),
              );
            },
          )
        ],
        automaticallyImplyLeading: false,
      ),
      body: Center(
        child: Column(
          children: [
            Image.asset('dash.png'),
            Text(
              'Welcome!',
              style: Theme.of(context).textTheme.displaySmall,
            ),
            const SignOutButton(),
          ],
        ),
      ),
    );
  }
}

Новым примечательным кодом является обратный вызов, передаваемый IconButton.isPressed method. При нажатии этой IconButton ваше приложение создает новый анонимный маршрут и переходит к нему. Этот маршрут будет отображать виджет ProfileScreen , который возвращается из обратного вызова MaterialPageRoute.builder .

Перезагрузите приложение и нажмите значок в правом верхнем углу (на панели приложения), и откроется подобная страница:

36487fc4ab4f26a7.png

Это стандартный пользовательский интерфейс, предоставляемый страницей пользовательского интерфейса FlutterFire. Все кнопки и текстовые поля подключены к Firebase Auth и работают «из коробки». Например, вы можете ввести имя в текстовое поле «Имя», и пользовательский интерфейс FlutterFire вызовет метод FirebaseAuth.instance.currentUser?.updateDisplayName , который сохранит это имя в Firebase.

Выписка

Прямо сейчас, если вы нажмете кнопку «Выйти», приложение не изменится. Он выведет вас из системы, но вы не вернетесь к виджету AuthGate. Для реализации этого используйте параметр ProfileScreen.actions.

Сначала обновите код в 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(),
          ],
        ),
      ),
    );
  }
}

Теперь, когда вы создаете экземпляр ProfileScreen , вы также передаете ему список действий в аргумент ProfileScreen.actions . Эти действия относятся к типу FlutterFireUiAction . Существует много разных классов, которые являются подтипами FlutterFireUiAction , и обычно вы используете их, чтобы сообщить своему приложению, что оно должно реагировать на различные изменения состояния аутентификации. SignedOutAction вызывает функцию обратного вызова, которую вы передаете ей, когда состояние аутентификации Firebase меняется на значение currentUser, равное нулю.

Добавив обратный вызов, который вызывает Navigator.of(context).pop() при срабатывании SignedOutAction, приложение перейдет на предыдущую страницу. В этом примере приложения существует только один постоянный маршрут, на котором отображается страница входа, если пользователь не выполнил вход, и домашняя страница, если пользователь есть. Поскольку это происходит, когда пользователь выходит из системы, приложение отображает страницу входа.

Настройте страницу профиля

Как и страница входа в систему, страница профиля настраивается. Во-первых, наша текущая страница не имеет возможности вернуться на домашнюю страницу, как только пользователь окажется на странице профиля. Исправьте это, предоставив виджету ProfileScreen AppBar.

дом.дарт

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

Аргумент ProfileScreen.appBar принимает виджет AppBar из пакета Flutter Material, поэтому его можно рассматривать как любой другой AppBar который вы создали и передали в Scaffold . В этом примере сохраняется стандартная функция автоматического добавления кнопки «Назад», и на экране теперь есть заголовок.

Добавьте детей на экран профиля

Виджет ProfileScreen также имеет необязательный аргумент с именем Children. Этот аргумент принимает список виджетов, и эти виджеты будут размещены вертикально внутри виджета Column, который уже используется внутри для создания ProfileScreen. Этот виджет Column в методе сборки 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();
                      })
                    ],
                    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(),
          ],
        ),
      ),
    );
  }
}

Перезагрузите приложение, и вы увидите это на экране:

ebe5792b765dbf87.png

7. Мультиплатформенный вход в Google Auth.

Пользовательский интерфейс FlutterFire также предоставляет виджеты и функции для аутентификации у сторонних поставщиков, таких как Google, Twitter, Facebook, Apple и Github.

Для интеграции с аутентификацией Google установите официальный плагин firebase_ui_oauth_google и его зависимости, которые будут обрабатывать собственный поток аутентификации. В терминале перейдите в корень вашего проекта flutter и введите следующую команду:

flutter pub add google_sign_in
flutter pub add firebase_ui_oauth_google

Включить поставщика услуг входа в Google

Затем включите провайдера Google в консоли Firebase :

  1. Перейдите к экрану «Поставщики входа в систему аутентификации» в консоли.
  2. Нажмите «Добавить нового провайдера». 8286fb28be94bf30.png
  3. Выберите «Google». c4e28e6f4974be7f.png
  4. Переключите переключатель с надписью «Включить» и нажмите «Сохранить». e74ff86990763826.png
  5. Если появится модальное окно с информацией о загрузке файлов конфигурации, нажмите «Готово».
  6. Убедитесь, что поставщик услуг входа в систему Google добавлен. 5329ce0543c90d95.png

Добавить кнопку входа в Google

Включив вход в Google, добавьте виджет, необходимый для отображения стилизованной кнопки входа в Google, на страницу входа. Перейдите к файлу 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: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();
     },
   );
 }
}

Единственный новый код здесь — добавление GoogleProvider(clientId: "YOUR_WEBCLIENT_ID") в конфигурацию виджета SignInScreen.

После этого перезагрузите приложение, и вы увидите кнопку входа в Google.

aca71a46a011bfb5.png

Настроить кнопку входа

Кнопка не работает без дополнительной настройки. Если вы разрабатываете с помощью Flutter Web, это единственный шаг, который вам нужно добавить, чтобы это заработало. Другие платформы требуют дополнительных шагов, которые обсуждаются немного позже.

  1. Перейдите на страницу поставщиков аутентификации в консоли Firebase .
  2. Нажмите на поставщика Google. 9b3a325c5eca6e49.png
  3. Нажмите на панель расширения «Конфигурация Web SDK».
  4. Скопируйте значение из «Идентификатор веб-клиента». 711a79f0d931c60f.png
  5. Вернитесь в текстовый редактор и обновите экземпляр GoogleProvider в файле auth_gate.dart , передав этот идентификатор в именованный параметр clientId .
GoogleProvider(
   clientId: "YOUR_WEBCLIENT_ID"
)

После ввода идентификатора веб-клиента перезагрузите приложение. Когда вы нажмете кнопку «Войти через Google», появится новое окно (если вы используете Интернет), которое проведет вас через процесс входа в Google. Изначально это выглядит так:

14e73e3c9de704bb.png

Настройка iOS

Чтобы это работало на iOS, необходимо выполнить дополнительный процесс настройки.

  1. Перейдите на экран «Настройки проекта» в консоли Firebase . Появится карточка со списком ваших приложений Firebase, которая выглядит следующим образом: fefa674acbf213cc.png
  2. Нажмите на iOS. Обратите внимание, что имя вашего приложения будет отличаться от моего. Там, где у меня написано «завершено», у вас будет написано «начать», если вы использовали проект flutter-codelabs/firebase-auth-flutterfire-ui/start для выполнения этой кодовой лаборатории.
  3. Нажмите кнопку с надписью «GoogleServices-Info.plist», чтобы загрузить необходимый файл конфигурации. f89b3192871dfbe3.png
  4. Перетащите загруженный файл в каталог с именем . /ios/Runner в вашем проекте Flutter.
  5. Откройте Xcode, выполнив следующую команду терминала из корня вашего проекта:

откройте ios/Runner.xcworkspace

  1. Щелкните правой кнопкой мыши каталог Runner и выберите «Добавить файлы в Runner». 858986063a4c5201.png
  2. Выберите GoogleService-Info.plist в файловом менеджере.
  3. Вернувшись в текстовый редактор (это не Xcode), добавьте приведенные ниже атрибуты CFBundleURLTypes в файл [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 -->

Если ваше приложение Flutter уже работает в iOS, вам необходимо полностью закрыть его, а затем перезапустить приложение. В противном случае запустите приложение в iOS.

8. Поздравляем!

Вы завершили создание пользовательского интерфейса Firebase Auth для лаборатории кода Flutter. Вы можете найти готовый код для этой Codelab в «полном» каталоге на github: Flutter Codelabs.

Что мы рассмотрели

  • Настройка приложения Flutter для использования Firebase
  • Настройка проекта Firebase в консоли Firebase
  • Интерфейс командной строки FlutterFire
  • Интерфейс командной строки Firebase
  • Использование аутентификации Firebase
  • Использование пользовательского интерфейса FlutterFire для простой обработки аутентификации Firebase в вашем приложении Flutter

Следующие шаги

Узнать больше

Спарки здесь, чтобы отпраздновать это событие вместе с вами!

2a0ad195769368b1.gif