iT邦幫忙

2023 iThome 鐵人賽

DAY 12
1
Mobile Development

Flutter 從零到實戰 - 30 天の學習筆記系列 第 12

[Day 12] 實戰新聞 APP - 設定 Firebase Auth 與串接

  • 分享至 

  • xImage
  •  

昨天我們已經將登入與註冊頁面寫完拉,今天我們將要來實際的串接功能。我們會使用 Firebase 這個由 Google 所提供的強大服務來進行實作。

https://ithelp.ithome.com.tw/upload/images/20230927/20135082nTy6AZF2To.png

Firebase 是 2011 年創立,並於 2014 年由 Google 收購的熱門應用程式後端服務平台。它提供了一系列的工具與服務,包括了Firestore、Firebase Auth、監控分析、資料庫、通知與 ML Kit 等等。

我們在此次專案中實作登入的功能,便是需要透過 Firebase Auth 的助力來完成。因此我們需要進行幾個設定。

設定 Firebase Auth

官網:https://firebase.google.com/

您可以直接透過 Google 帳戶進行登入,一但登入之後便會看到以下畫面

https://ithelp.ithome.com.tw/upload/images/20230927/20135082ywPw2rcZsR.png

點選「建立專案」來開始專案的設定。接下來為您的專案取名,並點選下一步到底即可建立專案。這邊我將我的專案取名做 micro-news-app ,等待建立好後即可從主控台中進入專案頁面,畫面如下。

https://ithelp.ithome.com.tw/upload/images/20230927/201350821Ys4VW4JOK.png

請點選「Authentication」的頁面中的「開始使用」,便會進入請你新增第一種登入方式。

請選擇「電子郵件/密碼」,開啟開關後儲存,您就已經完成 Firebase Auth 的設定囉。

https://ithelp.ithome.com.tw/upload/images/20230927/20135082CBYOZXeXbm.png

安裝 Firebase CLI

Firebase CLI (command line interface)是 Firebase 提供的命令列介面,透過指令來進行 firebase 的操作。

由於前一章節有帶大家安裝 nodejs ,因此我們可以很方面的透過 npm 來將套件全域安裝至電腦中,請打開終端機並輸入以下指令

# -g 表示 global,安裝的目標從原先的當前目錄底下改為至整台裝置
npm install -g firebase-tools

# 待安裝完畢後進行登入
firebase login

# 列出該帳號底下的專案列表
firebase projects:list

此時您應該可以在顯示的專案列表中看到方才透過網頁在 firebase 所建立 news app 專案。

安裝 FlutterFire

請先開啟上一章節所建立的 News App 專案資料夾,並開啟終端機。

FlutterFire CLI 是 Firebase 官方提供給 Flutter 開發使用的插件工具

# 下載 flutterfire cli
dart pub global activate flutterfire_cli

# 針對 app 進行配置
flutterfire configure

你會看到 flutterfire 去偵測並要你選擇專案的支援平台,可自行選擇。(使用上下鍵移動游標,空白鍵進行選擇/刪除),完成後按下 Enter 便會開始幫你產生這些平台的配置檔,最後會問你是否正確並選擇 Yes 就大功告成拉。

完成後 Firebase 會自動在你的 Flutter 專案的 lib 資料夾底下產生 firebase_options.dart 的檔案,裡面會紀錄你的 APP 對應至這些平台的各種資訊。

https://ithelp.ithome.com.tw/upload/images/20230927/20135082v4SNb56aEH.png

下載套件至 Flutter 專案

完成上述的操作後,您還需要將 firebase 提供的數個套件載入至我們的專案中。打開終端機並輸入以下指令

# flutter 下載第三方套件的方式
# flutter pub add [名稱]
# 下載 firebase_core
flutter pub add firebase_core
# 下載 firebase_auth
flutter pub add firebase_auth

此時就會開始將 firebase_authfirebase_core 以及其相依的套件一併的下載至你的 Flutter 專案中。你可以打開專案目錄底下的 pubspec.yml 其中的 dependencies 便會記錄該專案使用了哪些套件。(版本號碼跟我的不一樣沒關係,預設會下載最新版本)

# --------- 以上省略 ---------
dependencies:
  flutter:
    sdk: flutter

  cupertino_icons: ^1.0.2
  firebase_core: ^2.16.0
  firebase_auth: ^4.10.0
# --------- 以下省略 ---------

如此便完成了所有 firebase auth 的設定。

專案再一次~啟動

請打開 main.dart 並且再次把所有的內容皆移除並替換成以下程式碼。

import 'package:flutter/cupertino.dart';

void main() {
  // 確保 widgets 環境已經初始化
  WidgetsFlutterBinding.ensureInitialized();
  // 根據當前平台的配置初始化 firebase
  await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
  runApp(const MyApp());
}

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

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return const CupertinoApp(
        debugShowCheckedModeBanner: false, home: LoginScreen());
  }
}

這裡介紹一個 VS Code 插件支援自動修正的功能,有時當我們使用了未引用的套件或變數時,使用此功能便可以自動幫我們從此專案中找到正確的內容進行引用。

https://i.imgur.com/jOov55q.gif

先執行看看

如果你開發的是 iOS 應用程式,可能會遇到這個錯誤,以下提供解決方法:

https://ithelp.ithome.com.tw/upload/images/20230927/20135082T7E6eN17A4.png

  1. 進入 ios 資料夾中,如果有 Podfile.lock 檔案請刪除
  2. 執行指令 pod repo remove trunk
  3. 執行指令 sudo arch -x86_64 gem install ffi
  4. 執行指令 arch -x86_64 pod install --repo-update
  5. 執行指令 flutter run

希望你的專案可以因此執行起來QQ 當初看到這個錯誤我也是傻眼... 怎麼會預設幾乎啥都沒動過的竟然不能跑~

登入功能實作

首先請先至 firebase console 的 Authentication 地方,在 Users 頁面點選「添加用戶」。我們至少需要一個使用者資訊才有辦法運用這組帳號密碼進行登入。

https://ithelp.ithome.com.tw/upload/images/20230927/20135082ijGgp9mDWl.png

完成後,就可以回到程式碼中,並請開啟 login_screen.dart 檔案。由於登入的動作,是透過點擊登入按鈕才會觸發的,因此我們將實作寫在「登入」這個 CupertinoButtononPressed 參數中。

Firebase 有提供一個函式名叫 signInWithEmailAndPassword 並夾帶信箱、密碼便可以進行驗證,我們將使用此函式來實作。

onPressed: () async {
  try {
    UserCredential user = await FirebaseAuth.instance
        .signInWithEmailAndPassword(
            // 夾帶 email 文字框輸入文字
            email: _emailController.text,
            // 夾帶 password 文字框輸入文字
            password: _passwordController.text);
    print(user);
  } on FirebaseAuthException catch (e) {
    print(e.code);
  }
}

請將上面程式碼加至程式碼當中,並分別測試輸入正確資訊、輸入錯誤信箱格式、輸入錯誤信箱或密碼,各自得到的結果。

  • 輸入正確資訊:印出使用者帳號的相關資訊
  • 輸入錯誤信箱格式:印出「invalid-email」
  • 輸入錯誤信箱或密碼:印出「INVALID_LOGIN_CREDENTIALS」

如果是正確的帳號資訊,我們就能成功經過驗證。若輸入的資訊錯誤,我們應該要給予相應的錯誤提示。

使用 CupertinoAlertDialog

Alert dialog 通常使用於通知使用者某些需要確認的情況,例如當使用者輸入錯誤的帳號資訊時,我們便可以跳出通知告訴使用者「密碼錯誤」等等之類的訊息。

在 Cupertino 中定義了 CupertinoAlertDialog 讓我們完成這樣的行為,以下為使用範例

void _showAlertDialog(BuildContext context, String title, String message) {
  showCupertinoModalPopup<void>(
    context: context,
    builder: (BuildContext context) => CupertinoAlertDialog(
      // 欲顯示的標題
      title: Text(title),
      // 欲顯示的訊息
      content: Text(message),
      actions: <CupertinoDialogAction>[
        CupertinoDialogAction(
          isDefaultAction: true,
          onPressed: () {
            // 關閉此通知
            Navigator.pop(context);
          },
          child: const Text('關閉'),
        ),
      ],
    ),
  );
}

我們額外傳入了 titlemessage 來讓通知可以提供更明確的訊息。

因此我們可以將 onPressed 改寫成以下樣式

onPressed: () async {
  try {
    UserCredential user = await FirebaseAuth.instance
        .signInWithEmailAndPassword(
            // 夾帶 email 文字框輸入文字
            email: _emailController.text,
            // 夾帶 password 文字框輸入文字
            password: _passwordController.text);
    print('登入成功');
  } on FirebaseAuthException catch (e) {
    if (e.code == 'invalid-email') {
      _showAlertDialog(context, '登入失敗', '電子郵件格式錯誤');
    } else if (e.code == 'INVALID_LOGIN_CREDENTIALS') {
      _showAlertDialog(context, '登入失敗', '帳號或密碼錯誤');
    } else {
      _showAlertDialog(context, '登入失敗', '發生錯誤');
    }
  }
},

如此一來,一旦有錯誤便可以彈出錯誤訊息,與通知使用者當前狀態拉。

Navigator

昨天我們的程式碼告訴各位透過抽換 CupertinoApphome 參數來達到獨立的頁面開發,但是其實實際流程應為若使用者未有帳號時,會點選登入頁面中的「註冊帳號」按鈕,頁面便會導向註冊頁面。

我們會透過 Navigator 來完成,在應用程式中每個頁面都是一個 Route,而在頁面之中進行切換就是透過 Navigator 來完成。我們可以用一個 stack 來進行示意路由的狀態。

舉我們當前的應用程式為例:

https://ithelp.ithome.com.tw/upload/images/20230927/20135082oga25xXZMe.png

  1. 顯示的畫面永遠是 Stack 中堆疊在最上層的 route ,初始為「登入頁面」。
  2. 點擊「註冊按鈕」後觸發 push 的動作將「註冊頁面」堆疊置原先的頁面之上,並且保持永遠顯示最上層的原則。
  3. 點擊「前往登入」按鈕,則 pop stack 將最上層的 route 移除,回到原先的登入頁面。

現在我們可以來實作拉,因為事件觸發是點擊按鈕之後,所以請找到 login_screen.dart 註冊帳號按鈕的 onPressed 參數,並參考以下程式碼:

onPressed: () {
  // 以 CupertinoPageRoute 是表示以 Cupertino 的風格進行頁面跳轉
  // push 註冊頁面
  Navigator.push(context, CupertinoPageRoute(
    builder: (context) {
      return const RegisterScreen();
    },
  ));
},

此外也打開 register_screen.dart 的「前往登入」按鈕 onPressed 參數,並參考以下程式碼:

onPressed: () {
  Navigator.pop(context);
},

如此便可以成功的在兩頁面中進行切換拉!!有沒有越來越有樣子了呢

https://i.imgur.com/PJbUGzG.gif

串接註冊功能

登入功能串的差不多拉~接下來我們要來把註冊的功能也一起完成,請開啟 register_screen.dart 檔案。

Firebase 有提供一個函式名叫 createUserWithEmailAndPassword 並夾帶信箱、密碼便可以進行註冊,我們將使用此函式來實作。

onPressed: () async {
  try {
    UserCredential newUser = await FirebaseAuth.instance
        .createUserWithEmailAndPassword(
      email: _emailController.text,
      password: _passwordController.text,
    );
    print(newUser);
  } on FirebaseAuthException catch (e) {
    print(e.code);
  }
},

請將上面程式碼加至程式碼當中,並同樣的分別測試輸入新使用者資訊、已存在使用者資訊、註冊一個使用者並將密碼設為 12345、錯誤信箱格式的結果

  • 輸入新使用者資訊:印出新使用者帳號的相關資訊
  • 輸入已存在使用者:印出「email-already-in-use」
  • 密碼設為 12345:印出「weak-password」
  • 錯誤信箱格式:印出 「invalid-email」

同樣的,如果是正確的帳號資訊,我們就能成功經過驗證。若輸入的資訊錯誤,我們應該要給予相應的錯誤提示。此時我們可以將上面介紹的 _showAlertDialog 複製至此檔案,同樣也用於顯示資訊給使用者。

在註冊的頁面上多了一個輸入框用於二次驗證輸入的密碼內容,按照註冊流程應該要先檢查是否「密碼」與「驗證密碼」的輸入內容是否相同,相同才讓 firebase 去進行註冊;否則跳出「輸入密碼不符」的錯誤訊息,因此同樣我們可以將上述程式碼進行改寫。

onPressed: () async {
  if (_passwordController.text != _confirmPasswordController.text) {
    _showAlertDialog(context, '密碼不一致', '請檢查您的密碼與驗證密碼欄位內容是否正確');
    return;
  }
  try {
    UserCredential newUser = await FirebaseAuth.instance.createUserWithEmailAndPassword(
      email: _emailController.text,
      password: _passwordController.text,
    );
    print(newUser);
  } on FirebaseAuthException catch (e) {
    if (e.code == 'weak-password') {
      _showAlertDialog(context, '密碼強度不足', '為了您帳號的安全性,請使用強度較高的密碼');
    } else if (e.code == 'email-already-in-use') {
      _showAlertDialog(context, '信箱已被註冊', '該信箱已被註冊,您可以使用該信箱登入或使用其他信箱進行註冊');
    } else if (e.code == 'invalid-email') {
      _showAlertDialog(context, '信箱格式錯誤', '請檢查您的信箱格式是否正確');
    } else {
      _showAlertDialog(context, '註冊失敗', '請稍後再試');
    }
  }
},

這麼一來,註冊的流程也算是正式完成拉。請試著註冊一組帳號,成功後便可以至 firebase console 上檢視 users 是否有方才建立的帳號資訊。

今日總結

今天我們介紹:

  1. 什麼是 Firebase,並且建立了一個 firebase 專案
  2. 透過 flutterfire 將 firebase 引用至我們專案當中
  3. 實作登入流程與錯誤處理
  4. 學會如何頁面之間的切換
  5. 實作註冊流程與錯誤處理

經過今天的介紹,讓我們的應用程式已經有了基礎的帳號註冊與登入功能。不過這部分還沒完全結束!因為普遍的應用程式都有支援第三方登入,我們不能捨棄這個超級方便的功能呀~

因此明天的內容會延續今天的進度,串接 Google 登入以及實作忘記密碼的頁面喔!各位我們明天繼續囉~

今天的參考程式碼:https://github.com/ChungHanLin/micro_news_tutorial/tree/day12/micro_news_app


上一篇
[Day 11] 實戰新聞 APP - 登入/註冊畫面
下一篇
[Day 13] 實戰新聞 APP - Google Sign In 實作
系列文
Flutter 從零到實戰 - 30 天の學習筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言