Flutter集成FCM离线推送---完整步骤

flutter中使用消息推送的方式有很多,若要实现离线推送等功能,需要集成第三方的推送,flutter官方推荐使用Firebase Cloud Messaging (FCM) 。

  • 如果App针对的是国内用户的话,不用考虑这个,FCM推送的必要条件是:有VPN,且安卓手机拥有谷歌三大件

前置

  • 需要先完成firebase配置,这一步请参考Flutter集成apple、google登陆,其中的:1. firebase项目创建、2. firebase配置章节
  • 需要拥有firebase账号,科学上网,一部有google三大件且能翻墙的安卓手机或模拟器,android studio模拟器如何上网请参考:Android虚拟机如何联网
  • 如果是iOS设备,必需使用真机进行调试,模拟器是无法收到消息的

Android接入FCM

下载依赖

pubspec.yaml

yml 复制代码
dependencies:
	# FCM推送
  firebase_messaging: ^14.7.2
  flutter_local_notifications: ^16.1.0

封装代码

lib/firebase/fcm/fcm_utils.dart

  • 具体代码可以通过调试,加深理解
  • 具体意思可以看看注释
dart 复制代码
import 'dart:convert';
import 'dart:io';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
// 这两个是封装的路由,可不用
import 'package:planx_app/router/navigator_util.dart';
import 'package:planx_app/router/routes.dart';

class FirebaseApi {
  final _firebaseMessaging = FirebaseMessaging.instance;
  final _localNotifications = FlutterLocalNotificationsPlugin();
  final _androidChannel = const AndroidNotificationChannel(
    'planx', 'PlanX Android',  // 这些信息根据自己的app定义
    description: "PlanX Android description",
    importance: Importance.defaultImportance);

  // 本地消息,处理android的前台消息
  Future initLocalNotifications() async {
    const iOS = DarwinInitializationSettings();
    // @drawable/ic_launcher是应用的图标,路径是:android/app/src/main/res/drawable/ic_launcher.png
    const android = AndroidInitializationSettings('@drawable/ic_launcher');
    const settings = InitializationSettings(android: android, iOS: iOS);
    await _localNotifications.initialize(settings,
     onDidReceiveNotificationResponse: (NotificationResponse response) {
       // android 前台消息点击
       final message = RemoteMessage.fromMap(jsonDecode(response.payload!));
       print(response);
       // 处理收到消息
       handleMessage(message);
     });
    final platform = _localNotifications.resolvePlatformSpecificImplementation<
      AndroidFlutterLocalNotificationsPlugin>();
    await platform?.createNotificationChannel(_androidChannel);
  }

  // 初始化,获取设备token
  Future<void> initNotifications() async {
    await _firebaseMessaging.requestPermission();
    final fCMToken = await _firebaseMessaging.getToken();
    print(fCMToken); // 这个就是设备token,后端通过这token给设备发送信息
    initPushNotifications();
    initLocalNotifications();
  }

  // 初始化接收消息的各种回调
  Future initPushNotifications() async {
    await _firebaseMessaging.setForegroundNotificationPresentationOptions(
      alert: true, badge: true, sound: true);

    // 打开app时,会执行该回调,获取消息(通常是程序终止时,点击消息打开app的回调)
    _firebaseMessaging.getInitialMessage().then(
      (RemoteMessage? message) {
        if (message == null) return; // 没有消息不执行后操作
        handleMessage(message);
      },
    );

    // 后台程序运行时,点击消息触发
    FirebaseMessaging.onMessageOpenedApp
      .listen((RemoteMessage message) => handleMessage(message));

    // 前台消息,android不会通知,所以需要自定义本地通知(iOS没有前台消息,iOS的前台消息和后台运行时一样的效果)
    FirebaseMessaging.onMessage.listen((message) {
      final notification = message.notification;
      if (notification == null) return;
      if (Platform.isIOS) return;
      _localNotifications.show(
        notification.hashCode,
        notification.title,
        notification.body,
        NotificationDetails(
          android: AndroidNotificationDetails(
            _androidChannel.id,
            _androidChannel.name,
            channelDescription: _androidChannel.description,
            icon: '@drawable/ic_launcher',
          )),
        payload: jsonEncode(message.toMap()));
    });

    // 后台处理,后台程序运行时收到消息,不打开app也会执行的回调
    // FirebaseMessaging.onBackgroundMessage(FirebaseApi.handleBackgroundMessage);
  }

  // 处理收到的消息,比如跳转页面之类(这里需要无context跳转,可以参考我写的flutter路由配置篇章介绍)
  void handleMessage(RemoteMessage message) {
    NavigatorUtil.push(Routes.indexPage);
  }

  // static Future<void> handleBackgroundMessage(RemoteMessage message) async {
  //   print('后台消息');
  //   // BotToast.showText(text: '后台消息:${message.toString()}');
  //   print('title:${message.notification?.title}');
  //   print('body:${message.notification?.body}');
  //   print('payload:${message.data}');
  //   print('message:${message}');
  // }
}

在main中初始化

  • 初始化写在firebase配置后面

lib/main.dart

dart 复制代码
// ...
await Firebase.initializeApp(
  options: DefaultFirebaseOptions.currentPlatform);

FcmUtils().initNotifications(); // 初始化,获取token
// ...

运行与测试项目:

  • 点击允许,获取到token

打开firebase console测试

  • 选择发送测试消息
  • 将刚刚获取到的token,粘贴到输入框--->添加设备-->点击测试
  • 成功收到消息,后面再测试:终止程序是否收到消息,或后台运行是否收到消息

iOS接入FCM

配置项目

  • 打开firebase-->项目-->iOS应用
  • 下载这个文件,替换项目中的文件:ios/Runner/GoogleService-Info.plist
  • 点击查看SDK说明-->第四步
  • 根据提示复制到项目中

ios/Runner/AppDelegate.swift

配置证书

生成证书

  • 打开钥匙串,创建证书

输入自己的邮箱--->点击继续

  • 打开开发者后台,创建证书
  • 选择服务
  • 下载证书
  • 双击下载下来的证书
  • 打开钥匙串-->鼠标右键-->导出
  • 设置密码 --> 输入登陆密码--->导出成功,文件是.p12的文件

上传证书到firebase

xcode添加能力

运行和测试项目

  • 代码与android一致,这里就不贴了
  • 需要真机运行,模拟器无法收到消息

此时可能有报错,主要是网络原因

解决方案:

  • 终端开启代理(自行查一下搜索引擎)
  • cd ./ios
  • pod install

再次运行

  • 如果没有获取到token,请检查一下手机是否联网,并且科学上网
  • 获取token,放到firebase中测试,方式与Android一样,这里不细写了

收到消息--测试成功

相关推荐
晚烛2 小时前
Flutter + OpenHarmony 导航与状态管理架构:构建可维护、可扩展、高性能的鸿蒙应用骨架
flutter·架构·harmonyos
晚烛3 小时前
实战前瞻:构建高可靠、强协同的 Flutter + OpenHarmony 智慧教育平台
javascript·flutter·html
想学后端的前端工程师4 小时前
【Flutter跨平台开发实战指南:从零到上线-web技术栈】
前端·flutter
晚烛8 小时前
实战前瞻:构建高可靠、低延迟的 Flutter + OpenHarmony 智慧交通出行平台
前端·javascript·flutter
ujainu小8 小时前
Flutter 权限管理实战手册:permission_handler 全平台适配与最佳实践
flutter
子榆.10 小时前
Flutter 与开源鸿蒙(OpenHarmony)工程化实践:CI/CD、性能监控与多端发布
flutter·开源·harmonyos
QuantumLeap丶10 小时前
《Flutter全栈开发实战指南:从零到高级》- 26 -持续集成与部署
android·flutter·ios
2501_9159184112 小时前
TCP 抓包分析在复杂网络问题中的作用,从连接和数据流层面理解系统异常行为
网络·网络协议·tcp/ip·ios·小程序·uni-app·iphone
晚烛12 小时前
实战前瞻:构建高安全、强协同的 Flutter + OpenHarmony 智慧金融移动银行平台(支持国产密码体系、生物认证与信创全栈适配)
安全·flutter·金融
子榆.13 小时前
Flutter 与开源鸿蒙(OpenHarmony)国际化与无障碍适配指南:打造真正包容的跨平台应用
flutter·华为·开源·harmonyos