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
相关产品推荐
相关产品推荐

