เพิ่มขั้นตอนการตรวจสอบสิทธิ์ผู้ใช้ลงในแอป Flutter โดยใช้ FirebaseUI

1. ก่อนเริ่มต้น

ในโค้ดแล็บนี้ คุณจะได้เรียนรู้วิธีเพิ่มการตรวจสอบสิทธิ์ Firebase ลงในแอป Flutter โดยใช้แพ็กเกจ FlutterFire UI แพ็กเกจนี้จะช่วยให้คุณเพิ่มทั้งการตรวจสอบสิทธิ์ด้วยอีเมลและรหัสผ่าน รวมถึงการตรวจสอบสิทธิ์ด้วย Google Sign In ลงในแอป Flutter ได้ นอกจากนี้ คุณยังจะได้ดูวิธีตั้งค่าโปรเจ็กต์ Firebase และใช้ FlutterFire CLI เพื่อเริ่มต้นใช้งาน Firebase ในแอป Flutter ด้วย

ข้อกำหนดเบื้องต้น

โค้ดแล็บนี้ถือว่าคุณมีประสบการณ์การใช้งาน Flutter อยู่บ้าง หากไม่ คุณอาจต้องเรียนรู้พื้นฐานก่อน ลิงก์ต่อไปนี้มีประโยชน์

คุณควรมีประสบการณ์การใช้งาน Firebase บ้าง แต่ก็ไม่มีปัญหาหากคุณไม่เคยเพิ่ม Firebase ลงในโปรเจ็กต์ Flutter หากคุณไม่คุ้นเคยกับคอนโซล Firebase หรือเพิ่งเริ่มใช้ Firebase เป็นครั้งแรก โปรดดูลิงก์ต่อไปนี้ก่อน

สิ่งที่คุณจะสร้าง

Codelab นี้จะแนะนำการสร้างขั้นตอนการตรวจสอบสิทธิ์สําหรับแอป Flutter โดยใช้ Firebase สําหรับการตรวจสอบสิทธิ์ แอปพลิเคชันจะมีหน้าจอเข้าสู่ระบบ หน้าจอ "ลงทะเบียน" หน้าจอการกู้คืนรหัสผ่าน และหน้าจอโปรไฟล์ผู้ใช้

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

สิ่งที่คุณจะได้เรียนรู้

Codelab นี้ครอบคลุมหัวข้อต่อไปนี้

  • การเพิ่ม Firebase ไปยังแอป Flutter
  • การตั้งค่าคอนโซล Firebase
  • การใช้ Firebase CLI เพื่อเพิ่ม Firebase ลงในแอปพลิเคชัน
  • การใช้ FlutterFire CLI เพื่อสร้างการกำหนดค่า Firebase ใน Dart
  • การเพิ่มการตรวจสอบสิทธิ์ Firebase ลงในแอป Flutter
  • การตั้งค่าการตรวจสอบสิทธิ์ Firebase ในคอนโซล
  • การเพิ่มการลงชื่อเข้าใช้ด้วยอีเมลและรหัสผ่านด้วยแพ็กเกจ firebase_ui_auth
  • การเพิ่มการลงทะเบียนผู้ใช้ด้วยแพ็กเกจ firebase_ui_auth
  • การเพิ่มหน้า "หากลืมรหัสผ่าน"
  • การเพิ่มฟีเจอร์ลงชื่อเข้าใช้ด้วย Google ด้วย firebase_ui_auth
  • การกำหนดค่าแอปให้ทำงานร่วมกับผู้ให้บริการลงชื่อเข้าใช้หลายราย
  • การเพิ่มหน้าจอโปรไฟล์ผู้ใช้ลงในแอปพลิเคชันด้วยแพ็กเกจ firebase_ui_auth

โค้ดแล็บนี้เกี่ยวข้องกับการเพิ่มระบบการตรวจสอบสิทธิ์ที่มีประสิทธิภาพโดยใช้แพ็กเกจ firebase_ui_auth โดยเฉพาะ คุณจะเห็นว่าแอปทั้งหมดนี้พร้อมฟีเจอร์ข้างต้นทั้งหมดสามารถติดตั้งใช้งานได้ด้วยโค้ดประมาณ 100 บรรทัด

สิ่งที่ต้องมี

  • ความรู้เกี่ยวกับ Flutter และ SDK ที่ติดตั้งไว้
  • เครื่องมือแก้ไขข้อความ (Flutter รองรับ JetBrains IDE, Android Studio และ VS Code)
  • เบราว์เซอร์ Google Chrome หรือเป้าหมายการพัฒนาอื่นๆ ที่ต้องการสำหรับ Flutter (คำสั่งในเทอร์มินัลบางรายการในโค้ดแล็บนี้จะถือว่าคุณเรียกใช้แอปใน Chrome)

2. สร้างและตั้งค่าโปรเจ็กต์ Firebase

งานแรกที่คุณต้องทำคือสร้างโปรเจ็กต์ Firebase ในเว็บคอนโซล Firebase

สร้างโปรเจ็กต์ Firebase

  1. ลงชื่อเข้าใช้ Firebase
  2. ในคอนโซล Firebase ให้คลิกเพิ่มโปรเจ็กต์ (หรือสร้างโปรเจ็กต์) แล้วป้อนชื่อโปรเจ็กต์ Firebase (เช่น "FlutterFire-UI-Codelab") df42a5e3d9584b48.png
  3. คลิกตัวเลือกการสร้างโปรเจ็กต์ ยอมรับข้อกำหนดของ Firebase หากได้รับข้อความแจ้ง ข้ามการตั้งค่า Google Analytics เนื่องจากคุณจะไม่ได้ใช้ Analytics สําหรับแอปนี้ d1fcec48bf251eaa.png

ดูข้อมูลเพิ่มเติมเกี่ยวกับโปรเจ็กต์ Firebase ได้ที่ทําความเข้าใจโปรเจ็กต์ Firebase

เปิดใช้การลงชื่อเข้าใช้ด้วยอีเมลสําหรับการตรวจสอบสิทธิ์ Firebase

แอปที่คุณกําลังสร้างใช้ Firebase Authentication เพื่ออนุญาตให้ผู้ใช้ลงชื่อเข้าใช้แอป นอกจากนี้ยังอนุญาตให้ผู้ใช้ใหม่ลงทะเบียนจากแอปพลิเคชัน Flutter ได้ด้วย

คุณต้องเปิดใช้ Firebase Authentication โดยใช้คอนโซล Firebase และต้องมีการกําหนดค่าพิเศษเมื่อเปิดใช้

หากต้องการอนุญาตให้ผู้ใช้ลงชื่อเข้าใช้เว็บแอป คุณจะต้องลงชื่อเข้าใช้ด้วยวิธีการอีเมล/รหัสผ่านก่อน คุณจะเพิ่มวิธีการ Google Sign-In ในภายหลัง

  1. ในคอนโซล Firebase ให้ขยายเมนูสร้างในแผงด้านซ้าย
  2. คลิกการตรวจสอบสิทธิ์ แล้วคลิกปุ่มเริ่มต้นใช้งาน จากนั้นคลิกแท็บวิธีการลงชื่อเข้าใช้ (หรือไปที่แท็บวิธีการลงชื่อเข้าใช้โดยตรง)
  3. คลิกอีเมล/รหัสผ่านในรายการผู้ให้บริการลงชื่อเข้าใช้ ตั้งสวิตช์เปิดใช้เป็นเปิด แล้วคลิกบันทึก

58e3e3e23c2f16a4.png

3. ตั้งค่าแอป Flutter

คุณจะต้องดาวน์โหลดโค้ดเริ่มต้นและติดตั้ง Firebase CLI ก่อนที่เราจะเริ่ม

รับรหัสเริ่มต้น

โคลนที่เก็บ GitHub จากบรรทัดคำสั่ง

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

หรือหากคุณติดตั้งเครื่องมือ CLI ของ GitHub ไว้ ให้ทำดังนี้

gh repo clone flutter/codelabs flutter-codelabs

คุณควรโคลนโค้ดตัวอย่างลงในไดเรกทอรี flutter-codelabs ในเครื่อง ซึ่งจะมีโค้ดสำหรับคอลเล็กชันโค้ดแล็บ โค้ดสําหรับโค้ดแล็บนี้อยู่ในไดเรกทอรีย่อย flutter-codelabs/firebase-auth-flutterfire-ui

ไดเรกทอรี flutter-codelabs/firebase-auth-flutterfire-ui มีโปรเจ็กต์ Flutter 2 โปรเจ็กต์ รายการหนึ่งชื่อว่า complete และอีกรายการหนึ่งชื่อว่า start ไดเรกทอรี start มีโปรเจ็กต์ที่ไม่สมบูรณ์ และเป็นไดเรกทอรีที่คุณจะใช้เวลามากที่สุด

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

หากต้องการข้ามไปข้างหน้าหรือดูว่าสิ่งต่างๆ ควรมีลักษณะอย่างไรเมื่อเสร็จสมบูรณ์ ให้ดูในไดเรกทอรีชื่อ "เสร็จสมบูรณ์" เพื่อตรวจสอบ

หากต้องการทําตาม Codelab และเพิ่มโค้ดด้วยตนเอง คุณควรเริ่มต้นด้วยแอป Flutter ที่ flutter-codelabs/firebase-auth-flutterfire-ui/start และเพิ่มโค้ดลงในโปรเจ็กต์นั้นตลอดทั้ง Codelab เปิดหรือนําเข้าไดเรกทอรีนั้นไปยัง IDE ที่ต้องการ

ติดตั้ง Firebase CLI

Firebase CLI มีเครื่องมือสำหรับจัดการโปรเจ็กต์ Firebase คุณต้องใช้ CLI สำหรับ FlutterFire CLI ซึ่งจะติดตั้งในอีกสักครู่

การติดตั้ง CLI มีหลายวิธี ตรวจสอบตัวเลือกทั้งหมดที่ใช้ได้สำหรับระบบปฏิบัติการของคุณที่ firebase.google.com/docs/cli

หลังจากติดตั้ง CLI แล้ว คุณต้องตรวจสอบสิทธิ์กับ Firebase

  1. เข้าสู่ระบบ Firebase โดยใช้บัญชี Google โดยเรียกใช้คําสั่งต่อไปนี้
    firebase login
    
  2. คำสั่งนี้จะเชื่อมต่อเครื่องของคุณกับ Firebase และให้สิทธิ์เข้าถึงโปรเจ็กต์ Firebase แก่คุณ
  3. ทดสอบว่า CLI ติดตั้งอย่างถูกต้องและมีสิทธิ์เข้าถึงบัญชีโดยแสดงรายการโปรเจ็กต์ Firebase เรียกใช้คําสั่งต่อไปนี้
    firebase projects:list
    
  4. รายการที่แสดงควรเหมือนกับโปรเจ็กต์ Firebase ที่แสดงในคอนโซล Firebase คุณควรเห็นอย่างน้อย flutterfire-ui-codelab.

ติดตั้ง FlutterFire CLI

FlutterFire CLI เป็นเครื่องมือที่ช่วยลดความซับซ้อนในกระบวนการติดตั้ง Firebase ในทุกแพลตฟอร์มที่รองรับในแอป Flutter โดยสร้างขึ้นจาก Firebase CLI

ก่อนอื่น ให้ติดตั้ง CLI โดยทำดังนี้

dart pub global activate flutterfire_cli

ตรวจสอบว่าได้ติดตั้ง CLI แล้ว เรียกใช้คําสั่งต่อไปนี้และยืนยันว่า CLI แสดงเมนูความช่วยเหลือ

flutterfire --help

เพิ่มโปรเจ็กต์ Firebase ลงในแอป Flutter

กำหนดค่า FlutterFire

คุณสามารถใช้ FlutterFire เพื่อสร้างโค้ด Dart ที่จําเป็นสําหรับใช้ Firebase ในแอป Flutter

flutterfire configure

เมื่อเรียกใช้คําสั่งนี้ ระบบจะแจ้งให้คุณเลือกโปรเจ็กต์ Firebase ที่ต้องการใช้และแพลตฟอร์มที่ต้องการตั้งค่า

ภาพหน้าจอต่อไปนี้แสดงพรอมต์ที่คุณต้องตอบ

  1. เลือกโปรเจ็กต์ที่ต้องการใช้ ในกรณีนี้ ให้ใช้ flutterfire-ui-codelab1359cdeb83204baa.png
  2. เลือกแพลตฟอร์มที่ต้องการใช้ ในโค้ดแล็บนี้จะมีขั้นตอนการกําหนดค่าการตรวจสอบสิทธิ์ Firebase สําหรับ Flutter สําหรับเว็บ, iOS และ Android แต่คุณสามารถตั้งค่าโปรเจ็กต์ Firebase ให้ใช้ตัวเลือกทั้งหมดได้ 301c9534f594f472.png
  3. ภาพหน้าจอนี้แสดงเอาต์พุตเมื่อสิ้นสุดกระบวนการ หากคุ้นเคยกับ Firebase คุณจะเห็นว่าคุณไม่จําเป็นต้องสร้างแอปพลิเคชันแพลตฟอร์ม (เช่น แอปพลิเคชัน Android) ในคอนโซล เนื่องจาก FlutterFire CLI เป็นผู้สร้างให้ 12199a85ade30459.png

เมื่อดำเนินการเสร็จแล้ว ให้ดูแอป Flutter ในเครื่องมือแก้ไขข้อความ FlutterFire CLI ได้แก้ไขไฟล์ชื่อ firebase_options.dart ไฟล์นี้มีคลาสชื่อ FirebaseOptions ซึ่งมีตัวแปรแบบคงที่ที่จัดเก็บการกำหนดค่า Firebase ที่จําเป็นสําหรับแต่ละแพลตฟอร์ม หากเลือกทุกแพลตฟอร์มเมื่อเรียกใช้ flutterfire configure คุณจะเห็นค่าคงที่ชื่อ web, android, ios และ macos

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 ใช้คำว่าแอปพลิเคชันเพื่ออ้างอิงถึงบิลด์ที่เฉพาะเจาะจงสำหรับแพลตฟอร์มที่เฉพาะเจาะจงในโปรเจ็กต์ Firebase ตัวอย่างเช่น โปรเจ็กต์ Firebase ชื่อ FlutterFire-ui-codelab มีแอปพลิเคชันหลายรายการ ได้แก่ 1 รายการสําหรับ Android, 1 รายการสําหรับ iOS, 1 รายการสําหรับ macOS และ 1 รายการสําหรับเว็บ

เมธอด DefaultFirebaseOptions.currentPlatform ใช้ TargetPlatform enum ที่ Flutter แสดงเพื่อตรวจหาแพลตฟอร์มที่แอปของคุณทํางานอยู่ จากนั้นแสดงผลค่าการกําหนดค่า Firebase ที่จําเป็นสําหรับแอปพลิเคชัน Firebase ที่ถูกต้อง

เพิ่มแพ็กเกจ Firebase ลงในแอป Flutter

ขั้นตอนสุดท้ายในการตั้งค่าคือการเพิ่มแพ็กเกจ Firebase ที่เกี่ยวข้องลงในโปรเจ็กต์ Flutter ไฟล์ firebase_options.dart ควรมีข้อผิดพลาด เนื่องจากใช้แพ็กเกจ Firebase ที่ยังไม่ได้เพิ่ม ในเทอร์มินัล ให้ตรวจสอบว่าคุณอยู่ในรูทของโปรเจ็กต์ Flutter ที่ flutter-codelabs/firebase-emulator-suite/start จากนั้นเรียกใช้คําสั่ง 3 รายการต่อไปนี้

flutter pub add firebase_core firebase_auth firebase_ui_auth

แพ็กเกจเหล่านี้เป็นแพ็กเกจเดียวที่คุณต้องใช้ในตอนนี้

เริ่มต้น Firebase

หากต้องการใช้แพ็กเกจที่เพิ่มและ DefaultFirebaseOptions.currentPlatform, ให้อัปเดตโค้ดในฟังก์ชัน main ในไฟล์ main.dart

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

รหัสนี้ทํา 2 อย่าง

  1. WidgetsFlutterBinding.ensureInitialized() บอกให้ Flutter ไม่เริ่มเรียกใช้โค้ดวิดเจ็ตแอปพลิเคชันจนกว่าเฟรมเวิร์ก Flutter จะบูตเสร็จสมบูรณ์ Firebase ใช้ช่องทางแพลตฟอร์มแบบเนทีฟ ซึ่งกำหนดให้เฟรมเวิร์กต้องทำงานอยู่
  2. Firebase.initializeApp จะสร้างการเชื่อมต่อระหว่างแอป Flutter กับโปรเจ็กต์ Firebase ระบบจะนําเข้า DefaultFirebaseOptions.currentPlatform จากไฟล์ firebase_options.dart ที่เราสร้างขึ้น ค่าคงที่นี้จะตรวจหาแพลตฟอร์มที่คุณใช้อยู่ และส่งคีย์ Firebase ที่เกี่ยวข้อง

4. เพิ่มหน้า Firebase UI Auth เริ่มต้น

UI ของ Firebase สำหรับการตรวจสอบสิทธิ์มีวิดเจ็ตที่แสดงทั้งหน้าจอในแอปพลิเคชัน หน้าจอเหล่านี้จัดการขั้นตอนการตรวจสอบสิทธิ์ต่างๆ ทั่วทั้งแอปพลิเคชัน เช่น การลงชื่อเข้าใช้ การลงทะเบียน ลืมรหัสผ่าน โปรไฟล์ผู้ใช้ และอื่นๆ หากต้องการเริ่มต้นใช้งาน ให้เพิ่มหน้า Landing Page ลงในแอปที่ทำหน้าที่เป็นยามตรวจสอบสิทธิ์สําหรับแอปพลิเคชันหลัก

แอป Material หรือ Cupertino

UI ของ FlutterFire กำหนดให้แอปพลิเคชันของคุณต้องรวมอยู่ใน MaterialApp หรือ CupertinoApp UI จะแสดงความแตกต่างของวิดเจ็ต Material หรือ Cupertino โดยอัตโนมัติตามตัวเลือกของคุณ สําหรับโค้ดแล็บนี้ ให้ใช้ MaterialApp ซึ่งเพิ่มลงในแอปใน 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),
    );
  }
}

ตรวจสอบสถานะการตรวจสอบสิทธิ์

คุณต้องตรวจสอบว่าผู้ใช้ได้รับการตรวจสอบสิทธิ์หรือไม่ก่อนจึงจะแสดงหน้าจอลงชื่อเข้าใช้ได้ วิธีตรวจสอบที่พบบ่อยที่สุดคือการฟัง authStateChanges ของ FirebaseAuth โดยใช้ปลั๊กอิน Firebase Auth

ในตัวอย่างโค้ดด้านบน MaterialApp กำลังสร้างวิดเจ็ต AuthGate ในเมธอด build (นี่คือวิดเจ็ตที่กําหนดเอง ซึ่ง FlutterFire UI ไม่ได้ให้ไว้)

วิดเจ็ตดังกล่าวต้องได้รับการอัปเดตให้รวมสตรีม authStateChanges

authStateChanges API จะแสดงผล Stream ที่มีผู้ใช้ปัจจุบัน (หากลงชื่อเข้าใช้อยู่) หรือค่า Null หากไม่ได้ลงชื่อเข้าใช้ หากต้องการสมัครรับข้อมูลสถานะนี้ในแอปพลิเคชันของเรา คุณสามารถใช้วิดเจ็ต StreamBuilder ของ Flutter และส่งสตรีมไปยังวิดเจ็ตดังกล่าว

StreamBuilder คือวิดเจ็ตที่สร้างตัวเองโดยอิงตามข้อมูลสแนปชอตล่าสุดจากสตรีมที่คุณส่งให้ ระบบจะสร้างใหม่โดยอัตโนมัติเมื่อ Stream ส่งสแนปชอตใหม่

อัปเดตรหัสใน 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 กำลังส่งผ่าน FirebaseAuth.instance.authStateChanged ซึ่งเป็นสตรีมข้างต้น ซึ่งจะแสดงผลออบเจ็กต์ User ของ Firebase หากผู้ใช้ตรวจสอบสิทธิ์แล้ว ไม่เช่นนั้นระบบจะแสดงผล null
  • ถัดไป โค้ดใช้ snapshot.hasData เพื่อตรวจสอบว่าค่าจากสตรีมมีออบเจ็กต์ User หรือไม่
  • หากไม่มี ฟีเจอร์นี้จะแสดงวิดเจ็ต SignInScreen ขณะนี้หน้าจอนี้จะไม่ทําอะไรเลย และจะอัปเดตในขั้นตอนถัดไป
  • มิเช่นนั้น ระบบจะแสดงผล HomeScreen ซึ่งเป็นส่วนหลักของแอปพลิเคชันที่ผู้ใช้ที่ได้รับการตรวจสอบสิทธิ์เท่านั้นที่เข้าถึงได้

SignInScreen คือวิดเจ็ตที่มาจากแพ็กเกจ UI ของ FlutterFire ซึ่งจะเป็นหัวข้อหลักของขั้นตอนถัดไปในโค้ดแล็บนี้ เมื่อเรียกใช้แอป ณ จุดนี้ คุณควรเห็นหน้าจอลงชื่อเข้าใช้ที่ว่างเปล่า

5. หน้าจอลงชื่อเข้าใช้

วิดเจ็ต SignInScreen ที่ FlutterFire UI มีให้จะเพิ่มฟังก์ชันต่อไปนี้

  • อนุญาตให้ผู้ใช้ลงชื่อเข้าใช้
  • หากผู้ใช้ลืมรหัสผ่าน ให้แตะ "ลืมรหัสผ่าน" แล้วระบบจะนำผู้ใช้ไปยังแบบฟอร์มสำหรับรีเซ็ตรหัสผ่าน
  • หากยังไม่ได้ลงทะเบียน ผู้ใช้สามารถแตะ "ลงทะเบียน" แล้วระบบจะนำไปยังแบบฟอร์มอื่นที่อนุญาตให้ลงชื่อสมัครใช้ได้

อีกครั้ง ขั้นตอนนี้ใช้โค้ดเพียง 2-3 บรรทัด เรียกดูรหัสในวิดเจ็ต 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();
      },
    );
  }
}

วิดเจ็ต SignInScreen และอาร์กิวเมนต์ providers ของวิดเจ็ตเป็นโค้ดเพียงรายการเดียวที่จําเป็นต่อการใช้งานฟังก์ชันการทำงานทั้งหมดที่กล่าวมาข้างต้น ตอนนี้คุณควรเห็นหน้าจอลงชื่อเข้าใช้ที่มีช่องป้อนข้อความ "อีเมล" และ "รหัสผ่าน" รวมถึงปุ่ม "ลงชื่อเข้าใช้"

แม้ว่าจะใช้งานได้ แต่ไม่มีการจัดรูปแบบ วิดเจ็ตจะแสดงพารามิเตอร์เพื่อปรับแต่งลักษณะของหน้าจอลงชื่อเข้าใช้ เช่น คุณอาจต้องการเพิ่มโลโก้ของบริษัท

ปรับแต่งหน้าจอลงชื่อเข้าใช้

headerBuilder

เมื่อใช้อาร์กิวเมนต์ SignInScreen.headerBuilder คุณจะเพิ่มวิดเจ็ตที่ต้องการเหนือแบบฟอร์มลงชื่อเข้าใช้ได้ วิดเจ็ตนี้จะแสดงบนหน้าจอแคบเท่านั้น เช่น อุปกรณ์เคลื่อนที่ ในหน้าจอกว้าง คุณสามารถใช้ SignInScreen.sideBuilder ซึ่งจะอธิบายในภายหลังในโค้ดแล็บนี้

อัปเดตไฟล์ lib/auth_gate.dart ด้วยโค้ดนี้

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

เนื่องจากเป็นคอลแบ็ก จึงแสดงค่าที่คุณใช้ได้ เช่น BuildContext และ BoxConstraints และต้องให้คุณแสดงวิดเจ็ต วิดเจ็ตที่คุณแสดงกลับมาจะแสดงที่ด้านบนของหน้าจอ ในตัวอย่างนี้ โค้ดใหม่จะเพิ่มรูปภาพไว้ที่ด้านบนของหน้าจอ ตอนนี้ใบสมัครของคุณควรมีลักษณะดังนี้

73d7548d91bbd2ab.png

เครื่องมือสร้างคำบรรยาย

หน้าจอลงชื่อเข้าใช้จะแสดงพารามิเตอร์เพิ่มเติม 3 รายการที่ให้คุณปรับแต่งหน้าจอได้ ได้แก่ subtitleBuilder, footerBuilder และ sideBuilder

subtitleBuilder จะแตกต่างเล็กน้อยตรงที่อาร์กิวเมนต์การเรียกกลับจะมีการดำเนินการ ซึ่งเป็นประเภท AuthAction AuthAction คือ Enum ที่คุณสามารถใช้เพื่อตรวจจับว่าหน้าจอที่ผู้ใช้อยู่นั้นคือหน้าจอ "ลงชื่อเข้าใช้" หรือหน้าจอ "ลงทะเบียน"

อัปเดตโค้ดใน auth_gate.dart เพื่อใช้ 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();
      },
    );
  }
}

อาร์กิวเมนต์ footerBuilder เหมือนกับ subtitleBuilder จะไม่แสดง BoxConstraints หรือ shrinkOffset เนื่องจากมีไว้สำหรับข้อความ ไม่ใช่รูปภาพ แน่นอนว่าคุณเพิ่มวิดเจ็ตใดก็ได้ที่ต้องการ

เพิ่มส่วนท้ายลงในหน้าจอลงชื่อเข้าใช้ด้วยรหัสนี้

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

อาร์กิวเมนต์ SignInScreen.sidebuilder ยอมรับการเรียกกลับ และในครั้งนี้อาร์กิวเมนต์สําหรับการเรียกกลับคือ BuildContext และ double shrinkOffset วิดเจ็ตที่ sideBuilder แสดงผลจะปรากฏทางด้านซ้ายของแบบฟอร์มลงชื่อเข้าใช้และในหน้าจอแบบกว้างเท่านั้น ซึ่งหมายความว่าวิดเจ็ตจะแสดงบนเดสก์ท็อปและเว็บแอปเท่านั้น

ทางฝั่งใน UI ของ FlutterFire จะใช้จุดหยุดพักเพื่อพิจารณาว่าควรแสดงเนื้อหาส่วนหัว (บนหน้าจอแนวตั้ง เช่น อุปกรณ์เคลื่อนที่) หรือควรแสดงเนื้อหาด้านข้าง (บนหน้าจอแนวนอน เดสก์ท็อป หรือเว็บ) กล่าวโดยละเอียดคือ หากหน้าจอกว้างกว่า 800 พิกเซล ระบบจะแสดงเนื้อหาของเครื่องมือสร้างโฆษณาที่ด้านข้าง และไม่แสดงเนื้อหาส่วนหัว หากหน้าจอกว้างน้อยกว่า 800 พิกเซล ผลลัพธ์จะตรงกันข้าม

อัปเดตโค้ดใน auth_gate.dart เพื่อเพิ่มวิดเจ็ต 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();
      },
    );
  }
}

ตอนนี้แอปของคุณควรมีลักษณะเช่นนี้เมื่อคุณขยายความกว้างของหน้าต่าง (หากคุณใช้ Flutter Web หรือ MacOS)

8dc60b4e5d7dd2d0.png

สร้างผู้ใช้

ตอนนี้โค้ดทั้งหมดสําหรับหน้าจอนี้เสร็จแล้ว แต่คุณต้องสร้างผู้ใช้ก่อนจึงจะลงชื่อเข้าใช้ได้ ซึ่งทำได้ผ่านหน้าจอ "ลงทะเบียน" หรือจะสร้างผู้ใช้ในคอนโซล Firebase ก็ได้

วิธีใช้คอนโซล

  1. ไปที่ตาราง"ผู้ใช้" ในคอนโซล Firebase เลือก "flutterfire-ui-codelab" หรือโปรเจ็กต์อื่นหากคุณใช้ชื่ออื่น คุณจะเห็นตารางนี้ f038fd9a58ed60d9.png
  2. คลิกปุ่ม "เพิ่มผู้ใช้" 2d78390d4c5dbbfa.png
  3. ป้อนอีเมลและรหัสผ่านของผู้ใช้ใหม่ อีเมลและรหัสผ่านนี้อาจเป็นอีเมลและรหัสผ่านปลอมตามที่เราได้ป้อนในรูปภาพด้านล่าง วิธีนี้ใช้ได้ แต่ฟังก์ชัน "ลืมรหัสผ่าน" จะไม่ทำงานหากคุณใช้อีเมลปลอม 62ba0feb33d54add.png
  4. คลิก "เพิ่มผู้ใช้" 32b236b3ef94d4c7.png

ตอนนี้คุณกลับไปที่แอปพลิเคชัน Flutter และลงชื่อเข้าใช้ผู้ใช้โดยใช้หน้าลงชื่อเข้าใช้ได้ แอปของคุณควรมีลักษณะดังนี้

dd43d260537f3b1a.png

6. หน้าจอโปรไฟล์

FlutterFire UI ยังมีวิดเจ็ต ProfileScreen ด้วย ซึ่งจะช่วยให้คุณมีฟังก์ชันการทำงานมากมายในโค้ดเพียงไม่กี่บรรทัด

เพิ่มวิดเจ็ต ProfileScreen

ไปที่ไฟล์ 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) => 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(),
          ],
        ),
      ),
    );
  }
}

รหัสใหม่ของโน้ตคือคอลแบ็กที่ส่งไปยังเมธอด IconButton.isPressed เมื่อกด IconButton นั้น แอปพลิเคชันจะสร้างเส้นทางใหม่ที่ไม่ระบุตัวตนและไปยังเส้นทางนั้น เส้นทางนั้นจะแสดงวิดเจ็ต ProfileScreen ซึ่งแสดงผลจาก Callback ของ MaterialPageRoute.builder

โหลดแอปอีกครั้ง แล้วกดไอคอนที่ด้านขวาบน (ในแถบแอป) จากนั้นระบบจะแสดงหน้าเว็บดังต่อไปนี้

36487fc4ab4f26a7.png

นี่คือ UI มาตรฐานที่หน้า UI ของ FlutterFire มีให้ ปุ่มและช่องข้อความทั้งหมดจะเชื่อมต่อกับ Firebase Auth และใช้งานได้ทันที เช่น คุณสามารถป้อนชื่อในช่องข้อความ "ชื่อ" แล้ว UI ของ FlutterFire จะเรียกใช้เมธอด FirebaseAuth.instance.currentUser?.updateDisplayName ซึ่งจะบันทึกชื่อนั้นใน Firebase

ออกจากระบบ

ขณะนี้ หากคุณกดปุ่ม "ออกจากระบบ" แอปจะไม่เปลี่ยนแปลง ระบบจะออกจากระบบให้คุณ แต่จะไม่นําคุณกลับไปที่วิดเจ็ต AuthGate หากต้องการใช้ ให้ใช้พารามิเตอร์ ProfileScreen.actions

ก่อนอื่น ให้อัปเดตโค้ดใน 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(),
          ],
        ),
      ),
    );
  }
}

ตอนนี้เมื่อคุณสร้างอินสแตนซ์ของ ProfileScreen คุณจะส่งรายการการดำเนินการไปยังอาร์กิวเมนต์ ProfileScreen.actions ด้วย การดำเนินการเหล่านี้เป็นประเภท FlutterFireUiAction มีคลาสต่างๆ มากมายที่เป็นประเภทย่อยของ FlutterFireUiAction และโดยทั่วไปแล้วคุณใช้คลาสเหล่านี้เพื่อบอกให้แอปตอบสนองต่อการเปลี่ยนแปลงสถานะการรับรองที่แตกต่างกัน SignedOutAction จะเรียกฟังก์ชัน Callback ที่คุณระบุไว้เมื่อสถานะการตรวจสอบสิทธิ์ Firebase เปลี่ยนเป็น currentUser เป็นค่าว่าง

การเพิ่มการเรียกกลับที่เรียก Navigator.of(context).pop() เมื่อ SignedOutAction ทริกเกอร์ แอปจะไปยังหน้าก่อนหน้า ในแอปตัวอย่างนี้ มีเส้นทางถาวรเพียงเส้นทางเดียว ซึ่งจะแสดงหน้าจอลงชื่อเข้าใช้หากไม่มีผู้ใช้ลงชื่อเข้าใช้ และหน้าแรกหากมีผู้ใช้ เนื่องจากเหตุการณ์นี้เกิดขึ้นเมื่อผู้ใช้ออกจากระบบ แอปจึงจะแสดงหน้าจอลงชื่อเข้าใช้

ปรับแต่งหน้าโปรไฟล์

หน้าโปรไฟล์ปรับแต่งได้เช่นเดียวกับหน้าจอลงชื่อเข้าใช้ ประการแรก หน้าปัจจุบันของเราไม่มีวิธีกลับไปที่หน้าแรกเมื่อผู้ใช้อยู่ในหน้าโปรไฟล์ แก้ไขปัญหานี้โดยให้ AppBar กับวิดเจ็ต 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(),
          ],
        ),
      ),
    );
  }
}

อาร์กิวเมนต์ ProfileScreen.appBar จะยอมรับวิดเจ็ต AppBar จากแพ็กเกจ Flutter Material เพื่อให้ระบบจัดการเหมือนกับ AppBar อื่นๆ ที่คุณสร้างและส่งไปยัง Scaffold ในตัวอย่างนี้ ระบบจะยังคงฟังก์ชันการทำงานเริ่มต้นของการเพิ่มปุ่ม "กลับ" โดยอัตโนมัติ และตอนนี้หน้าจอก็มีชื่อแล้ว

เพิ่มบุตรหลานในหน้าจอโปรไฟล์

วิดเจ็ต ProfileScreen ยังมีอาร์กิวเมนต์ที่ไม่บังคับชื่อ children ด้วย อาร์กิวเมนต์นี้จะยอมรับรายการวิดเจ็ต และวิดเจ็ตเหล่านั้นจะวางในแนวตั้งภายในวิดเจ็ต Column ที่ใช้ภายในอยู่แล้วเพื่อสร้าง ProfileScreen วิดเจ็ต Column นี้ในเมธอดการสร้าง ProfileScreen จะวางรายการย่อยที่คุณส่งไว้เหนือปุ่ม "ออกจากระบบ"

อัปเดตโค้ดใน 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(
                    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(),
          ],
        ),
      ),
    );
  }
}

โหลดแอปซ้ำ แล้วคุณจะเห็นข้อความนี้บนหน้าจอ

ebe5792b765dbf87.png

7. การลงชื่อเข้าใช้ด้วยการตรวจสอบสิทธิ์ของ Google แบบหลายแพลตฟอร์ม

นอกจากนี้ UI ของ FlutterFire ยังมีวิดเจ็ตและฟังก์ชันสําหรับการตรวจสอบสิทธิ์กับผู้ให้บริการบุคคลที่สาม เช่น Google, Twitter, Facebook, Apple และ GitHub

หากต้องการผสานรวมกับการตรวจสอบสิทธิ์ของ Google ให้ติดตั้งปลั๊กอิน firebase_ui_oauth_google อย่างเป็นทางการและไลบรารีที่เกี่ยวข้อง ซึ่งจะจัดการขั้นตอนการตรวจสอบสิทธิ์แบบดั้งเดิม ในเทอร์มินัล ให้ไปที่รูทของโปรเจ็กต์ Flutter แล้วป้อนคำสั่งต่อไปนี้

flutter pub add google_sign_in firebase_ui_oauth_google

เปิดใช้ผู้ให้บริการ Google Sign-In

ถัดไป ให้เปิดใช้ผู้ให้บริการ Google ในคอนโซล Firebase โดยทำดังนี้

  1. ไปที่หน้าจอผู้ให้บริการการลงชื่อเข้าใช้เพื่อตรวจสอบสิทธิ์ในคอนโซล
  2. คลิก "เพิ่มผู้ให้บริการใหม่" 8286fb28be94bf30.png
  3. เลือก "Google" c4e28e6f4974be7f.png
  4. สลับสวิตช์ "เปิดใช้" แล้วกด "บันทึก" e74ff86990763826.png
  5. หากโมดัลปรากฏขึ้นพร้อมข้อมูลเกี่ยวกับการดาวน์โหลดไฟล์การกําหนดค่า ให้คลิก "เสร็จสิ้น"
  6. ยืนยันว่าเพิ่มผู้ให้บริการลงชื่อเข้าใช้ด้วย Google แล้ว 5329ce0543c90d95.png

เพิ่มปุ่มลงชื่อเข้าใช้ด้วย Google

เมื่อเปิดใช้ Google Sign-In แล้ว ให้เพิ่มวิดเจ็ตที่จําเป็นในการแสดงปุ่มลงชื่อเข้าใช้ Google ที่มีสไตล์ลงในหน้าจอลงชื่อเข้าใช้ ไปที่ไฟล์ auth_gate.dart แล้วอัปเดตโค้ดเป็นข้อความต่อไปนี้

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

โค้ดใหม่เพียงอย่างเดียวคือการเพิ่ม GoogleProvider(clientId: "YOUR_WEBCLIENT_ID") ลงในการกำหนดค่าวิดเจ็ต SignInScreen

เมื่อเพิ่มแล้ว ให้โหลดแอปซ้ำ แล้วคุณจะเห็นปุ่มลงชื่อเข้าใช้ด้วย Google

aca71a46a011bfb5.png

กำหนดค่าปุ่มลงชื่อเข้าใช้

ปุ่มจะไม่ทำงานหากไม่มีการกําหนดค่าเพิ่มเติม หากคุณกำลังพัฒนาด้วย Flutter Web ขั้นตอนนี้จะเป็นขั้นตอนเดียวที่คุณต้องทำเพื่อให้การดำเนินการนี้ใช้งานได้ แพลตฟอร์มอื่นๆ จะต้องมีขั้นตอนเพิ่มเติม ซึ่งเราจะพูดถึงในอีกสักครู่

  1. ไปที่หน้าผู้ให้บริการตรวจสอบสิทธิ์ในคอนโซล Firebase
  2. คลิกผู้ให้บริการ Google 9b3a325c5eca6e49.png
  3. คลิกแผงขยาย "การกำหนดค่า SDK ของเว็บ"
  4. คัดลอกค่าจาก "รหัสไคลเอ็นต์เว็บ" 711a79f0d931c60f.png
  5. กลับไปที่เครื่องมือแก้ไขข้อความ แล้วอัปเดตอินสแตนซ์ของ GoogleProvider ในไฟล์ auth_gate.dart ด้วยการส่งรหัสนี้ไปยังพารามิเตอร์ที่มีชื่อ clientId
GoogleProvider(
   clientId: "YOUR_WEBCLIENT_ID"
)

เมื่อป้อนรหัสไคลเอ็นต์เว็บแล้ว ให้โหลดแอปอีกครั้ง เมื่อกดปุ่ม "ลงชื่อเข้าใช้ด้วย Google" หน้าต่างใหม่จะปรากฏขึ้น (หากคุณใช้เว็บ) ซึ่งจะแนะนำขั้นตอนการลงชื่อเข้าใช้ด้วย Google ในระยะแรก หน้านี้จะมีลักษณะดังนี้

14e73e3c9de704bb.png

กำหนดค่า iOS

กระบวนการกําหนดค่าเพิ่มเติมเป็นสิ่งจําเป็นเพื่อให้การทดสอบนี้ทํางานใน iOS

  1. ไปที่หน้าจอการตั้งค่าโปรเจ็กต์ในคอนโซล Firebase การ์ดจะแสดงแอป Firebase ของคุณซึ่งมีลักษณะดังนี้ fefa674acbf213cc.png
  2. เลือก iOS โปรดทราบว่าชื่อแอปพลิเคชันจะแตกต่างจากชื่อที่แสดงในภาพหน้าจอ ตรงที่ภาพหน้าจอระบุว่า "เสร็จสมบูรณ์" ของคุณจะระบุว่า "เริ่ม" หากคุณใช้โปรเจ็กต์ flutter-codelabs/firebase-auth-flutterfire-ui/start เพื่อทําตามในโค้ดแล็บนี้
  3. คลิกปุ่มที่ระบุว่า GoogleServices-Info.plist เพื่อดาวน์โหลดไฟล์กําหนดค่าที่จําเป็น f89b3192871dfbe3.png
  4. ลากไฟล์ที่ดาวน์โหลดไปยังไดเรกทอรีชื่อ /ios/Runner ในโปรเจ็กต์ Flutter
  5. เปิด Xcode โดยเรียกใช้คำสั่งเทอร์มินัลต่อไปนี้จากรูทของโปรเจ็กต์ open ios/Runner.xcworkspace
  6. คลิกขวาที่ไดเรกทอรี Runner แล้วเลือก "เพิ่มไฟล์ไปยัง Runner" 858986063a4c5201.png
  7. เลือก GoogleService-Info.plist จากเครื่องมือจัดการไฟล์
  8. กลับไปที่เครื่องมือแก้ไขข้อความ (ที่ไม่ใช่ Xcode) แล้วเพิ่มแอตทริบิวต์ CFBundleURLTypes ด้านล่างลงในไฟล์ 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. คุณต้องแทนที่ GoogleProvider.clientId ที่คุณเพิ่มในการตั้งค่าเว็บด้วยรหัสไคลเอ็นต์ที่เชื่อมโยงกับรหัสไคลเอ็นต์ Firebase iOS ขั้นแรก ให้ค้นหารหัสนี้ในไฟล์ firebase_options.dart ซึ่งเป็นส่วนหนึ่งของค่าคงที่ iOS คัดลอกค่าที่ส่งไปยัง 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. วางค่านั้นลงในตัวแปร clientId ในไฟล์ 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));
}

หากแอป Flutter ทำงานอยู่ใน iOS อยู่แล้ว คุณต้องปิดแอปนั้นโดยสมบูรณ์แล้วเรียกใช้แอปพลิเคชันอีกครั้ง หรือเรียกใช้แอปใน iOS

8. ยินดีด้วย

คุณทำ Codelab UI ของ Firebase Auth สำหรับ Flutter เสร็จแล้ว คุณดูโค้ดที่สมบูรณ์ของ Codelab นี้ได้ในไดเรกทอรี firebase-auth-flutterfire-ui/complete ใน GitHub

สิ่งที่เราได้พูดถึงไปแล้ว

  • การตั้งค่าแอป Flutter ให้ใช้ Firebase
  • การตั้งค่าโปรเจ็กต์ Firebase ในคอนโซล Firebase
  • FlutterFire CLI
  • Firebase CLI
  • การใช้การตรวจสอบสิทธิ์ Firebase
  • การใช้ FlutterFire UI เพื่อจัดการ Firebase Auth ในแอป Flutter

ขั้นตอนถัดไป

ดูข้อมูลเพิ่มเติม

Sparky พร้อมร่วมฉลองกับคุณ

2a0ad195769368b1.gif