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 Xác thực Firebase vào ứng dụng Flutter bằng gói FlutterFire UI. Với gói này, bạn sẽ thêm cả tính năng xác thực bằng email và mật khẩu cũng như tính năng xác thực bằng Google Sign In vào một ứng dụng Flutter. Bạn cũng sẽ tìm hiểu cách thiết lập một dự án Firebase và sử dụng FlutterFire CLI để khởi động 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ó kinh nghiệm sử dụng Flutter. Nếu không, trước tiên bạn nên tìm hiểu những kiến thức cơ bản. Các đường liên kết sau đây sẽ hữu ích:

Bạn cũng nên có kinh nghiệm sử dụng Firebase, nhưng không sao nếu bạn chưa từng thêm Firebase vào một 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 cách tạo quy trình xác thực cho một ứng dụng Flutter, sử dụ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.png

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

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

  • 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
  • Sử dụng FlutterFire CLI để tạo cấu hình Firebase trong Dart
  • Thêm Xác thực Firebase vào ứng dụng Flutter
  • Thiết lập 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 "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 đặ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 cách sử dụng gói firebase_ui_auth. Như bạn thấy, toàn bộ ứng dụng này, với tất cả các tính năng nêu 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 cơ bản về Flutter và đã cài đặt SDK
  • Một trình soạn thảo văn bản (Flutter hỗ trợ các IDE của JetBrains, Android Studio và VS Code)
  • Trình duyệt Google Chrome hoặc mục tiêu phát triển mà bạn ưu tiên khác cho Flutter. (Một số lệnh trên thiết bị đầu cuối 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 làm 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 bảng điều khiển của Firebase bằng Tài khoản Google của bạn.
  2. Nhấp vào nút này để tạo một dự án mới, rồi nhập tên dự án (ví dụ: FlutterFire-UI-Codelab).
  3. Nhấp vào Tiếp tục.
  4. Nếu được nhắc, hãy xem xét và chấp nhận các điều khoản của Firebase, rồi nhấp vào Tiếp tục.
  5. (Không bắt buộc) Bật tính năng hỗ trợ của AI trong bảng điều khiển của Firebase (còn gọi là "Gemini trong Firebase").
  6. Đối với lớp học lập trình này, bạn không cần Google Analytics, vì vậy hãy tắt lựa chọn Google Analytics.
  7. Nhấp vào Tạo dự án, đợi dự án được cấp phép rồi nhấp vào Tiếp tục.

Để 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 mà bạn đang tạo sử dụng Xác thực Firebase để 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 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 của Firebase, hãy mở rộng trình đơn Tạo ở 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 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 đầu 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ụ CLI của GitHub:

gh repo clone flutter/codelabs flutter-codelabs

Bạn nên sao chép 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 2 dự án Flutter. Một thuộc tính được gọi là complete và thuộc tính còn lại được gọ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 bỏ qua hoặc xem một đối tượng sẽ trông như thế nào khi hoàn thành, hãy xem trong thư mục có tên là complete để tham khảo chéo.

Nếu muốn theo dõi 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

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

Có nhiều cách để cài đặt CLI. Xem tất cả các lựa chọn có sẵn cho hệ điều hành của bạn tại firebase.google.com/docs/cli.

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
    
  2. 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.
  3. 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
    
  4. Danh sách hiển thị phải giống với các dự án Firebase có trong bảng điều khiển của 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ủa bạn. 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à xác minh 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ể 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 những câu hỏi 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-codelab1359cdeb83204baa.png
  2. Chọn những nền tảng bạn muốn sử dụng. Trong lớp học lập trình này, có các bước để định cấu hình Xác thực Firebase cho Flutter 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 lựa chọn. 301c9534f594f472.png
  3. Ảnh chụp màn hình này cho thấy kết quả đầu ra ở 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 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 đã thực hiện việc này cho bạn. 12199a85ade30459.png

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

lib/firebase_options.dart

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

class DefaultFirebaseOptions {
  static FirebaseOptions get currentPlatform {
    if (kIsWeb) {
      return web;
    }

    switch (defaultTargetPlatform) {
      case TargetPlatform.android:
        return android;
      case TargetPlatform.iOS:
        return ios;
      case TargetPlatform.macOS:
        return macos;
      default:
        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ỉ bản dựng cụ thể cho một nền tảng cụ thể trong một dự án Firebase. Ví dụ: dự án Firebase có tên FlutterFire-ui-codelab có nhiều ứng dụng: một cho Android, một cho iOS, một cho macOS và một cho Web.

Phương thức DefaultFirebaseOptions.currentPlatform sử dụng enum TargetPlatform do Flutter cung cấp để 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 phù hợp.

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 của bạn. Tệp firebase_options.dart sẽ có lỗi vì tệp này dựa 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 ở 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 firebase_auth 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, hãy cập nhật mã trong hàm main trong tệp main.dart.DefaultFirebaseOptions.currentPlatform,

lib/main.dart

import 'package:firebase_core/firebase_core.dart';                  // Add this import
import 'package:flutter/material.dart';

import 'app.dart';
import 'firebase_options.dart';                                     // And this import

// TODO(codelab user): Get API key
const clientId = 'YOUR_CLIENT_ID';

void main() async {
  // Add from here...
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
  // To here.

  runApp(const MyApp(clientId: clientId));
}

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

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

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

Firebase UI for 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ủa bạn. Những màn hình này xử lý nhiều quy trình xác thực trong ứng dụng của bạn, 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à một lớp bảo vệ xác thực cho ứng dụng chính.

Ứng dụng Material hoặc Cupertino

FlutterFire UI yêu cầu ứng dụng của bạn được bao bọc 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 của các tiện ích Material hoặc Cupertino. Trong 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).

lib/app.dart

import 'package:flutter/material.dart';

import 'auth_gate.dart';

class MyApp extends StatelessWidget {
  const MyApp({super.key, required this.clientId});

  final String clientId;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
      ),
      home: AuthGate(clientId: clientId),
    );
  }
}

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 đã được xác thực hay chưa. Cách phổ biến nhất để kiểm tra điều này là nghe FirebaseAuth của authStateChanges bằng cách sử dụng trình bổ trợ Xác thực Firebase.

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

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

API authStateChanges sẽ 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ể 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 ảnh chụp nhanh dữ liệu mới nhất từ một Stream mà bạn truyền cho tiện ích này. Nó sẽ tự động tạo lại khi Stream phát ra một ảnh chụp nhanh mới.

Cập nhật mã trong auth_gate.dart.

lib/auth_gate.dart

import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider; // Add this import
import 'package:firebase_ui_auth/firebase_ui_auth.dart';                  // And this import
import 'package:flutter/material.dart';

import 'home.dart';

class AuthGate extends StatelessWidget {
  const AuthGate({super.key, required this.clientId});

  final String clientId;

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

        return const HomeScreen();
      },
    );                                                                 // To here.
  }
}
  • StreamBuilder.stream đang được truyền FirebaseAuth.instance.authStateChanged, luồng nói trên, sẽ trả về một đối tượng Firebase User nếu người dùng đã xác thực, nếu không, đối tượng này sẽ trả về null.
  • Tiếp theo, mã này đang 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ó, thì phương thức này sẽ trả về một tiện ích SignInScreen. Hiện tại, màn hình này sẽ không làm gì cả, màn hình 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ỉ 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 FlutterFire UI cung cấp sẽ thêm các 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 "Quên mật khẩu?" và đượ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 chuyển đến một biểu mẫu khác để đăng ký.

Xin nhắc lại, bạn chỉ cần viết một vài dòng mã. Nhớ lại mã trong tiện ích AuthGate:

lib/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, required this.clientId});

  final String clientId;

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

        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. Lúc này, 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 dáng. 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 vào phía trên biểu mẫu đăng nhập. Tiện ích này chỉ xuất hiện trên màn hình hẹp, chẳng hạn như thiết bị di động. Trên màn hình lớn, bạn có thể sử dụng SignInScreen.sideBuilder. Chúng ta sẽ thảo luận về thành phần này ở các phần sau trong lớp học lập trình này.

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

lib/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, required this.clientId});

  final String clientId;

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<User?>(
      stream: FirebaseAuth.instance.authStateChanges(),
      builder: (context, snapshot) {
        if (!snapshot.hasData) {
          return SignInScreen(                                         // Modify from here...
            providers: [EmailAuthProvider()],
            headerBuilder: (context, constraints, shrinkOffset) {
              return Padding(
                padding: const EdgeInsets.all(20),
                child: AspectRatio(
                  aspectRatio: 1,
                  child: Image.asset('assets/flutterfire_300x.png'),
                ),
              );
            },
          );                                                           // To here.
        }

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

The headerBuilder argument requires a function of the type HeaderBuilder, which
is defined in the FlutterFire UI package.

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

Vì là một lệnh gọi lại, nên lệnh gọi lại này sẽ 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. Tiện ích mà 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 có thêm 3 tham số cho phép bạn tuỳ chỉnh màn hình: subtitleBuilder, footerBuildersideBuilder.

subtitleBuilder có khác biệt nhỏ là các đối số gọi lại bao gồm một thao tác 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.

lib/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, required this.clientId});

  final String clientId;

  @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'),
                ),
              );
            },
            subtitleBuilder: (context, action) {                     // Add from here...
              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!'),
              );
            },                                                       // To here.
          );
        }

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

Đối số footerBuilder giống với subtitleBuilder. API này không hiển thị BoxConstraints hoặc shrinkOffset vì API này dành cho văn bản chứ không phải hình ảnh. Tất nhiên, 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.

lib/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, required this.clientId});

  final String clientId;

  @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'),
                ),
              );
            },
            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) {                       // Add from here...
              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),
                ),
              );
            },                                                       // To here.
          );
        }

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

Side Builder

Đố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ẽ xuất hiện ở bên trái biểu mẫu đăng nhập và chỉ xuất hiện trên màn hình rộng. Điều này có nghĩa là tiện ích này sẽ chỉ xuất hiện trên máy tính và ứng dụng web.

Về nội bộ, FlutterFire UI sử dụng một điểm ngắt để xác định xem nội dung tiêu đề có nên xuất hiện (trên màn hình dọc, chẳng hạn như thiết bị di động) hay nội dung bên có nên xuất hiện (trên màn hình ngang, máy tính hoặc web). Cụ thể, nếu màn hình có chiều rộng lớn hơn 800 pixel, thì nội dung của trình tạo bên sẽ xuất hiện và nội dung của tiêu đề sẽ không xuất hiện. Nếu màn hình có chiều rộng nhỏ hơn 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.

lib/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, required this.clientId});

  final String clientId;

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

Đến đây là xong hết mã cho màn hình này. 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 bạn có thể tạo người dùng trong bảng điều khiển của 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. Chọn "flutterfire-ui-codelab" hoặc một dự án khác nếu bạn dùng tên khác. Bạn sẽ thấy bảng sau: f038fd9a58ed60d9.png
  2. Nhấp vào nút "Thêm người dùng". 2d78390d4c5dbbfa.png
  3. 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ả, như tôi đã nhập trong hình bên dưới. Cách này sẽ hiệu quả, 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
  4. 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 và đăng nhập cho người dùng bằng 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ơ

FlutterFire UI cũng cung cấp một tiện ích ProfileScreen. Tiện ích này cũng cung cấp cho bạn nhiều chức năng chỉ trong 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ã này:

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

Đoạn mã mới cần lưu ý là lệnh gọi lại được truyền đến phương thức IconButton.isPressed. Khi người dùng nhấn vào IconButton, ứng dụng của bạn sẽ tạo một tuyến đường ẩn danh mới và chuyển đến tuyến đường đó. Tuyến đường đó 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, đẩy biểu tượng ở trên cùng bên phải (trong thanh ứng dụng) và biểu tượng này 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 FlutterFire UI 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 Xác thực Firebase và hoạt động ngay khi xuất xưởng. Ví dụ: bạn có thể nhập tên vào trường văn bản "Tên" và FlutterFire UI 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 vào 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 dùng tham số ProfileScreen.actions.

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

lib/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: [
            SizedBox(width: 250, child: Image.asset('assets/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 sẽ truyền một danh sách các thao tác vào đối số ProfileScreen.actions. Các hành động này thuộc loại FlutterFireUiAction. Có nhiều lớp là kiểu phụ của FlutterFireUiAction và nói chung, bạn 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 uỷ quyền. SignedOutAction gọi một hàm gọi lại mà bạn cung cấp khi trạng thái xác thực Firebase thay đổi thành currentUser là giá trị 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 ví dụ này, chỉ có một tuyến đường cố định, cho thấy màn hình Đăng nhập nếu chưa có người dùng nào đă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ị màn hình Đăng nhập.

Tuỳ chỉnh trang hồ sơ

Tương tự như màn hình Đăng nhập, bạn có thể tuỳ chỉnh trang hồ sơ. Trước tiên, 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 thêm một AppBar vào tiện ích ProfileScreen.

lib/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: [
            SizedBox(width: 250, child: Image.asset('assets/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, bạn có thể coi đối số này như bất kỳ AppBar nào khác mà bạn đã tạo và truyền đến một Scaffold. Trong ví dụ này, chức năng mặc định là tự động thêm nút "back" (quay lại) vẫn đượ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 một danh sách các tiện ích và những tiện ích đó sẽ được đặt theo chiều dọc bên trong một tiện ích Column đã được dùng nội bộ để tạo ProfileScreen. Tiện ích Column này trong phương thức tạo ProfileScreen sẽ đặt các phần tử 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 biểu trưng công ty tại đây, tương tự như màn hình Đăng nhập.

lib/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: [
            SizedBox(width: 250, child: Image.asset('assets/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 tin sau trên màn hình:

ebe5792b765dbf87.png

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

FlutterFire UI 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 quy trình 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 rồi nhập lệnh sau:

flutter pub add google_sign_in 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 nhà cung cấp Google trong Bảng điều khiển của 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 vào "Lưu". e74ff86990763826.png
  5. Nếu một phương thức xuất hiện cùng 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 trì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ó kiểu cách vào màn hình đăng nhập. Chuyển đến tệp auth_gate.dart rồi cập nhật mã thành mã sau:

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

import 'home.dart';

class AuthGate extends StatelessWidget {
  const AuthGate({super.key, required this.clientId});

  final String clientId;

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

Đoạn 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

Định cấu hình 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 phải 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 các bước, 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 Google. 9b3a325c5eca6e49.png
  3. Nhấp vào bảng điều khiển mở rộng "Cấu hình Web SDK".
  4. Sao chép giá trị từ "Mã ứng dụng khách trên web". 711a79f0d931c60f.png
  5. Quay lại trình chỉnh sửa văn bản và cập nhật thực thể GoogleProvider trong tệp auth_gate.dart bằng cách truyền mã nhận dạng này vào tham số được đặt tên clientId.
GoogleProvider(
   clientId: "YOUR_WEBCLIENT_ID"
)

Sau khi bạn 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 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 thực hiện thêm một quy trình thiết lập.

  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, trông như sau: fefa674acbf213cc.png
  2. Chọn iOS. Xin lưu ý rằng tên ứng dụng của bạn sẽ khác với tên trong ảnh chụp màn hình. Trong ảnh chụp màn hình có chữ "complete" (hoàn tất), ảnh chụp màn hình của bạn sẽ có chữ "start" (bắt đầu) nếu bạn dùng dự án flutter-codelabs/firebase-auth-flutterfire-ui/start để theo dõi lớp học lập trình này.
  3. Nhấp vào nút có biểu tượng GoogleServices-Info.plist để tải tệp cấu hình cần thiết xuống. f89b3192871dfbe3.png
  4. Kéo 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 sau trên thiết bị đầu cuối từ gốc dự án của bạn: open ios/Runner.xcworkspace
  6. Nhấp chuột phải vào thư mục Runner 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. Trong trình soạn thảo văn bản (không phải Xcode), hãy thêm các thuộc tính CFBundleURLTypes bên dưới vào tệp 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 -->
    
  9. Bạn cần thay thế GoogleProvider.clientId mà bạn đã thêm trong chế độ thiết lập web bằng Mã khách hàng đượ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',
    );
    
  10. Dán giá trị đó vào biến clientId trong tệp lib/main.dart.

lib/main.dart

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

import 'app.dart';
import 'firebase_options.dart';

const clientId = 'YOUR_CLIENT_ID'; // Replace this value with your Client ID.

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

  runApp(const MyApp(clientId: clientId));
}

Nếu ứng dụng Flutter đang chạy trong iOS, bạn phải tắt hoàn toàn 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 Giao diện người dùng Firebase Auth cho Flutter . Bạn có thể tìm thấy đoạn mã hoàn chỉnh cho Lớp học lập trình này trong thư mục firebase-auth-flutterfire-ui/complete trên GitHub.

Nội dung đã đề cập

  • Thiết lập một ứ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 Firebase Authentication
  • Sử dụng giao diện người dùng FlutterFire để xử lý hoạt động 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 để cùng bạn ăn mừng!

2a0ad195769368b1.gif