You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter iOS端无法接收Node.js Firebase Admin SDK推送通知问题

Flutter iOS端FCM推送异常排查与解决

问题背景

开发的Flutter客户端通过Node.js云函数调用Firebase Admin SDK推送通知,Android端(前台、后台、静默通知)接收正常,但iOS端前后台均无法接收。推送使用的是Flutter FirebaseMessaging获取并存储在Firestore中的FCM Token,每个用户最多保留5个Token适配多设备登录场景。

云函数推送代码

//Attempt to send an identic message (title, body) to every token in fcmTokens
//fcmTokens is an array of objects and assume that the variable token indeed holds the valid token for each iteration
function sendNotifications(fcmTokens, userId, payloadData, title, body, silent = false) {
  // Customize the notification payload
  try {
    Object.entries(fcmTokens).forEach(async (entry) => {
      const key = entry[0];
      const token = entry[1];
      console.log(`Key: ${key} - Token: ${token}`);

      notificationPayload = {
        token: token,
      };
      if (payloadData) {
        notificationPayload.data = payloadData;
      }

      // Add notification body if it's not a silent notification
      if (!silent) {
        notificationPayload.notification = {
          title: title,
          body: body,
          content_available: true
        };
      } else {
        console.log("Silent notification.");
      }
      const messaging = admin.messaging();
      
      await messaging.send(notificationPayload)
      .then((response) => {
        // Response is a message ID string.
        //console.log(`Notificationpayload: ${JSON.stringify(notificationPayload)}`);
        console.log('Successfully sent message:', response);
      })
      .catch(async (error) => {
        console.error('Error sending message:', error);
      });
    });
  } catch (error) {
    console.error(`Error building notification payload: ${error}`);
    return null; // Handle the error as needed
  }
}

已确认信息

  • FCM Token已成功存储到Firestore;
  • 手动在Firebase控制台使用该Token测试,可成功推送到iOS设备。

问题更新

更新1:iOS初始化报错

iOS真机调试时出现以下异常:

[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled
Exception: Invalid argument(s): iOS settings must be set when
targeting iOS platform.
#0 FlutterLocalNotificationsPlugin.initialize (package:flutter_local_notifications/src/flutter_local_notifications_plugin.dart:151:9)
#1 NotificationControllerFree._configureLocalNotifications (package:resistentes/notification_controller_free.dart:48:44)
#2 NotificationControllerFree.initializeRemoteNotifications (package:resistentes/notification_controller_free.dart:41:11)

已计划更新Flutter Local Notifications的初始化配置。

更新2:iOS接收异常

添加iOS专属本地通知初始化配置后,iOS端可接收通知但存在以下异常:

  • 应用前台时:调试控制台显示通知已被处理,但无通知弹窗;
  • 应用后台时:通知可弹窗显示,但调试控制台无处理日志;
  • 应用初始化时控制台输出:

[FirebaseMessaging][I-FCM001000] FIRMessaging Remote Notifications
proxy enabled, will swizzle remote notification receiver handlers. If
you'd prefer to manually integrate Firebase Messaging, add
"FirebaseAppDelegateProxyEnabled" to your Info.plist, and set it to
NO. Follow the instructions at:
https://firebase.google.com/docs/cloud-messaging/ios/client#method_swizzling_in_firebase_messaging
to ensure proper integration.

解决方案

1. 前台无弹窗问题处理

iOS默认不会在前台自动弹出FCM通知,需通过FlutterLocalNotificationsPlugin手动展示。在FirebaseMessaging的onMessage回调中调用本地通知的show方法:

FirebaseMessaging.onMessage.listen((RemoteMessage message) {
  RemoteNotification? notification = message.notification;
  if (notification != null) {
    flutterLocalNotificationsPlugin.show(
      notification.hashCode,
      notification.title,
      notification.body,
      const NotificationDetails(
        iOS: IOSNotificationDetails(),
      ),
    );
  }
});

2. 后台无处理日志问题处理

iOS后台状态下,普通通知由系统接管展示,不会触发onMessage回调:

  • 用户点击通知时,会触发onMessageOpenedApp回调;
  • 静默通知或纯数据消息,需配置onBackgroundMessage顶级回调(不能是类方法)来处理:
// 后台消息处理顶级函数
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  await Firebase.initializeApp();
  print('处理后台消息: ${message.messageId}');
  // 这里添加后台消息的业务逻辑
}

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  // 注册后台消息处理
  FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
  runApp(MyApp());
}

3. Firebase AppDelegate Swizzling提示处理

该提示为可选配置:

  • 若需手动控制通知处理逻辑,可在iOS项目的Info.plist中添加FirebaseAppDelegateProxyEnabled并设置为NO,同时在原生AppDelegate中实现通知相关方法并转递给Flutter;
  • 若当前功能满足需求,可忽略该提示,保留默认的Swizzling即可。

4. 云函数Payload优化

调整推送Payload适配iOS规则:

  • 普通通知移除content_available字段(该字段仅用于静默通知);
  • 静默通知确保data字段包含content_available: true,且不包含notification字段;
function sendNotifications(fcmTokens, userId, payloadData, title, body, silent = false) {
  try {
    Object.entries(fcmTokens).forEach(async (entry) => {
      const token = entry[1];
      const notificationPayload = { token: token };

      if (payloadData) {
        notificationPayload.data = { ...payloadData };
      }

      if (!silent) {
        // 普通通知配置
        notificationPayload.notification = { title, body };
        // 若需后台更新数据,在data中添加content_available
        if (notificationPayload.data) {
          notificationPayload.data.content_available = true;
        }
      } else {
        // 静默通知配置
        notificationPayload.data = {
          ...notificationPayload.data,
          content_available: true
        };
        console.log("Silent notification.");
      }

      const messaging = admin.messaging();
      await messaging.send(notificationPayload)
        .then((response) => console.log('推送成功:', response))
        .catch((error) => console.error('推送失败:', error));
    });
  } catch (error) {
    console.error('构建Payload失败:', error);
    return null;
  }
}

内容的提问来源于stack exchange,提问作者Aleix Rué

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 04:19:53