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

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

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

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

Codelab นี้ถือว่าคุณมีประสบการณ์การใช้งาน 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

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

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

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

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

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

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

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

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

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

แอปที่คุณสร้างใช้การตรวจสอบสิทธิ์ Firebase เพื่ออนุญาตให้ผู้ใช้ลงชื่อเข้าใช้แอปของคุณ และยังอนุญาตให้ผู้ใช้ใหม่ลงทะเบียนจากแอปพลิเคชัน 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 ในเครื่องของคุณ ซึ่งมีโค้ดสำหรับชุดของ Codelab โค้ดสำหรับโค้ดแล็บนี้อยู่ในไดเรกทอรีย่อย 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. เลือกแพลตฟอร์มที่ต้องการใช้ ใน Codelab นี้มีขั้นตอนในการกําหนดค่าการตรวจสอบสิทธิ์ 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 มีแอปพลิเคชันหลายรายการ ได้แก่ แอปพลิเคชันสำหรับ Android, iOS, macOS และเว็บ

เมธอด DefaultFirebaseOptions.currentPlatform ใช้การแจงนับ TargetPlatform ที่ 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 เริ่มต้น

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

Material หรือแอป Cupertino

FlutterFire UI กำหนดให้แอปพลิเคชันของคุณต้องอยู่ใน 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),
    );
  }
}

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

คุณต้องพิจารณาก่อนว่าผู้ใช้ได้รับการตรวจสอบสิทธิ์หรือไม่ก่อนที่จะแสดงหน้าจอลงชื่อเข้าใช้ วิธีที่พบบ่อยที่สุดในการตรวจสอบคือการฟัง FirebaseAuthauthStateChanges โดยใช้ปลั๊กอิน 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 เป็นวิดเจ็ตที่มาจากแพ็กเกจ FlutterFire UI ซึ่งจะเป็นหัวใจสำคัญของขั้นตอนถัดไปในโค้ดแล็บนี้ เมื่อเรียกใช้แอปในตอนนี้ คุณควรเห็นหน้าจอลงชื่อเข้าใช้ที่ว่างเปล่า

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 ยอมรับ Callback และครั้งนี้อาร์กิวเมนต์ของ Callback นั้นคือ BuildContext และ double shrinkOffset วิดเจ็ตที่ sideBuilder แสดงจะปรากฏทางด้านซ้ายของแบบฟอร์มลงชื่อเข้าใช้ และจะปรากฏเฉพาะบนหน้าจอแบบกว้างเท่านั้น ซึ่งหมายความว่าวิดเจ็ตจะแสดงในเดสก์ท็อปและเว็บแอปเท่านั้น

ภายใน FlutterFire UI จะใช้เบรกพอยต์เพื่อพิจารณาว่าจะแสดงเนื้อหาส่วนหัว (ในหน้าจอสูง เช่น อุปกรณ์เคลื่อนที่) หรือเนื้อหาด้านข้าง (ในหน้าจอกว้าง เช่น เดสก์ท็อปหรือเว็บ) กล่าวคือ หากหน้าจอมีความกว้างมากกว่า 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 ซึ่งส่งคืนจากแฮนเดิล MaterialPageRoute.builder

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

36487fc4ab4f26a7.png

นี่คือ UI มาตรฐานที่หน้า FlutterFire UI มีให้ ปุ่มและช่องข้อความทั้งหมดเชื่อมต่อกับ Firebase Auth และใช้งานได้ทันที เช่น คุณสามารถป้อนชื่อลงในช่องข้อความ "ชื่อ" แล้ว FlutterFire UI จะเรียกใช้เมธอด 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 เป็น null

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

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

หน้าโปรไฟล์ปรับแต่งได้เช่นเดียวกับหน้าจอลงชื่อเข้าใช้ ประการแรก หน้าปัจจุบันของเราไม่มีวิธีนำทางกลับไปที่หน้าแรกเมื่อผู้ใช้อยู่ในหน้าโปรไฟล์ แก้ไขปัญหานี้โดยให้วิดเจ็ต ProfileScreen มี AppBar

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 build จะวางองค์ประกอบย่อยที่คุณส่งไว้เหนือปุ่ม "ออกจากระบบ"

อัปเดตรหัสใน 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 แบบหลายแพลตฟอร์ม

นอกจากนี้ FlutterFire UI ยังมีวิดเจ็ตและฟังก์ชันการทำงานสำหรับการตรวจสอบสิทธิ์กับผู้ให้บริการบุคคลที่สาม เช่น 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 แล้ว ให้เพิ่มวิดเจ็ตที่จำเป็นเพื่อแสดงปุ่มลงชื่อเข้าใช้ด้วย 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. คลิกแผงการขยาย "การกำหนดค่า Web SDK"
  4. คัดลอกค่าจาก "รหัสไคลเอ็นต์เว็บ" 711a79f0d931c60f.png
  5. กลับไปที่โปรแกรมแก้ไขข้อความ แล้วอัปเดตอินสแตนซ์ของ GoogleProvider ในไฟล์ auth_gate.dart โดยส่งรหัสนี้ไปยังพารามิเตอร์ที่ชื่อ clientId
GoogleProvider(
   clientId: "YOUR_WEBCLIENT_ID"
)

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

14e73e3c9de704bb.png

กำหนดค่า iOS

หากต้องการให้ฟีเจอร์นี้ทำงานบน iOS ได้ คุณต้องดำเนินการกำหนดค่าเพิ่มเติม

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

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

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

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

  • ดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้ Firestore และการตรวจสอบสิทธิ์ใน Flutter ได้ที่ Get to know Firebase for Flutter Codelab
  • สำรวจเครื่องมืออื่นๆ ของ Firebase สำหรับสร้างแอปพลิเคชัน Flutter

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

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

2a0ad195769368b1.gif