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一样,这里不细写了

收到消息--测试成功

相关推荐
Forever不止如此1 小时前
【CustomPainter】绘制圆环
flutter·custompainter·圆环
wills7772 小时前
Flutter Error: Type ‘UnmodifiableUint8ListView‘ not found
flutter
逻辑克3 小时前
使用 MultipeerConnectivity 在 iOS 中实现近场无线数据传输
ios
编程乐学6 小时前
基于Android Studio 蜜雪冰城(奶茶饮品点餐)—原创
android·gitee·android studio·大作业·安卓课设·奶茶点餐
IH_LZH7 小时前
Broadcast:Android中实现组件及进程间通信
android·java·android studio·broadcast
dnekmihfbnmv8 小时前
好用的电容笔有哪些推荐一下?年度最值得推荐五款电容笔分享!
ios·电脑·ipad·平板
技术无疆18 小时前
快速开发与维护:探索 AndroidAnnotations
android·java·android studio·android-studio·androidx·代码注入
AiFlutter1 天前
Flutter之Package教程
flutter
Magnetic_h1 天前
【iOS】单例模式
笔记·学习·ui·ios·单例模式·objective-c