Cloud Function发送的iOS通知未收到,Firebase Console测试正常
iOS设备无法接收Cloud Function发送的FCM通知
已完成的验证步骤
- Xcode中已启用推送通知权限,同时开启后台模式:Background fetch、Remote notifications、Background processing
- Firebase项目的Cloud Messaging模块已上传APNs Auth Key,且Firebase Cloud Messaging API (V1)处于启用状态
- Cloud Function已绑定Firebase项目,使用Firebase Admin SDK Service Agent完成配置
核心问题
Cloud Function可正常响应recent_messages集合的文档创建/更新操作,日志返回成功发送的响应(例如textPayload: "Successfully sent message: projects/{Project_ID}/messages/1701549315603249"),但iOS设备完全收不到通知。但使用Firebase Console向同一FCM令牌发送通知时,设备能正常接收并显示。
Xcode中didReceiveRemoteNotification方法设置的断点仅在Firebase Console发送通知时触发,Cloud Function发送时无任何触发迹象。Cloud Function日志仅显示成功信息,目前找不到下一步排查方向。
Cloud Function代码(尝试过两种发送方式)
const gaxios = require('gaxios'); const admin = require('firebase-admin'); const functions = require('firebase-functions'); admin.initializeApp(functions.config().firebase); let db = admin.firestore(); const { GoogleAuth } = require('google-auth-library'); async function getAccessToken() { const auth = new GoogleAuth({ keyFile: './service-account-key.json', scopes: 'https://www.googleapis.com/auth/firebase.messaging', }); const client = await auth.getClient(); const accessTokenResponse = await client.getAccessToken(); return accessTokenResponse.token; } // onCreate trigger for new messages exports.onCreateMessage = functions.firestore.document('recent_messages/{messageId}').onCreate( (snapshot) => { handleNotification(snapshot); return handleNotificationPost(snapshot); } ); // onUpdate trigger for message updates exports.onUpdateMessage = functions.firestore.document('recent_messages/{messageId}').onUpdate( (change) => { handleNotification(change.after); return handleNotificationPost(change.after); } ); // Function to handle sending notifications async function handleNotification(snapshot) { // Fetching the recent message data const messageData = snapshot.data(); const gid = messageData.gid; const toId = messageData.toId; const fromId = messageData.fromId; const type = messageData.type; const text = messageData.text; // Query the 'games' collection const gameRef = db.collection('games').doc(gid); const gameDoc = await gameRef.get(); const gameData = gameDoc.data(); const gameUsers = gameData.gameUsers || []; const user = gameUsers.find(u => u.fid === toId); if (!user) { console.log('User not found'); return null; } // Send notification if (user.deviceToken) { try { // Notification details const payload = { notification: { title: "Test Title", body: "Test body" }, apns: { payload: { aps: { alert: { title: "Test Title", body: "Test body" }, } } }, token: user.deviceToken }; console.log("FCM Token:", user.deviceToken) admin.messaging().send(payload) .then((response) => { console.log('Successfully sent message:', response); }).catch((error) => { console.log('Error sending message:', error); }); console.log('Notification sent to:', toId); } catch (error) { console.error('Error sending notification:', error); } } else { console.log('No device token found for user:', toId); } } // Function to handle sending notifications async function handleNotificationPost(snapshot) { // Fetching the recent message data const messageData = snapshot.data(); const gid = messageData.gid; const toId = messageData.toId; const fromId = messageData.fromId; const type = messageData.type; const text = messageData.text; // Query the 'games' collection const gameRef = db.collection('games').doc(gid); const gameDoc = await gameRef.get(); const gameData = gameDoc.data(); const gameUsers = gameData.gameUsers || []; const user = gameUsers.find(u => u.fid === toId); if (!user) { console.log('User not found'); return null; } // Send notification if (user.deviceToken) { try { const accessToken = await getAccessToken(); // Notification details const payload = { "message": { "token": user.deviceToken, "notification": { "title": "New message from ${fromId}", "body": type === "text" ? (text.length <= 100 ? text : text.substring(0, 97) + "...") : "You received an image", }, } }; console.log("FCM Token:", user.deviceToken) console.log('Access Token:', accessToken); const url = 'https://fcm.googleapis.com/v1/projects/{ProjectID}/messages:send'; // Sending POST request const response = await gaxios.request({ url: 'https://fcm.googleapis.com/v1/projects/{ProjectID}/messages:send', method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${accessToken}` }, data: payload }); console.log('Notification sent to:', toId); console.log('Response from POST:', response.data); } catch (error) { console.error('Error sending notification:', error); } } else { console.log('No device token found for user:', toId); } }
Xcode相关代码
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { if let messageID = userInfo[gcmMessageIDKey] { print("Message ID: \(messageID)") } // Print full message. print("Did receive remote notification: \(userInfo)") completionHandler(UIBackgroundFetchResult.newData) }
内容的提问来源于stack exchange,提问作者James Bradley
相关产品推荐
相关产品推荐

