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

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

ใน Codelab นี้ คุณจะได้ทราบวิธีเพิ่มการตรวจสอบสิทธิ์ Firebase ลงในแอป Flutter โดยใช้แพ็กเกจ UI ของ FlutterFire แพ็กเกจนี้จะช่วยให้คุณเพิ่มทั้งการตรวจสอบสิทธิ์ด้วยอีเมล/รหัสผ่านและการตรวจสอบสิทธิ์ด้วย 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

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

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

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

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

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

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

  1. ลงชื่อเข้าใช้ Firebase
  2. ในคอนโซล Firebase ให้คลิกเพิ่มโปรเจ็กต์ (หรือสร้างโปรเจ็กต์) แล้วป้อนชื่อโปรเจ็กต์ Firebase (เช่น "FlutterFire-UI-Codelab")

df42a5e3d9584b48.png

  1. คลิกตัวเลือกการสร้างโปรเจ็กต์ ยอมรับข้อกำหนดของ Firebase หากได้รับข้อความแจ้ง ข้ามการตั้งค่า Google Analytics เนื่องจากคุณจะไม่ใช้ Analytics สําหรับแอปนี้

d1fcec48bf251eaa.png

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

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

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

คุณต้องเปิดใช้การตรวจสอบสิทธิ์ Firebase โดยใช้คอนโซล 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 FlutterFire CLI ต้องใช้ CLI ซึ่งคุณจะติดตั้งในอีกไม่ช้า

การติดตั้ง CLI ทำได้หลายวิธี วิธีที่ง่ายที่สุดในการใช้ MacOS หรือ Linux คือเรียกใช้คำสั่งนี้จากเทอร์มินัล

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

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

  1. เข้าสู่ระบบ Firebase โดยใช้บัญชี Google โดยเรียกใช้คําสั่งต่อไปนี้
firebase login
  1. คำสั่งนี้จะเชื่อมต่อเครื่องภายในของคุณกับ Firebase และให้สิทธิ์คุณเข้าถึงโปรเจ็กต์ Firebase
  1. ทดสอบว่า CLI ติดตั้งอย่างถูกต้องและมีสิทธิ์เข้าถึงบัญชีโดยแสดงรายการโปรเจ็กต์ Firebase เรียกใช้คำสั่งต่อไปนี้
firebase projects:list
  1. รายการที่แสดงควรเหมือนกับโปรเจ็กต์ 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-codelab 1359cdeb83204baa.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

firebase_options.dart

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

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

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

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

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

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

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

Firebase ใช้คำว่าแอปพลิเคชันเพื่ออ้างอิงถึงบิลด์ที่เฉพาะเจาะจงสำหรับแพลตฟอร์มที่เฉพาะเจาะจงในโปรเจ็กต์ 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
flutter pub add firebase_auth
flutter pub add firebase_ui_auth

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

เริ่มต้น Firebase

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

main.dart

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


 runApp(const MyApp());
}

โค้ดนี้มีการทำงาน 2 อย่าง

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

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

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

แอป Material หรือ Cupertino

UI ของ FlutterFire กําหนดให้แอปพลิเคชันของคุณต้องรวมอยู่ใน MaterialApp หรือ CupertinoApp UI จะแสดงความแตกต่างของวิดเจ็ต Material หรือ Cupertino โดยอัตโนมัติตามตัวเลือกของคุณ สำหรับ Codelab นี้ ให้ใช้ MaterialApp ซึ่งเพิ่มไปยังแอปใน app.dart แล้ว

app.dart

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

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

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

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

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

วิดเจ็ตนั้นต้องอัปเดตให้รวมสตรีม authStateChanges

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

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

อัปเดตรหัสใน auth_gate.dart

auth_gate.dart

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

import 'home.dart';

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

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

        return const HomeScreen();
      },
    );
  }
}
  • StreamBuilder.stream กำลังส่งผ่าน FirebaseAuth.instance.authStateChanged ซึ่งเป็นสตรีมที่กล่าวถึงข้างต้น ซึ่งจะแสดงออบเจ็กต์ Firebase User หากผู้ใช้ตรวจสอบสิทธิ์แล้ว (ไม่เช่นนั้นระบบจะแสดงผล null)
  • ถัดไป โค้ดใช้ snapshot.hasData เพื่อตรวจสอบว่าค่าจากสตรีมมีออบเจ็กต์ User หรือไม่
  • หากไม่มี ระบบจะแสดงวิดเจ็ต SignInScreen กลับมา ขณะนี้หน้าจอดังกล่าวไม่สามารถดำเนินการใดๆ ได้ ระบบจะอัปเดตข้อมูลนี้ในขั้นตอนถัดไป
  • มิเช่นนั้น ระบบจะแสดงผล HomeScreen ซึ่งเป็นส่วนหลักของแอปพลิเคชันที่ผู้ใช้ที่ได้รับการตรวจสอบสิทธิ์เท่านั้นที่เข้าถึงได้

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

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

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

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

ขอย้ำอีกครั้งว่าต้องใช้โค้ดเพียงไม่กี่บรรทัด จดจำรหัสในวิดเจ็ต AuthGate ไว้

auth_gate.dart

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

import 'home.dart';

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

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

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

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

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

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

headerBuilder

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

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

auth_gate.dart

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

import 'home.dart';

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

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

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

อาร์กิวเมนต์ "HeaderBuilder" ต้องมีฟังก์ชันของประเภท HeaderBuilder ซึ่งกําหนดไว้ในแพ็กเกจ UI ของ FlutterFire

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

auth_gate.dart

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

import 'home.dart';

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

 @override
 Widget build(BuildContext context) {
   return StreamBuilder<User?>(
     stream: FirebaseAuth.instance.authStateChanges(),
     builder: (context, snapshot) {
       if (!snapshot.hasData) {
         return SignInScreen(
           providers: [
              EmailAuthProvider()
           ],
           headerBuilder: (context, constraints, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('flutterfire_300x.png'),
               ),
             );
           },
           subtitleBuilder: (context, action) {
             return Padding(
               padding: const EdgeInsets.symmetric(vertical: 8.0),
               child: action == AuthAction.signIn
                   ? const Text('Welcome to FlutterFire, please sign in!')
                   : const Text('Welcome to Flutterfire, please sign up!'),
             );
           },
         );
       }

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

โหลดแอปพลิเคชันซ้ำ ควรมีหน้าตาแบบนี้

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

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

auth_gate.dart

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

import 'home.dart';

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

 @override
 Widget build(BuildContext context) {
   return StreamBuilder<User?>(
     stream: FirebaseAuth.instance.authStateChanges(),
     builder: (context, snapshot) {
       if (!snapshot.hasData) {
         return SignInScreen(
           providers: [
             EmailAuthProvider()
           ],
           headerBuilder: (context, constraints, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('flutterfire_300x.png'),
               ),
             );
           },
           subtitleBuilder: (context, action) {
             return Padding(
               padding: const EdgeInsets.symmetric(vertical: 8.0),
               child: action == AuthAction.signIn
                   ? const Text('Welcome to FlutterFire, please sign in!')
                   : const Text('Welcome to Flutterfire, please sign up!'),
             );
           },
           footerBuilder: (context, action) {
             return const Padding(
               padding: EdgeInsets.only(top: 16),
               child: Text(
                 'By signing in, you agree to our terms and conditions.',
                 style: TextStyle(color: Colors.grey),
               ),
             );
           },
         );
       }

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

ผู้สร้างด้านข้าง

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

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

อัปเดตโค้ดใน auth_gate.dart เพื่อเพิ่มวิดเจ็ต sideBuilder

auth_gate.dart

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

import 'home.dart';

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

 @override
 Widget build(BuildContext context) {
   return StreamBuilder<User?>(
     stream: FirebaseAuth.instance.authStateChanges(),
     builder: (context, snapshot) {
       if (!snapshot.hasData) {
         return SignInScreen(
           providers: [
             EmailAuthProvider(),
           ],
           headerBuilder: (context, constraints, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('flutterfire_300x.png'),
               ),
             );
           },
           subtitleBuilder: (context, action) {
             return Padding(
               padding: const EdgeInsets.symmetric(vertical: 8.0),
               child: action == AuthAction.signIn
                   ? const Text('Welcome to FlutterFire, please sign in!')
                   : const Text('Welcome to Flutterfire, please sign up!'),
             );
           },
           footerBuilder: (context, action) {
             return const Padding(
               padding: EdgeInsets.only(top: 16),
               child: Text(
                 'By signing in, you agree to our terms and conditions.',
                 style: TextStyle(color: Colors.grey),
               ),
             );
           },
           sideBuilder: (context, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('flutterfire_300x.png'),
               ),
             );
           },
         );
       }
       return const HomeScreen();
     },
   );
 }
}

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

8dc60b4e5d7dd2d0.png

สร้างผู้ใช้

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

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

  1. ไปที่ตาราง "ผู้ใช้" ในคอนโซล Firebase
  2. คลิกที่นี่
  3. เลือก "flutterfire-ui-codelab" (หรือโปรเจ็กต์อื่นหากคุณใช้ชื่ออื่น) คุณจะเห็นตารางนี้

f038fd9a58ed60d9.png

  1. คลิกปุ่ม &quot;เพิ่มผู้ใช้&quot;

2d78390d4c5dbbfa.png

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

62ba0feb33d54add.png

  1. คลิก &quot;เพิ่มผู้ใช้&quot;

32b236b3ef94d4c7.png

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

dd43d260537f3b1a.png

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

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

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

ไปยังไฟล์ home.dart ในโปรแกรมแก้ไขข้อความ อัปเดตด้วยรหัสนี้

home.dart

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

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

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

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

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

36487fc4ab4f26a7.png

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

ออกจากระบบ

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

ก่อนอื่น ให้อัปเดตโค้ดใน home.dart

home.dart

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

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

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

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

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

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

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

home.dart

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

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

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

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

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

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

อัปเดตรหัสใน home.dart ให้แสดงโลโก้บริษัทที่นี่ ซึ่งคล้ายกับหน้าจอลงชื่อเข้าใช้

home.dart

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

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

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

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

ebe5792b765dbf87.png

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

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

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

flutter pub add google_sign_in
flutter pub add firebase_ui_oauth_google

เปิดใช้ผู้ให้บริการการลงชื่อเข้าใช้ Google

จากนั้นเปิดใช้ผู้ให้บริการ 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 และอัปเดตโค้ดเป็นดังนี้

auth_gate.dart

import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider;
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:firebase_ui_oauth_google/firebase_ui_oauth_google.dart'; // new
import 'package:flutter/material.dart';

import 'home.dart';

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

 @override
 Widget build(BuildContext context) {
   return StreamBuilder<User?>(
     stream: FirebaseAuth.instance.authStateChanges(),
     builder: (context, snapshot) {
       if (!snapshot.hasData) {
         return SignInScreen(
           providers: [
             EmailAuthProvider(),
             GoogleProvider(clientId: "YOUR_WEBCLIENT_ID"),  // new
           ],
           headerBuilder: (context, constraints, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('flutterfire_300x.png'),
               ),
             );
           },
           subtitleBuilder: (context, action) {
             return Padding(
               padding: const EdgeInsets.symmetric(vertical: 8.0),
               child: action == AuthAction.signIn
                   ? const Text('Welcome to FlutterFire, please sign in!')
                   : const Text('Welcome to Flutterfire, please sign up!'),
             );
           },
           footerBuilder: (context, action) {
             return const Padding(
               padding: EdgeInsets.only(top: 16),
               child: Text(
                 'By signing in, you agree to our terms and conditions.',
                 style: TextStyle(color: Colors.grey),
               ),
             );
           },
           sideBuilder: (context, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('flutterfire_300x.png'),
               ),
             );
           },
         );
       }

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

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

เมื่อเพิ่มแล้ว ให้โหลดแอปซ้ำและคุณจะเห็นปุ่ม Google Sign-In

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 แล้วเลือก Add Files to "Runner"858986063a4c5201.png
  7. เลือก GoogleService-Info.plist จากเครื่องมือจัดการไฟล์
  8. กลับไปที่เครื่องมือแก้ไขข้อความ (ที่ไม่ใช่ Xcode) แล้วเพิ่มแอตทริบิวต์ CFBundleURLTypes ด้านล่างลงในไฟล์ [my_project]/ios/Runner/Info.plist
<!-- Put me in the [my_project]/ios/Runner/Info.plist file -->
<!-- Google Sign-in Section -->
<key>CFBundleURLTypes</key>
<array>
        <dict>
                <key>CFBundleTypeRole</key>
                <string>Editor</string>
                <key>CFBundleURLSchemes</key>
                <array>
                        <!-- TODO Replace this value: -->
                        <!-- Copied from GoogleService-Info.plist key REVERSED_CLIENT_ID -->
                        <string>com.googleusercontent.apps.861823949799-vc35cprkp249096uujjn0vvnmcvjppkn</string>
                </array>
        </dict>
</array>
<!-- End of the Google Sign-in Section -->
  1. คุณต้องแทนที่ 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',
);
  1. วางค่านั้นลงในอาร์กิวเมนต์ GoogleProvider.clientId ในวิดเจ็ต AuthGate
import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider;
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:firebase_ui_oauth_google/firebase_ui_oauth_google.dart';
import 'package:flutter/material.dart';

import 'home.dart';


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

 @override
 Widget build(BuildContext context) {
   return StreamBuilder<User?>(
     stream: FirebaseAuth.instance.authStateChanges(),
     builder: (context, snapshot) {
       if (!snapshot.hasData) {
         return SignInScreen(
           providers: [
             EmailAuthProvider(),
             GoogleProvider(clientId: "YOUR IOS CLIENT ID"),  // replace String
           ],
           headerBuilder: (context, constraints, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('flutterfire_300x.png'),
               ),
             );
           },
           subtitleBuilder: (context, action) {
             return Padding(
               padding: const EdgeInsets.symmetric(vertical: 8.0),
               child: action == AuthAction.signIn
                   ? const Text('Welcome to FlutterFire, please sign in!')
                   : const Text('Welcome to Flutterfire, please sign up!'),
             );
           },
           footerBuilder: (context, action) {
             return const Padding(
               padding: EdgeInsets.only(top: 16),
               child: Text(
                 'By signing in, you agree to our terms and conditions.',
                 style: TextStyle(color: Colors.grey),
               ),
             );
           },
           sideBuilder: (context, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('flutterfire_300x.png'),
               ),
             );
           },
         );
       }

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

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

8. ยินดีด้วย

คุณทำ Codelab UI ของ Firebase Auth สำหรับ Flutter เสร็จแล้ว คุณดูโค้ดที่สมบูรณ์ของ Codelab นี้ได้ในไดเรกทอรี "เสร็จสมบูรณ์" บน GitHub: Flutter Codelabs

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

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

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

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

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

2a0ad195769368b1.gif