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

Flutter调用Firebase Cloud Function时参数无法传递的问题

解决Flutter调用Firebase Cloud Function参数为空的问题

问题现象

Flutter调用Firebase云函数sendNotification时,云函数日志显示已执行,但传入的fcmToken、title、body均为空,参数未成功传递到云函数中。

原代码

Flutter端代码

Future<void> sendNotification({
      required String fcmToken,
      required String title,
      required String body,
    }) async {
      final HttpsCallable callable = FirebaseFunctions.instance.httpsCallable('sendNotification');
    
      try {
        print("Sending notification with data:");
        print("FCM Token: $fcmToken");
        print("Title: $title");
        print("Body: $body");
        
        // Send data directly without nesting
        final result = await callable.call({
          'fcmToken': fcmToken,
          'title': title,
          'body': body,
        });
        
      } catch (e) {
        print('Error sending notification: $e');
      }
    }

云函数代码(index.js)

const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();

exports.sendNotification = functions.https.onCall(async (data, context) => {
  // Extract data directly (no nesting)
  const {fcmToken, title, body} = data;

  // Safe logging without circular references
  console.log("Received notification request:", {
    fcmToken: fcmToken || "not provided",
    title: title || "not provided",
    body: body || "not provided",
  });

  // Validate required fields
  if (!fcmToken) {
    throw new functions.https.HttpsError(
        "invalid-argument",
        "FCM Token is required",
    );
  }

  // Construct the message payload
  const message = {
    token: fcmToken,
    notification: {
      title: title || "New Message",
      body: body || "You have a new message",
    },
  };

  try {
    const response = await admin.messaging().send(message);
    console.log("Successfully sent message:", response);
    return {success: true, messageId: response};
  } catch (error) {
    console.error("Error sending message:", error.message);
    throw new functions.https.HttpsError(
        "internal",
        "Failed to send notification: " + error.message,
    );
  }
});

排查与解决步骤

1. 匹配云函数区域配置

如果你的云函数部署时指定了非默认区域(比如asia-east1),Flutter端必须对应指定区域,否则会调用到默认区域的旧版本/不存在的函数,导致参数丢失:

  • Flutter端修改初始化代码:
    // 指定和云函数一致的区域
    final HttpsCallable callable = FirebaseFunctions.instanceFor(region: 'asia-east1')
        .httpsCallable('sendNotification');
    
  • 云函数部署时指定区域(或在代码中声明):
    // 代码中声明区域
    exports.sendNotification = functions.region('asia-east1').https.onCall(async (data, context) => {
      // ... 原有代码
    });
    // 部署命令:firebase deploy --only functions:sendNotification --region asia-east1
    

2. 确保参数非空且类型正确

在Flutter端添加断言,确认传入的参数都是非空字符串,避免因空值导致传递失败:

assert(fcmToken.isNotEmpty, 'FCM Token不能为空');
assert(title.isNotEmpty, '标题不能为空');
assert(body.isNotEmpty, '内容不能为空');

3. 本地调试验证参数传递

使用Firebase模拟器本地运行云函数,直接查看参数是否能正确接收:

  • 启动云函数模拟器:firebase emulators:start --only functions
  • Flutter端连接模拟器:
    FirebaseFunctions.instance.useFunctionsEmulator('localhost', 5001);
    
  • 调用函数后,查看模拟器日志里的Received data,确认参数是否完整。

4. 重新部署云函数

确保你修改后的云函数已经重新部署到线上,避免运行的是旧代码:

firebase deploy --only functions

修正后的完整代码

Flutter端

Future<void> sendNotification({
  required String fcmToken,
  required String title,
  required String body,
}) async {
  // 指定云函数区域(与部署时一致)
  final HttpsCallable callable = FirebaseFunctions.instanceFor(region: 'asia-east1')
      .httpsCallable('sendNotification');

  try {
    // 验证参数非空
    assert(fcmToken.isNotEmpty, 'FCM Token不能为空');
    assert(title.isNotEmpty, '标题不能为空');
    assert(body.isNotEmpty, '内容不能为空');

    print("发送通知数据:");
    print("FCM Token: $fcmToken");
    print("标题: $title");
    print("内容: $body");
    
    final result = await callable.call({
      'fcmToken': fcmToken,
      'title': title,
      'body': body,
    });
    print("通知发送成功: ${result.data}");
    
  } catch (e) {
    print('发送通知失败: $e');
  }
}

云函数端

const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();

// 指定部署区域
exports.sendNotification = functions.region('asia-east1').https.onCall(async (data, context) => {
  const {fcmToken, title, body} = data;

  // 打印完整传入数据,方便排查
  console.log("收到的完整数据:", JSON.stringify(data));
  console.log("解析后的字段:", {
    fcmToken: fcmToken ?? "未提供",
    title: title ?? "未提供",
    body: body ?? "未提供",
  });

  if (!fcmToken) {
    throw new functions.https.HttpsError(
        "invalid-argument",
        "FCM Token是必填项",
    );
  }

  const message = {
    token: fcmToken,
    notification: {
      title: title || "新消息",
      body: body || "你有一条新消息",
    },
  };

  try {
    const response = await admin.messaging().send(message);
    console.log("消息发送成功:", response);
    return {success: true, messageId: response};
  } catch (error) {
    console.error("消息发送失败:", error);
    throw new functions.https.HttpsError(
        "internal",
        "发送通知失败: " + error.message,
    );
  }
});

内容的提问来源于stack exchange,提问作者Max

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 18:15:22