Flutter消息处理插件firebase_messaging_handler的使用

发布于 1周前 作者 h691938207 来自 Flutter

Flutter消息处理插件firebase_messaging_handler的使用

如果你对处理Firebase Cloud Messaging (FCM) 通知感到困扰,那么firebase_messaging_handler插件将会是一个不错的选择。它旨在简化FCM的通知管理过程。

主要优点

  • 统一流:所有通知点击回调(包括已终止、后台和前台状态)都通过一个易于管理的流传递。
  • 优化的后端调用:确保FCM更新到后端的回调仅触发一次,避免不必要的API请求。
  • 用户友好的权限处理:智能地请求通知权限,提供流畅的用户体验。

安装步骤

添加依赖

首先,在你的pubspec.yaml文件中添加firebase_messaging_handler包依赖。这个插件已经包含了必要的功能,所以你不需要单独添加firebase_messagingflutter_local_notifications依赖。

dependencies:
  firebase_messaging_handler: ^版本号

针对Android和iOS的具体修改

Android

android/app/src/main/AndroidManifest.xml文件的<manifest>部分添加以下权限和接收器:

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.VIBRATE" /> 

<application>
    <meta-data
        android:name="com.google.firebase.messaging.default_notification_icon"
        android:resource="@drawable/ic_notification" />
    <receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationReceiver" />
    <receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED"/>
            <action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
            <action android:name="android.intent.action.QUICKBOOT_POWERON" />
            <action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
        </intent-filter>
    </receiver>
</application>

为了启用多Dex支持,请在android/app/build.gradle中添加:

android {
defaultConfig {
    ...
    multiDexEnabled true
    ...
}
...
dependencies {
...
implementation "androidx.multidex:multidex:2.0.1"
...
}

iOS

  1. 在Apple Developer Portal注册你的应用,并为你的App ID添加推送通知功能。
  2. 确保在Xcode中正确初始化Firebase,并启用推送通知和后台模式能力。
  3. 在AppDelegate中初始化Firebase。

初始化Firebase

在应用的main函数中初始化Firebase后立即添加以下代码行:

await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
await FirebaseMessagingHandler.instance.checkInitial();

示例Demo

下面是一个完整的示例,展示了如何使用firebase_messaging_handler来初始化和处理通知:

import 'dart:developer';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging_handler/firebase_messaging_handler.dart';
import 'package:flutter/material.dart';
import 'firebase_options.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );

  await FirebaseMessagingHandler.instance.checkInitial();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Firebase Messaging Handler Example',
      home: NotificationScreen(),
    );
  }
}

class NotificationScreen extends StatefulWidget {
  const NotificationScreen({Key? key}) : super(key: key);

  @override
  State<NotificationScreen> createState() => _NotificationScreenState();
}

class _NotificationScreenState extends State<NotificationScreen> {
  late FirebaseMessagingHandler _messagingHandler;
  String? _currentPayload;
  bool _showClearButton = true;

  @override
  void initState() {
    _initFirebaseMessagingHandler();
    super.initState();
  }

  Future<void> _initFirebaseMessagingHandler() async {
    _messagingHandler = FirebaseMessagingHandler.instance;
    Stream<NotificationData?>? clickStream = await _messagingHandler.init(
      androidChannelList: [
        NotificationChannelData(
          id: 'android_notification_channel_id',
          name: 'name can be anything',
          importance: NotificationImportanceEnum.max,
          priority: NotificationPriorityEnum.high,
        ),
      ],
      androidNotificationIconPath: '@drawable/ic_notification',
      senderId: DefaultFirebaseOptions.android.messagingSenderId,
      updateTokenCallback: (final String fcmToken) async {
        log('FCM Token: $fcmToken');
        setState(() {
          _showClearButton = true;
        });
        print('FCM Token: $fcmToken');

        return Future.value(true);
      },
    );

    if (clickStream != null) {
      clickStream.listen((NotificationData? data) {
        if (data != null) {
          setState(() {
            _currentPayload =
                (data.payload.isNotEmpty ? data.payload : '').toString();
          });
        }
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Handler Example'),
        centerTitle: true,
        actions: [
          InkWell(
            onTap: () async {
              await _messagingHandler.clearToken();
              await _initFirebaseMessagingHandler();
            },
            child: const Padding(
              padding: EdgeInsets.only(right: 20, left: 10),
              child: Icon(Icons.restart_alt),
            ),
          ),
        ],
      ),
      body: Center(
        child: Text(
          'Current Payload: \n$_currentPayload',
          textAlign: TextAlign.center,
        ),
      ),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
      floatingActionButton: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          if (_showClearButton)
            Padding(
              padding: const EdgeInsets.only(right: 20),
              child: ElevatedButton(
                style: ElevatedButton.styleFrom(backgroundColor: Colors.blue),
                onPressed: () async {
                  await _messagingHandler.clearToken();
                  setState(() {
                    _showClearButton = false;
                  });
                },
                child: const Text(
                  'Clear Token',
                  style: TextStyle(color: Colors.white),
                ),
              ),
            ),
          ElevatedButton(
            style: ElevatedButton.styleFrom(backgroundColor: Colors.blue),
            onPressed: () {
              setState(() {
                _currentPayload = null;
              });
            },
            child: const Text(
              'Clear Payload',
              style: TextStyle(color: Colors.white),
            ),
          ),
        ],
      ),
    );
  }
}

这段代码展示了如何集成firebase_messaging_handler插件,初始化通知监听,并根据接收到的通知数据更新UI。


更多关于Flutter消息处理插件firebase_messaging_handler的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter消息处理插件firebase_messaging_handler的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter项目中使用firebase_messaging_handler插件进行消息处理的示例代码。这个插件允许你定义处理来自Firebase Cloud Messaging (FCM)的消息的顶级函数。

首先,你需要确保你的Flutter项目已经集成了Firebase Cloud Messaging。如果你还没有集成,你可以按照官方文档进行集成。

1. 添加依赖

pubspec.yaml文件中添加firebase_messagingfirebase_core依赖:

dependencies:
  flutter:
    sdk: flutter
  firebase_core: ^1.13.0 # 确保使用最新版本
  firebase_messaging: ^11.2.5 # 确保使用最新版本

2. 配置Firebase

确保你已经在Firebase控制台中为你的应用配置了Firebase项目,并下载了google-services.json文件,然后将其放置在android/app/目录下。对于iOS,你需要配置Runner/GoogleService-Info.plist

3. 设置Firebase应用

在你的main.dart文件中初始化Firebase应用:

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

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();

  // 配置Firebase Messaging
  FirebaseMessaging.instance.configure(
    onMessage: (RemoteMessage message) async {
      // 处理前台消息
      print('A new FCM message arrived!');
      print('Message data: ${message.data}');
    },
    onBackgroundMessage: myBackgroundMessageHandler, // 指定后台消息处理器
    onLaunch: (RemoteMessage message) async {
      // 处理从点击通知启动应用时的消息
      print('User tapped on a notification when the app was not running.');
    },
    onResume: (RemoteMessage message) async {
      // 处理用户从通知返回应用时的消息
      print('User tapped on a notification when the app was already running.');
    },
  );

  runApp(MyApp());
}

// 顶级函数,用于后台消息处理
Future<void> myBackgroundMessageHandler(RemoteMessage message) async {
  // 处理后台消息
  print('Handling a background message: ${message.data}');
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Firebase Messaging Demo'),
        ),
        body: Center(
          child: Text('Check your console for messages!'),
        ),
      ),
    );
  }
}

4. 在android/app/src/main/AndroidManifest.xml中添加权限

确保你的AndroidManifest.xml文件中包含了接收消息所需的权限:

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/>
<application
    ...>
    <receiver android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver" android:exported="true" />
    <receiver android:name="com.google.firebase.iid.FirebaseInstanceIdInternalReceiver" android:exported="false" />
    <service
        android:name="com.google.firebase.messaging.FirebaseMessagingService"
        android:exported="true">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>
    ...
</application>

5. 在iOS项目中配置Background Modes

在Xcode中,打开你的Runner项目,选择你的应用目标,转到Signing & Capabilities标签,并启用Background Modes,选择Remote Notifications。

注意事项

  • onBackgroundMessage只能处理在Dart VM未终止时(即应用仍在后台运行时)接收到的消息。如果应用被系统终止,你需要使用FCM的Data-only消息,并通过系统的通知机制唤醒应用。
  • 确保你的应用有适当的权限来处理通知,并且用户已经授予了这些权限。

这样,你就完成了在Flutter中使用firebase_messaging进行消息处理的基本设置。firebase_messaging_handler插件的核心功能实际上是通过onBackgroundMessage指定的顶级函数来实现的,而不需要额外的插件包,因为firebase_messaging已经提供了这一功能。

回到顶部