6.Firebase Messaging

Code

import 'dart:developer';

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

class MessagingService {
    static String? fcmToken; // Variable to store the FCM token

    static final MessagingService _instance = MessagingService._internal();

    factory MessagingService() => _instance;

    MessagingService._internal();

    final FirebaseMessaging _fcm = FirebaseMessaging.instance;

    Future<void> init(BuildContext context) async {
        // Requesting permission for notifications
        NotificationSettings settings = await _fcm.requestPermission(
        alert: true,
        announcement: false,
        badge: true,
        carPlay: false,
        criticalAlert: false,
        provisional: false,
        sound: true,
        );

    debugPrint(
        'User granted notifications permission: ${settings.authorizationStatus}');

    // Retrieving the FCM token
    fcmToken = await _fcm.getToken();
    log('fcmToken: $fcmToken');

    // Handling background messages using the specified handler
    FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);

    // Listening for incoming messages while the app is in the foreground
    FirebaseMessaging.onMessage.listen((RemoteMessage message) {
    debugPrint('Got a message whilst in the foreground!');
    debugPrint('Message data: ${message.notification!.title.toString()}');

    if (message.notification != null) {
        if (message.notification!.title != null &&
            message.notification!.body != null) {
        _showNotificationDialog(context, message);
        }
    }
});

    // Handling the initial message received when the app is launched from dead (killed state)
    // When the app is killed and a new notification arrives when user clicks on it
    // It gets the data to which screen to open
    _fcm.getInitialMessage().then((message) {
    if (message != null) {
        _handleNotificationClick(context, message);
    }
    });

    // Handling a notification click event when the app is in the background
    FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
    debugPrint(
        'onMessageOpenedApp: ${message.notification!.title.toString()}');
    _handleNotificationClick(context, message);
    });
}

    // Handling a notification click event by navigating to the specified screen
    void _handleNotificationClick(BuildContext context, RemoteMessage message) {
        final notificationData = message.data;

        if (notificationData.containsKey('screen')) {
        final screen = notificationData['screen'];
        Navigator.of(context).pushNamed(screen);
        }
    }

    // Show a dialog when a notification is received
    void _showNotificationDialog(BuildContext context, RemoteMessage message) {
    final notificationData = message.data;
    final screen = notificationData['screen'];

    showDialog(
    context: context,
    barrierDismissible: false,
    builder: (BuildContext context) {
        return PopScope(
        canPop: false,
        child: AlertDialog(
            title: Text(message.notification!.title!),
            content: Text(message.notification!.body!),
            actions: [
            if (notificationData.containsKey('screen'))
                TextButton(
                onPressed: () {
                    Navigator.pop(context);
                    Navigator.of(context).pushNamed(screen);
                },
                child: const Text('Open Screen'),
                ),
            TextButton(
                onPressed: () => Navigator.of(context).pop(),
                child: const Text('Dismiss'),
            ),
            ],
        ),
        );
    },
    );
    }
}

// Handler for background messages
@pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
// If you're going to use other Firebase services in the background, such as Firestore,
// make sure you call `initializeApp` before using other Firebase services.
debugPrint('Handling a background message: ${message.notification!.title}');
}

這段程式碼定義了一個名為 MessagingService 的類別,該類別用於處理 Firebase Cloud Messaging(FCM)的相關操作。FCM 是一種允許您向應用程式用戶發送通知的服務。

MessagingService 類別中,我們首先定義了一個靜態變數 fcmToken 來存儲 FCM token,以及一個私有的 FirebaseMessaging 實例 _fcm

init 方法是用來初始化 FCM 的。在這個方法中,我們首先請求用戶允許接收通知,然後獲取並存儲 FCM token。接著,我們設定了一個背景消息處理器,並開始監聽前台和背景的消息。如果收到消息,我們會顯示一個對話框,並在用戶點擊通知時導航到指定的螢幕。

_handleNotificationClick 方法是用來處理用戶點擊通知的事件。在這個方法中,我們檢查消息數據中是否包含 ‘screen’ 鍵,如果包含,我們就導航到該鍵對應的螢幕。

_showNotificationDialog 方法是用來顯示一個包含通知標題和內容的對話框。如果消息數據中包含 ‘screen’ 鍵,對話框中還會有一個 ‘Open Screen’ 按鈕,用戶點擊這個按鈕會導航到該鍵對應的螢幕。

最後,我們定義了一個背景消息處理器 _firebaseMessagingBackgroundHandler。這個處理器會在應用程式在背景運行時接收到消息時被調用。在這個處理器中,我們只是簡單地打印出了消息的標題。如果您需要在背景中使用其他 Firebase 服務,例如 Firestore,您需要在使用這些服務之前調用 initializeApp 方法。

需加入final _messagingService = MessagingService();於Stste
需修改initSate()

1
2
3
4
void initState() {
    super.initState();
    _messagingService.init(context);
}


Last update : 13 novembre 2024
Created : 13 novembre 2024

Comments

Comments