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 cách sử dụ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:

Sản phẩm bạn sẽ tạo ra

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 cách sử dụng Firebase cho tính năng 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.png

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

Lớp học lập trình này sẽ đề cập đến:

  • Thêm Firebase vào ứng dụng Flutter
  • Thiết lập Bảng điều khiển Firebase
  • Sử dụng Firebase CLI để thêm Firebase vào ứng dụng
  • Sử dụng FlutterFire CLI để tạo cấu hình Firebase trong Dart
  • Thêm tính năng 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 tính năng đăng ký người dùng bằng gói firebase_ui_auth
  • Thêm trang "Bạn quên mật khẩu?"
  • 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 để hoạt động 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 tập trung vào việc thêm một hệ thống Xác thực mạnh mẽ bằng cách sử dụ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 soạn thảo văn bản (Flutter hỗ trợ JetBrains IDE, Android Studio và VS Code)
  • 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 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 Firebase Authentication để cho phép người dùng đăng nhập vào ứng dụng. Ứng dụng này cũng cho phép người dùng mới đăng ký từ ứ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ó 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 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, rồi 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 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ã 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 thuộc tính được gọi là complete và thuộc tính còn lại 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 và tự thêm mã, bạn nên bắt đầu với ứ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. Mở hoặc nhập thư mục đó vào IDE mà bạn muốn dùng.

Cài đặt Giao diện dòng lệnh (CLI) của Firebase

Giao diện dòng lệnh (CLI) của Firebase cung cấp các công cụ để quản lý dự án Firebase. Bạn cần có CLI cho FlutterFire CLI mà bạn sẽ cài đặt sau.

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. 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 sẽ xuất 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.

flutterfire configure

Khi chạy lệnh này, bạn sẽ được nhắc chọn dự án Firebase mà bạn muốn sử dụng và 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 các câu lệnh mà bạn cần 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ẽ tìm 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, nhưng bạn có thể thiết lập dự án Firebase để sử dụng tất cả các tuỳ chọn. 301c9534f594f472.png
  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 mình không cần tạo ứng dụng nền tảng (ví dụ: ứng dụng Android) trong bảng điều khiển và FlutterFire CLI đã thực hiện 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 do 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 dụng Firebase chính xác.

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 phụ thuộc vào các gói Firebase chưa được thêm. Trong thiết bị đầu cuối, 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à những gói duy nhất bạn cần tại thời điểm này.

Khởi động Firebase

Để sử dụng các gói đã thêm và DefaultFirebaseOptions.currentPlatform,, hãy 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 hai 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, yêu cầu khung phải đang chạy.
  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 cho Auth cung cấp các tiện ích đại diện cho toàn bộ màn hình trong ứng dụng. Các màn hình này xử lý nhiều quy trình xác thực trong ứ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 một trang đích vào ứng dụng của bạn để đóng vai trò là trình bảo vệ xác thực cho ứng dụng chính.

Ứng dụng Material hoặc Cupertino

Giao diện người dùng FlutterFire yêu cầu ứng dụng của bạn được gói trong 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. Lớp này đã đượ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 bản dựng. (Đây là một tiện ích tuỳ chỉnh, không 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. Lớp này sẽ tự động tạo lại khi Luồng phát ra một ảnh chụp 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, sẽ trả về một đối tượng User Firebase 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ã đang 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ả. Nội dung 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ý" để được chuyển đến một biểu mẫu khác cho phép họ đăng ký.

Xin nhắc lại, bạn chỉ cần một vài dòng mã. Hãy nhớ 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 để có được 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

headerBuilder

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ị thêm 3 tham số 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 enum mà bạn có thể dùng để phát hiện xem màn hình mà người dùng đang truy cập 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 subtitleBuilder. 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 mình 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 bên

Đối số SignInScreen.sidebuilder chấp nhận một 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 này có nghĩa là tiện ích sẽ chỉ hiển thị trên ứng dụng web và máy tính.

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

Bây giờ, ứng dụng của bạn 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

Tại thời điểm 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 một 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. Cách này sẽ hoạt động, nhưng chức 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ả.

62ba0feb33d54add.png

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

32b236b3ef94d4c7.png

Bây giờ, bạn có thể quay lại ứng dụng Flutter và đăng nhập người dùng thô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(),
          ],
        ),
      ),
    );
  }
}

Mã ghi chú mới là lệnh gọi lại được truyền đến IconButton.isPressed method. Khi 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 đó. 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 vào biểu tượng ở trên cùng bên phải (trong thanh ứng dụng). Ứng dụng sẽ hiển thị một trang như sau:

36487fc4ab4f26a7.png

Đây là giao diện người dùng tiêu 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.

Đă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 chuyển về 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(),
          ],
        ),
      ),
    );
  }
}

Bây giờ, khi tạo một thực thể của ProfileScreen, bạn cũng truyền danh sách các thao tác vào đối số ProfileScreen.actions. Các thao tác này thuộc loại FlutterFireUiAction. Có nhiều lớp là loại phụ của FlutterFireUiAction và nói chung, bạn sử dụng các lớp này để yêu cầu ứng dụng phản ứng với các 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 một lệnh gọi lại gọi Navigator.of(context).pop() khi SignedOutAction kích hoạt, ứng dụng sẽ chuyển đến trang trước. Trong ứng dụng mẫu này, chỉ có một tuyến đường 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 tiện ích AppBar từ gói Flutter Material, vì vậy, đối số này có thể được coi như mọi AppBar khác mà bạn đã tạo và chuyể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ẻ em 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ên là children. Đối số này chấp nhận danh sách các 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 tạo 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 Trình cung cấp dịch vụ đăng nhập bằng Google

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

  1. Chuyển đến màn hình Authentication sign-in providers (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.png
  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.png
  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. Xác nhận rằng bạn đã thêm nhà cung cấp dịch vụ đăng nhập bằng Google. 5329ce0543c90d95.png

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 ích SignInScreen.

Sau khi thê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 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 yêu cầu thêm một số bước, chúng ta sẽ thảo luận về các bước đó trong phần sau.

  1. Chuyển đến trang Nhà cung cấp xác thực trong Bảng điều khiển Firebase.
  2. Nhấp vào nhà cung cấp Google. 9b3a325c5eca6e49.png
  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, mã sẽ có dạng như sau:

14e73e3c9de704bb.png

Định cấu hình iOS

Để tính năng này hoạt động trên iOS, bạn cần phải thiết lập thêm.

  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 ứng dụng của bạn sẽ khác với tên ứng dụng của tôi. Nếu bạn đã sử dụng dự án flutter-codelabs/firebase-auth-flutterfire-ui/start để theo dõi lớp học lập trình này, thì dòng chữ "complete" (hoàn tất) của tôi sẽ là "start" (bắt đầu).
  3. Nhấp vào nút có nhãn "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 ./ios/Runner trong dự án Flutter.
  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 đến 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 của bạn đ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 lớp học lập trình về Giao diện người dùng Firebase Auth cho 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" (hoàn tất) trên GitHub: Lớp học lập trình về Flutter

Nội dung chúng ta đã đề cập

  • Thiết lập ứng dụng Flutter để sử 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 tính năng 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 xin chúc mừng bạn!

2a0ad195769368b1.gif