Thêm quy trình xác thực người dùng vào ứng dụng Flutter bằng FirebaseUI

1. Trước khi bắt đầu

Trong lớp học lập trình này, bạn sẽ tìm hiểu cách thêm tính năng Xác thực Firebase vào ứng dụng Flutter bằng gói giao diện người dùng FlutterFire. Với gói này, bạn sẽ thêm cả phương thức xác thực email/mật khẩu và phương thức xác thực Đăng nhập bằng Google vào ứng dụng Flutter. Bạn cũng sẽ tìm hiểu cách thiết lập dự án Firebase và sử dụng FlutterFire CLI để khởi chạy Firebase trong ứng dụng Flutter.

Điều kiện tiên quyết

Lớp học lập trình này giả định rằng bạn đã có một số kinh nghiệm về Flutter. Nếu không, bạn nên tìm hiểu các kiến thức cơ bản trước. Các đường liên kết sau đây sẽ hữu ích:

Bạn cũng nên có một số kinh nghiệm về Firebase, nhưng không sao nếu bạn chưa bao giờ thêm Firebase vào dự án Flutter. Nếu bạn chưa quen với bảng điều khiển Firebase hoặc hoàn toàn mới sử dụng Firebase, trước tiên, hãy xem các đường liên kết sau:

Nội dung bạn sẽ tạo

Lớp học lập trình này hướng dẫn bạn xây dựng quy trình xác thực cho ứng dụng Flutter bằng Firebase để Xác thực. Ứng dụng sẽ có màn hình đăng nhập, màn hình "Đăng ký", màn hình khôi phục mật khẩu và màn hình hồ sơ người dùng.

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

Kiến thức bạn sẽ học được

Lớp học lập trình này bao gồm:

  • Thêm Firebase vào ứng dụng Flutter
  • Thiết lập Bảng điều khiển của Firebase
  • Sử dụng Firebase CLI để thêm Firebase vào ứng dụng của bạn
  • Sử dụng FlutterFire CLI để tạo cấu hình Firebase trong Dart
  • Thêm phương thức xác thực Firebase vào ứng dụng Flutter
  • Thiết lập tính năng Xác thực Firebase trong bảng điều khiển
  • Thêm tính năng đăng nhập bằng Email và mật khẩu bằng gói firebase_ui_auth
  • Thêm hoạt động đăng ký người dùng với gói firebase_ui_auth
  • Thêm trang "Bạn quên mật khẩu?"
  • Đang thêm tính năng Đăng nhập bằng Google bằng firebase_ui_auth
  • Định cấu hình ứng dụng của bạn để làm việc với nhiều nhà cung cấp dịch vụ đăng nhập.
  • Thêm màn hình hồ sơ người dùng vào ứng dụng bằng gói firebase_ui_auth

Lớp học lập trình này đặc biệt quan tâm đến việc thêm một hệ thống Xác thực mạnh mẽ bằng gói firebase_ui_auth. Như bạn sẽ thấy, toàn bộ ứng dụng này, với tất cả các tính năng ở trên, có thể được triển khai bằng khoảng 100 dòng mã.

Bạn cần có

  • Có kiến thức về Flutter và đã cài đặt SDK
  • Trình chỉnh sửa văn bản (Flutter hỗ trợ IDE JetBrains, Android Studio và VS)
  • Trình duyệt Google Chrome hoặc mục tiêu phát triển khác mà bạn ưu tiên cho Flutter. (Một số lệnh dòng lệnh trong lớp học lập trình này sẽ giả định rằng bạn đang chạy ứng dụng trên Chrome)

2. Tạo và thiết lập dự án Firebase

Việc đầu tiên bạn cần hoàn thành là tạo một dự án Firebase trong bảng điều khiển web của Firebase.

Tạo một dự án Firebase

  1. Đăng nhập vào Firebase.
  2. Trong bảng điều khiển của Firebase, hãy nhấp vào Thêm dự án (hoặc Tạo dự án) rồi nhập tên cho dự án Firebase của bạn (ví dụ: "FlutterFire-UI-Codelab").

df42a5e3d9584b48.png

  1. Nhấp vào các tuỳ chọn tạo dự án. Chấp nhận các điều khoản của Firebase nếu được nhắc. Bỏ qua bước thiết lập Google Analytics vì bạn sẽ không sử dụng Analytics cho ứng dụng này.

d1fcec48bf251eaa.png

Để tìm hiểu thêm về các dự án Firebase, hãy xem bài viết Tìm hiểu về các dự án Firebase.

Bật tính năng đăng nhập bằng email cho tính năng Xác thực Firebase

Ứng dụng bạn đang tạo sử dụng tính năng Xác thực Firebase để cho phép người dùng đăng nhập vào ứng dụng của bạn. Cơ chế này cũng cho phép người dùng mới đăng ký qua ứng dụng Flutter.

Bạn cần bật tính năng Xác thực Firebase bằng Bảng điều khiển của Firebase và cần cấu hình đặc biệt sau khi bật.

Để cho phép người dùng đăng nhập vào ứng dụng web, trước tiên, bạn sẽ sử dụng phương thức đăng nhập Email/Mật khẩu. Sau đó, bạn sẽ thêm phương thức Đăng nhập bằng Google.

  1. Trong bảng điều khiển của Firebase, hãy mở rộng trình đơn Build (Tạo) trong bảng điều khiển bên trái.
  2. Nhấp vào Xác thực, sau đó nhấp vào nút Bắt đầu, sau đó nhấp vào thẻ Phương thức đăng nhập (hoặc nhấp vào đây để chuyển thẳng đến thẻ Phương thức đăng nhập).
  3. Nhấp vào Email/Mật khẩu trong danh sách Nhà cung cấp dịch vụ đăng nhập, đặt nút chuyển Bật sang vị trí bật rồi nhấp vào Lưu. 58e3e3e23c2f16a4.png

3. Thiết lập ứng dụng Flutter

Bạn cần tải mã khởi động xuống và cài đặt Giao diện dòng lệnh (CLI) của Firebase trước khi bắt đầu.

Lấy đoạn mã khởi đầu

Sao chép kho lưu trữ GitHub từ dòng lệnh:

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

Ngoài ra, nếu bạn đã cài đặt công cụ dòng lệnh của GitHub:

gh repo clone flutter/codelabs flutter-codelabs

Bạn nên nhân bản mã mẫu vào thư mục flutter-codelabs trên máy của mình. Thư mục này chứa mã cho một bộ sưu tập các lớp học lập trình. Mã dành cho lớp học lập trình này nằm trong thư mục con flutter-codelabs/firebase-auth-flutterfire-ui.

Thư mục flutter-codelabs/firebase-auth-flutterfire-ui chứa hai dự án Flutter. Một thành phần có tên là complete và thành phần còn lại tên là start. Thư mục start chứa một dự án chưa hoàn chỉnh và đây là nơi bạn sẽ dành nhiều thời gian nhất.

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

Nếu bạn muốn chuyển tiếp hoặc xem nội dung sẽ trông như thế nào khi hoàn tất, hãy tìm trong thư mục có tên complete để tham chiếu chéo.

Nếu muốn làm theo lớp học lập trình này và tự thêm mã, bạn nên bắt đầu bằng ứng dụng Flutter tại flutter-codelabs/firebase-auth-flutterfire-ui/start và thêm mã vào dự án đó trong suốt lớp học lập trình này. Mở hoặc nhập thư mục đó vào IDE mà bạn muốn dùng.

Cài đặt Firebase CLI

Firebase CLI cung cấp các công cụ để quản lý dự án Firebase của bạn. Bạn cần phải có CLI cho FlutterFire CLI, mà bạn sẽ cài đặt sau giây lát.

Có nhiều cách để cài đặt CLI. Cách đơn giản nhất (nếu bạn đang sử dụng MacOS hoặc Linux) là chạy lệnh này từ thiết bị đầu cuối:

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

Sau khi cài đặt CLI, bạn phải xác thực bằng Firebase.

  1. Đăng nhập vào Firebase bằng Tài khoản Google của bạn bằng cách chạy lệnh sau:
firebase login
  1. Lệnh này kết nối máy cục bộ của bạn với Firebase và cấp cho bạn quyền truy cập vào các dự án Firebase.
  1. Kiểm tra để đảm bảo CLI đã được cài đặt đúng cách và có quyền truy cập vào tài khoản của bạn bằng cách liệt kê các dự án Firebase của bạn. Chạy lệnh sau:
firebase projects:list
  1. Danh sách hiển thị phải giống với các dự án Firebase được liệt kê trong bảng điều khiển Firebase. Bạn sẽ thấy ít nhất flutterfire-ui-codelab.

Cài đặt FlutterFire CLI

FlutterFire CLI là một công cụ giúp đơn giản hoá quy trình cài đặt Firebase trên tất cả các nền tảng được hỗ trợ trong ứng dụng Flutter. Công cụ này được xây dựng dựa trên Firebase CLI.

Trước tiên, hãy cài đặt CLI:

dart pub global activate flutterfire_cli

Đảm bảo bạn đã cài đặt CLI. Chạy lệnh sau và đảm bảo rằng CLI xuất ra trình đơn trợ giúp.

flutterfire -—help

Thêm dự án Firebase vào ứng dụng Flutter

Định cấu hình FlutterFire

Bạn có thể sử dụng FlutterFire để tạo mã Dart cần thiết nhằm sử dụng Firebase trong ứng dụng Flutter của mình.

flutterfire configure

Khi lệnh này chạy, bạn sẽ được nhắc chọn dự án Firebase mà bạn muốn sử dụng cũng như nền tảng mà bạn muốn thiết lập.

Các ảnh chụp màn hình sau đây cho thấy những câu lệnh bạn cần phải trả lời.

  1. Chọn dự án mà bạn muốn sử dụng. Trong trường hợp này, hãy sử dụng flutterfire-ui-codelab 1359cdeb83204baa.png.
  2. Chọn nền tảng bạn muốn sử dụng. Trong lớp học lập trình này, bạn sẽ thấy các bước định cấu hình tính năng Xác thực Firebase cho Flutter dành cho web, iOS và Android. Tuy nhiên, bạn có thể thiết lập dự án Firebase của mình để sử dụng tất cả các lựa chọn. 301c9534f594f472.pngS
  3. Ảnh chụp màn hình này cho thấy kết quả ở cuối quy trình. Nếu đã quen thuộc với Firebase, bạn sẽ nhận thấy rằng bạn không cần phải tạo các ứng dụng nền tảng (ví dụ: ứng dụng Android) trong bảng điều khiển, và FlutterFire CLI đã làm việc này cho bạn. 12199a85ade30459.png

Khi hoàn tất, hãy xem ứng dụng Flutter trong trình soạn thảo văn bản. FlutterFire CLI đã tạo một tệp mới có tên là firebase_options.dart. Tệp này chứa một lớp có tên là FirebaseOptions, lớp này có các biến tĩnh chứa cấu hình Firebase cần thiết cho từng nền tảng. Nếu đã chọn tất cả nền tảng khi chạy flutterfire configure, bạn sẽ thấy các giá trị tĩnh có tên web, android, iosmacos.

firebase_options.dart

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

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

   throw UnsupportedError(
     'DefaultFirebaseOptions are not supported for this platform.',
   );
 }

 static const FirebaseOptions web = FirebaseOptions(
   apiKey: 'AIzaSyCqFjCV_9CZmYeIvcK9FVy4drmKUlSaIWY',
   appId: '1:963656261848:web:7219f7fca5fc70afb237ad',
   messagingSenderId: '963656261848',
   projectId: 'flutterfire-ui-codelab',
   authDomain: 'flutterfire-ui-codelab.firebaseapp.com',
   storageBucket: 'flutterfire-ui-codelab.firebasestorage.app',
   measurementId: 'G-DGF0CP099H',
 );

 static const FirebaseOptions android = FirebaseOptions(
   apiKey: 'AIzaSyDconZaCQpkxIJ5KQBF-3tEU0rxYsLkIe8',
   appId: '1:963656261848:android:c939ccc86ab2dcdbb237ad',
   messagingSenderId: '963656261848',
   projectId: 'flutterfire-ui-codelab',
   storageBucket: 'flutterfire-ui-codelab.firebasestorage.app',
 );

 static const FirebaseOptions ios = FirebaseOptions(
   apiKey: 'AIzaSyBqLWsqFjYAdGyihKTahMRDQMo0N6NVjAs',
   appId: '1:963656261848:ios:d9e01cfe8b675dfcb237ad',
   messagingSenderId: '963656261848',
   projectId: 'flutterfire-ui-codelab',
   storageBucket: 'flutterfire-ui-codelab.firebasestorage.app',
   iosClientId: '963656261848-v7r3vq1v6haupv0l1mdrmsf56ktnua60.apps.googleusercontent.com',
   iosBundleId: 'com.example.complete',
 );

 static const FirebaseOptions macos = FirebaseOptions(
   apiKey: 'AIzaSyBqLWsqFjYAdGyihKTahMRDQMo0N6NVjAs',
   appId: '1:963656261848:ios:d9e01cfe8b675dfcb237ad',
   messagingSenderId: '963656261848',
   projectId: 'flutterfire-ui-codelab',
   storageBucket: 'flutterfire-ui-codelab.firebasestorage.app',
   iosClientId: '963656261848-v7r3vq1v6haupv0l1mdrmsf56ktnua60.apps.googleusercontent.com',
   iosBundleId: 'com.example.complete',
 );
}

Firebase sử dụng từ ứng dụng để chỉ một bản dựng cụ thể cho một nền tảng cụ thể trong dự án Firebase. Ví dụ: dự án Firebase có tên FlutterFire-ui-codelab có nhiều ứng dụng: một ứng dụng dành cho Android, một ứng dụng dành cho iOS, một ứng dụng dành cho MacOS và một ứng dụng dành cho Web.

Phương thức DefaultFirebaseOptions.currentPlatform sử dụng enum TargetPlatform mà Flutter hiển thị để phát hiện nền tảng mà ứng dụng của bạn đang chạy, sau đó trả về các giá trị cấu hình Firebase cần thiết cho đúng ứng dụng Firebase.

Thêm các gói Firebase vào ứng dụng Flutter

Bước thiết lập cuối cùng là thêm các gói Firebase có liên quan vào dự án Flutter. Tệp firebase_options.dart sẽ có lỗi, vì tệp này dựa trên các gói Firebase chưa được thêm vào. Trong cửa sổ dòng lệnh, hãy đảm bảo bạn đang ở thư mục gốc của dự án Flutter tại flutter-codelabs/firebase-emulator-suite/start. Sau đó, hãy chạy 3 lệnh sau:

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

Đây là các gói duy nhất bạn cần vào thời điểm này.

Khởi động Firebase

Để sử dụng các gói được thêm vào, DefaultFirebaseOptions.currentPlatform, sẽ cập nhật mã trong hàm main trong tệp main.dart.

main.dart

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


 runApp(const MyApp());
}

Mã này thực hiện 2 việc.

  1. WidgetsFlutterBinding.ensureInitialized() yêu cầu Flutter không bắt đầu chạy mã tiện ích ứng dụng cho đến khi khung Flutter khởi động xong. Firebase sử dụng các kênh nền tảng gốc nên yêu cầu phải chạy khung.
  2. Firebase.initializeApp thiết lập kết nối giữa ứng dụng Flutter và dự án Firebase. DefaultFirebaseOptions.currentPlatform được nhập từ tệp firebase_options.dart đã tạo. Giá trị tĩnh này phát hiện nền tảng bạn đang chạy và truyền vào các khoá Firebase tương ứng.

4. Thêm trang xác thực giao diện người dùng Firebase ban đầu

Giao diện người dùng Firebase để xác thực cung cấp các tiện ích đại diện cho toàn bộ màn hình trong ứng dụng của bạn. Những màn hình này sẽ xử lý nhiều quy trình xác thực trong toàn bộ ứng dụng, chẳng hạn như Đăng nhập, Đăng ký, Quên mật khẩu, Hồ sơ người dùng, v.v. Để bắt đầu, hãy thêm trang đích vào ứng dụng của bạn hoạt động như một biện pháp bảo vệ xác thực cho ứng dụng chính.

Material hoặc ứng dụng Cupertino

Giao diện người dùng FlutterFire yêu cầu ứng dụng của bạn phải được gói bằng MaterialApp hoặc CupertinoApp. Tuỳ thuộc vào lựa chọn của bạn, giao diện người dùng sẽ tự động phản ánh sự khác biệt giữa các tiện ích Material hoặc Cupertino. Đối với lớp học lập trình này, hãy sử dụng MaterialApp (đã được thêm vào ứng dụng trong app.dart).

app.dart

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

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

Kiểm tra trạng thái xác thực

Trước khi có thể hiển thị màn hình đăng nhập, bạn cần xác định xem người dùng hiện đã được xác thực hay chưa. Cách phổ biến nhất để kiểm tra điều này là nghe authStateChanges của FirebaseAuth bằng trình bổ trợ Xác thực Firebase.

Trong mã mẫu ở trên, MaterialApp đang tạo một tiện ích AuthGate trong phương thức xây dựng của nó. (Đây là một tiện ích tuỳ chỉnh, không phải do giao diện người dùng FlutterFire cung cấp.)

Bạn cần cập nhật tiện ích đó để thêm luồng authStateChanges.

API authStateChanges trả về một Stream với người dùng hiện tại (nếu họ đã đăng nhập) hoặc giá trị rỗng nếu họ chưa đăng nhập. Để đăng ký trạng thái này trong ứng dụng, bạn có thể sử dụng tiện ích StreamBuilder của Flutter và truyền luồng đến tiện ích đó.

StreamBuilder là một tiện ích tự tạo dựa trên bản tổng quan nhanh mới nhất về dữ liệu từ một Luồng mà bạn truyền vào. Nó tự động tạo lại khi Luồng tạo ra một bản tổng quan nhanh mới.

Cập nhật mã trong 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 đang được truyền FirebaseAuth.instance.authStateChanged (luồng nêu trên). Luồng này sẽ trả về đối tượng Firebase User nếu người dùng đã xác thực. (Nếu không, hàm này sẽ trả về null.)
  • Tiếp theo, mã này sẽ sử dụng snapshot.hasData để kiểm tra xem giá trị từ luồng có chứa đối tượng User hay không.
  • Nếu không có, phương thức này sẽ trả về một tiện ích SignInScreen. Hiện tại, màn hình đó sẽ không làm gì cả. Thông tin này sẽ được cập nhật trong bước tiếp theo.
  • Nếu không, phương thức này sẽ trả về một HomeScreen, đây là phần chính của ứng dụng mà chỉ những người dùng đã xác thực mới có thể truy cập.

SignInScreen là một tiện ích đến từ gói giao diện người dùng FlutterFire. Đây sẽ là trọng tâm của bước tiếp theo trong lớp học lập trình này. Khi chạy ứng dụng tại thời điểm này, bạn sẽ thấy một màn hình đăng nhập trống.

5. Màn hình đăng nhập

Tiện ích SignInScreen do giao diện người dùng FlutterFire cung cấp, bổ sung chức năng sau:

  • Cho phép người dùng đăng nhập
  • Nếu quên mật khẩu, người dùng có thể nhấn vào "Bạn quên mật khẩu?" để được chuyển đến một biểu mẫu đặt lại mật khẩu
  • Nếu chưa đăng ký, người dùng có thể nhấn vào "Đăng ký" và được đưa đến một biểu mẫu khác cho phép họ đăng ký.

Xin nhắc lại, thao tác này chỉ yêu cầu một vài dòng mã. Gọi lại mã trong tiện ích 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();
      },
    );
  }
}

Tiện ích SignInScreen và đối số providers của tiện ích này là mã duy nhất cần thiết để nhận tất cả chức năng nêu trên. Bây giờ, bạn sẽ thấy một màn hình đăng nhập có các trường nhập văn bản "email" và "mật khẩu", cũng như nút "Đăng nhập".

Mặc dù có chức năng nhưng ứng dụng này thiếu kiểu. Tiện ích này hiển thị các tham số để tuỳ chỉnh giao diện của màn hình đăng nhập. Ví dụ: bạn có thể muốn thêm biểu trưng của công ty.

Tuỳ chỉnh màn hình đăng nhập

công cụ tạo tiêu đề

Bằng cách sử dụng đối số SignInScreen.headerBuilder, bạn có thể thêm bất kỳ tiện ích nào bạn muốn phía trên biểu mẫu đăng nhập. Tiện ích này chỉ hiển thị trên màn hình hẹp, chẳng hạn như thiết bị di động. Trên màn hình rộng, bạn có thể sử dụng SignInScreen.sideBuilder. Chúng ta sẽ thảo luận về SignInScreen.sideBuilder ở phần sau của lớp học lập trình này.

Cập nhật tệp auth_gate.dart bằng mã sau:

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

Đối số headerBuilder yêu cầu một hàm thuộc loại HeaderBuilder, được xác định trong gói giao diện người dùng FlutterFire.

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

Vì là lệnh gọi lại nên phương thức này hiển thị các giá trị mà bạn có thể sử dụng, chẳng hạn như BuildContextBoxConstraints, đồng thời yêu cầu bạn trả về một tiện ích. Bất kỳ tiện ích nào bạn trả về sẽ xuất hiện ở đầu màn hình. Trong ví dụ này, mã mới sẽ thêm một hình ảnh vào đầu màn hình. Bây giờ, ứng dụng của bạn sẽ có dạng như sau.

73d7548d91bbd2ab.png.

Trình tạo phụ đề

Màn hình đăng nhập hiển thị 3 tham số bổ sung cho phép bạn tuỳ chỉnh màn hình: subtitleBuilder, footerBuildersideBuilder.

subtitleBuilder hơi khác ở chỗ các đối số gọi lại bao gồm một hành động thuộc loại AuthAction. AuthAction là một giá trị enum mà bạn có thể sử dụng để phát hiện xem màn hình mà người dùng đang sử dụng là màn hình "đăng nhập" hay màn hình "đăng ký".

Cập nhật mã trong auth_gate.dart để sử dụng 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();
     },
   );
 }
}

Tải lại ứng dụng và ứng dụng sẽ có dạng như sau

Đối sốfooterBuilder giống với SubBuilder. Phương thức này không hiển thị BoxConstraints hoặc shrinkOffset vì phương thức này dành cho văn bản thay vì hình ảnh. (Mặc dù bạn có thể thêm bất kỳ tiện ích nào bạn muốn.)

Thêm chân trang vào màn hình đăng nhập bằng mã này.

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

Trình tạo phụ

Đối sốSignInScreen.sidebuilder chấp nhận lệnh gọi lại và lần này các đối số cho lệnh gọi lại đó là BuildContextdouble shrinkOffset. Tiện ích mà sideBuilder trả về sẽ hiển thị ở bên trái của biểu mẫu đăng nhập và chỉ trên màn hình rộng. Điều đó có nghĩa là tiện ích này sẽ chỉ hiển thị trên máy tính và ứng dụng web.

Trong nội bộ, giao diện người dùng FlutterFire sử dụng một điểm ngắt để xác định xem nội dung tiêu đề có nên hiển thị (trên màn hình cao, chẳng hạn như thiết bị di động) hay nội dung bên phải có nên hiển thị (trên màn hình rộng, máy tính hoặc web) hay không. Cụ thể, nếu màn hình có chiều rộng hơn 800 pixel, thì nội dung của trình tạo bên sẽ hiển thị và nội dung của tiêu đề sẽ không hiển thị. Nếu màn hình có chiều rộng dưới 800 pixel, thì điều ngược lại sẽ xảy ra.

Cập nhật mã trong auth_gate.dart để thêm các tiện ích 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();
     },
   );
 }
}

Lúc này, ứng dụng sẽ có dạng như sau khi bạn mở rộng chiều rộng của cửa sổ (nếu bạn đang sử dụng Flutter web hoặc MacOS).

8dc60b4e5d7dd2d0.png

Tạo người dùng

Lúc này, tất cả mã cho màn hình này đã hoàn tất. Tuy nhiên, trước khi có thể đăng nhập, bạn cần tạo Người dùng. Bạn có thể thực hiện việc này bằng màn hình "Đăng ký" hoặc tạo người dùng trong bảng điều khiển Firebase.

Cách sử dụng bảng điều khiển:

  1. Chuyển đến bảng "Người dùng" trong bảng điều khiển của Firebase.
  2. Nhấp vào đây
  3. Chọn "flutterfire-ui-codelab" (hoặc một dự án khác nếu bạn đã sử dụng tên khác). Bạn sẽ thấy bảng sau:

f038fd9a58ed60d9.png

  1. Nhấp vào nút "Thêm người dùng".

2d78390d4c5dbbfa.png

  1. Nhập địa chỉ email và mật khẩu cho người dùng mới. Đây có thể là email và mật khẩu giả mạo, như tôi đã nhập trong hình ảnh bên dưới. Thao tác đó sẽ hiệu quả, nhưng tính năng "Quên mật khẩu" sẽ không hoạt động nếu bạn sử dụng địa chỉ email giả mạo.

62ba0feb33d54add.png

  1. Nhấp vào "Thêm người dùng"

32b236b3ef94d4c7.png

Giờ đây, bạn có thể quay lại ứng dụng Flutter của mình và đăng nhập người dùng qua trang đăng nhập. Ứng dụng của bạn sẽ có dạng như sau:

dd43d260537f3b1a.png

6. Màn hình hồ sơ

Giao diện người dùng FlutterFire cũng cung cấp một tiện ích ProfileScreen, một lần nữa, cung cấp cho bạn nhiều chức năng trong một vài dòng mã.

Thêm tiện ích ProfileScreen

Chuyển đến tệp home.dart trong trình chỉnh sửa văn bản. Cập nhật bằng mã sau:

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

Đoạn mã lưu ý mới là lệnh gọi lại được truyền đến IconButton.isPressed method.. Khi bạn nhấn IconButton, ứng dụng của bạn sẽ tạo một tuyến ẩn danh mới và điều hướng đến đó. Tuyến đó sẽ hiển thị tiện ích ProfileScreen được trả về từ lệnh gọi lại MaterialPageRoute.builder.

Tải lại ứng dụng và nhấn biểu tượng ở trên cùng bên phải (trong thanh ứng dụng), sau đó ứng dụng sẽ hiển thị một trang như sau:

36487fc4ab4f26a7.png

Đây là giao diện người dùng chuẩn do trang giao diện người dùng FlutterFire cung cấp. Tất cả các nút và trường văn bản đều được kết nối với Firebase Auth và hoạt động ngay từ đầu. Ví dụ: bạn có thể nhập tên vào trường văn bản "Tên" và giao diện người dùng FlutterFire sẽ gọi phương thức FirebaseAuth.instance.currentUser?.updateDisplayName để lưu tên đó vào Firebase.

Đang đăng xuất

Hiện tại, nếu bạn nhấn nút "Đăng xuất", ứng dụng sẽ không thay đổi. Thao tác này sẽ đăng xuất bạn nhưng bạn sẽ không được điều hướng trở lại tiện ích AuthGate. Để triển khai việc này, hãy sử dụng tham số ProfileScreen.actions.

Trước tiên, hãy cập nhật mã trong home.dart.

home.dart

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

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        actions: [
          IconButton(
            icon: const Icon(Icons.person),
            onPressed: () {
              Navigator.push(
                context,
                MaterialPageRoute<ProfileScreen>(
                  builder: (context) => ProfileScreen(
                    actions: [
                      SignedOutAction((context) {
                        Navigator.of(context).pop();
                      })
                    ],
                  ),
                ),
              );
            },
          )
        ],
        automaticallyImplyLeading: false,
      ),
      body: Center(
        child: Column(
          children: [
            Image.asset('dash.png'),
            Text(
              'Welcome!',
              style: Theme.of(context).textTheme.displaySmall,
            ),
            const SignOutButton(),
          ],
        ),
      ),
    );
  }
}

Giờ đây, khi tạo một thực thể của ProfileScreen, bạn cũng truyền cho thực thể đó danh sách thao tác đến đối số ProfileScreen.actions. Các thao tác này thuộc loại FlutterFireUiAction. Có nhiều lớp là các loại phụ của FlutterFireUiAction và nhìn chung, bạn sử dụng các lớp này để yêu cầu ứng dụng của mình phản ứng với những thay đổi về trạng thái xác thực. SignedOutAction gọi một hàm gọi lại mà bạn cung cấp cho hàm này khi trạng thái xác thực Firebase thay đổi thành currentUser rỗng.

Bằng cách thêm lệnh gọi lại gọi Navigator.of(context).pop() khi SignedOutAction kích hoạt, ứng dụng sẽ điều hướng về trang trước. Trong ứng dụng mẫu này, chỉ có một tuyến cố định hiển thị trang đăng nhập nếu người dùng chưa đăng nhập và trang chủ nếu có người dùng. Vì điều này xảy ra khi người dùng đăng xuất, nên ứng dụng sẽ hiển thị trang Đăng nhập.

Tuỳ chỉnh Trang doanh nghiệp

Tương tự như trang Đăng nhập, bạn có thể tuỳ chỉnh trang hồ sơ. Thứ nhất, trang hiện tại của chúng ta không có cách nào để quay lại trang chủ sau khi người dùng truy cập vào trang hồ sơ. Khắc phục vấn đề này bằng cách cung cấp AppBar cho tiện ích ProfileScreen.

home.dart

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

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

 @override
 Widget build(BuildContext context) {
   return Scaffold(
     appBar: AppBar(
       actions: [
         IconButton(
           icon: const Icon(Icons.person),
           onPressed: () {
             Navigator.push(
               context,
               MaterialPageRoute<ProfileScreen>(
                 builder: (context) => ProfileScreen(
                   appBar: AppBar(
                     title: const Text('User Profile'),
                   ),
                   actions: [
                     SignedOutAction((context) {
                       Navigator.of(context).pop();
                     })
                   ],
                 ),
               ),
             );
           },
         )
       ],
       automaticallyImplyLeading: false,
     ),
     body: Center(
       child: Column(
         children: [
           Image.asset('dash.png'),
           Text(
             'Welcome!',
             style: Theme.of(context).textTheme.displaySmall,
           ),
           const SignOutButton(),
         ],
       ),
     ),
   );
 }
}

Đối số ProfileScreen.appBar chấp nhận một tiện ích AppBar từ gói Flutter Material. Vì vậy, đối số này có thể được coi là một AppBar khác mà bạn đã tạo và truyền đến Scaffold. Trong ví dụ này, chức năng mặc định là tự động thêm nút "quay lại" được giữ nguyên và màn hình hiện có tiêu đề.

Thêm trẻ vào màn hình hồ sơ

Tiện ích ProfileScreen cũng có một đối số không bắt buộc được đặt tên là con. Đối số này chấp nhận một danh sách tiện ích và các tiện ích đó sẽ được đặt theo chiều dọc bên trong tiện ích Cột đã được sử dụng nội bộ để tạo ProfileScreen. Tiện ích Cột này trong phương thức xây dựng ProfileScreen sẽ đặt các thành phần con mà bạn truyền vào phía trên nút "Đăng xuất".

Cập nhật mã trong home.dart để hiển thị biểu trưng công ty tại đây, tương tự như màn hình đăng nhập.

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

Tải lại ứng dụng và bạn sẽ thấy thông báo này trên màn hình:

ebe5792b765dbf87.png.

7. Đăng nhập bằng Google Auth trên nhiều nền tảng

Giao diện người dùng FlutterFire cũng cung cấp các tiện ích và chức năng để xác thực với các nhà cung cấp bên thứ ba, chẳng hạn như Google, Twitter, Facebook, Apple và Github.

Để tích hợp với tính năng xác thực của Google, hãy cài đặt trình bổ trợ firebase_ui_oauth_google chính thức và các phần phụ thuộc của trình bổ trợ này. Trình bổ trợ này sẽ xử lý quy trình xác thực gốc. Trong cửa sổ dòng lệnh, hãy chuyển đến thư mục gốc của dự án flutter và nhập lệnh sau:

flutter pub add google_sign_in
flutter pub add firebase_ui_oauth_google

Bật Nhà cung cấp dịch vụ đăng nhập bằng Google

Tiếp theo, hãy bật nhà cung cấp của Google trong Bảng điều khiển của Firebase:

  1. Chuyển đến màn hình Nhà cung cấp dịch vụ đăng nhập xác thực trong bảng điều khiển.
  2. Nhấp vào "Thêm nhà cung cấp mới". 8286fb28be94bf30.pngs
  3. Chọn "Google". c4e28e6f4974be7f.png.
  4. Gạt nút chuyển có nhãn "Bật" rồi nhấn "Lưu". e74ff86990763826.pngS
  5. Nếu một cửa sổ bật lên xuất hiện với thông tin về việc tải tệp cấu hình xuống, hãy nhấp vào "Xong".
  6. Kiểm tra để đảm bảo bạn đã thêm nhà cung cấp dịch vụ đăng nhập bằng Google. 5329ce0543c90d95.pngS

Thêm nút đăng nhập bằng Google

Khi bật tính năng đăng nhập bằng Google, hãy thêm tiện ích cần thiết để hiển thị nút đăng nhập bằng Google được tạo kiểu vào trang đăng nhập. Chuyển đến tệp auth_gate.dart và cập nhật mã thành như sau:

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

Mã mới duy nhất ở đây là việc thêm GoogleProvider(clientId: "YOUR_WEBCLIENT_ID") vào cấu hình tiện íchSignInScreen.

Sau khi thêm mã đó, hãy tải lại ứng dụng và bạn sẽ thấy nút đăng nhập bằng Google.

aca71a46a011bfb5.png

Thiết lập nút đăng nhập

Nút này không hoạt động được nếu không có cấu hình bổ sung. Nếu đang phát triển bằng Flutter Web, thì đây là bước duy nhất bạn cần thêm để tính năng này hoạt động. Các nền tảng khác có các bước bổ sung sẽ được thảo luận sau.

  1. Chuyển đến trang Nhà cung cấp dịch vụ xác thực trong Bảng điều khiển của Firebase.
  2. Nhấp vào nhà cung cấp của Google. 9b3a325c5eca6e49.pngS
  3. Nhấp vào bảng mở rộng "Cấu hình SDK web".
  4. Sao chép giá trị từ "Mã ứng dụng khách web" 711a79f0d931c60f.png.
  5. Quay lại trình soạn thảo văn bản và cập nhật thực thể của GoogleProvider trong tệp auth_gate.dart bằng cách truyền mã nhận dạng này đến tham số có tên clientId.
GoogleProvider(
   clientId: "YOUR_WEBCLIENT_ID"
)

Sau khi nhập mã ứng dụng web, hãy tải lại ứng dụng. Khi bạn nhấn nút "Đăng nhập bằng Google", một cửa sổ mới sẽ xuất hiện (nếu bạn đang sử dụng web) để hướng dẫn bạn thực hiện quy trình đăng nhập bằng Google. Ban đầu, giao diện như sau:

14e73e3c9de704bb.png

Định cấu hình iOS

Để tính năng này hoạt động trên iOS, có thêm một quy trình định cấu hình.

  1. Chuyển đến màn hình Cài đặt dự án trong bảng điều khiển của Firebase. Bạn sẽ thấy một thẻ liệt kê các ứng dụng Firebase của mình như sau: fefa674acbf213cc.png
  2. Nhấp vào iOS. Xin lưu ý rằng tên đơn đăng ký của bạn sẽ khác với tên đơn đăng ký của tôi. Trong trường hợp của tôi nói "complete" (hoàn tất), nội dung của bạn sẽ hiển thị "bắt đầu", nếu bạn sử dụng dự án flutter-codelabs/firebase-auth-flutterfire-ui/start để tiếp tục theo dõi lớp học lập trình này.
  3. Nhấp vào nút "GoogleServices-Info.plist" để tải tệp cấu hình cần thiết xuống. f89b3192871dfbe3.png.
  4. Kéo và thả tệp đã tải xuống vào thư mục có tên là ./ios/Runner trong dự án Flutter của bạn.
  5. Mở Xcode bằng cách chạy lệnh dòng lệnh sau từ thư mục gốc của dự án: open ios/Runner.xcworkspace
  6. Nhấp chuột phải vào thư mục Runner (Trình chạy) rồi chọn Add Files to "Runner" (Thêm tệp vào "Runner"). 858986063a4c5201.png
  7. Chọn GoogleService-Info.plist trong trình quản lý tệp.
  8. Quay lại trình soạn thảo văn bản (không phải Xcode), thêm các thuộc tính CFBundleURLTypes bên dưới vào tệp [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. Bạn cần thay thế GoogleProvider.clientId mà bạn đã thêm trong phần thiết lập web bằng Mã ứng dụng khách được liên kết với mã ứng dụng khách Firebase iOS. Trước tiên, bạn có thể tìm thấy mã nhận dạng này trong tệp firebase_options.dart, trong hằng số iOS. Sao chép giá trị được truyền vào 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. Dán giá trị đó vào đối số GoogleProvider.clientId trong tiện ích 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();
     },
   );
 }
}

Nếu ứng dụng Flutter đang chạy trong iOS, bạn phải tắt hoàn toàn ứng dụng đó rồi chạy lại ứng dụng. Nếu không, hãy chạy ứng dụng trong iOS.

8. Xin chúc mừng!

Bạn đã hoàn tất giao diện người dùng xác thực Firebase cho lớp học lập trình Flutter . Bạn có thể tìm thấy mã đã hoàn chỉnh cho Lớp học lập trình này trong thư mục "complete" trên GitHub: Flutter Codelabs

Nội dung đã đề cập

  • Thiết lập một ứng dụng Flutter để dùng Firebase
  • Thiết lập dự án Firebase trong bảng điều khiển của Firebase
  • FlutterFire CLI
  • Giao diện dòng lệnh (CLI) của Firebase
  • Sử dụng phương pháp xác thực Firebase
  • Dễ dàng sử dụng giao diện người dùng FlutterFire để xử lý quy trình xác thực Firebase trong ứng dụng Flutter

Các bước tiếp theo

Tìm hiểu thêm

Sparky đã có mặt để chung vui cùng bạn!

2a0ad195769368b1.gif