Ionic3集成FCM推送:如何为通知添加操作按钮?
解决Ionic3 FCM推送添加操作按钮的报错问题
我看你现在在Ionic3项目中使用FCM插件实现推送通知,想要给推送添加三个操作按钮,但尝试添加按钮时Firebase函数控制台会报错,目前不带按钮的推送可以正常运行。下面我来帮你排查并解决这个问题:
问题根源分析
你之前注释掉的操作按钮配置存在两个核心问题:
- Payload结构错误:FCM的通知操作按钮不能直接放在
notification字段下,对于Ionic的FCM插件来说,需要将操作按钮配置放在data字段中,同时要遵循插件要求的格式。 - 平台兼容性配置缺失:Android和iOS对于推送操作按钮的配置细节有区别,需要兼顾两者的格式要求,并且要确保数据格式符合FCM的传输规范。
修改后的Firebase云函数代码
下面是调整后的sendChatNotification函数代码,重点修正了payload的结构,正确配置了操作按钮:
exports.sendChatNotification = functions.database.ref('/app/chat/user/{clientUid}/{trainerUid}/{pushId}').onWrite((event) => { const clientUid = event.params.clientUid; const trainerUid = event.params.trainerUid; const MessageId = event.params.pushId; const Message = event.data.val(); console.log('newly pushed message -> ', Message) // 如果是删除操作则退出函数 if (!event.data.val()) { return console.log('Client ', clientUid, 'un-followed user', trainerUid); } console.log('We have a new message of trainer with UID:', trainerUid, 'voor client veranderd nu wel?:', clientUid); console.log('message en id', Message, MessageId); // 获取目标用户的设备token列表 const targetUid = (Message.afzender === 'pt') ? clientUid : trainerUid; const getDeviceTokensPromise = admin.database().ref(`/users/${targetUid}/notificationTokens`).once('value'); // 获取训练者信息 const getTrainerProfilePromise = admin.auth().getUser(trainerUid); return Promise.all([getDeviceTokensPromise, getTrainerProfilePromise]).then((results) => { const tokensSnapshot = results[0]; const trainer = results[1]; // 检查是否有可用的设备token if (!tokensSnapshot.hasChildren()) { return console.log('There are no notification tokens to send to.'); } console.log('There are', tokensSnapshot.numChildren(), 'tokens to send notifications to.'); // 通知详情配置,重点调整了操作按钮的位置和格式 const payload = { notification: { title: `Nieuw bericht ${(Message.afzender === 'pt') ? 'van de trainer' : 'van een client'}!`, body: `${Message.naam} heeft je een bericht gestuurd.`, sound: "default", click_action: "FCM_PLUGIN_ACTIVITY", icon: "fcm_push_icon", priority: "high" }, data: { // 配置三个操作按钮,转为字符串符合FCM数据传输要求 actions: JSON.stringify([ { "icon": "reply", "title": "Antwoorden", "callback": "replyAction", "foreground": true }, { "icon": "mark_read", "title": "Markeer als gelezen", "callback": "markReadAction", "foreground": false }, { "icon": "dismiss", "title": "Verwijder", "callback": "dismissAction", "foreground": false } ]) } }; // 提取所有token列表 const tokens = Object.keys(tokensSnapshot.val()); // 发送通知到所有目标设备 return admin.messaging().sendToDevice(tokens, payload); }).then((response) => { // 清理无效的token const tokensToRemove = []; response.results.forEach((result, index) => { const error = result.error; if (error) { console.error('Failure sending notification to', tokens[index], error); if (error.code === 'messaging/invalid-registration-token' || error.code === 'messaging/registration-token-not-registered') { tokensToRemove.push(tokensSnapshot.ref.child(tokens[index]).remove()); } } }); return Promise.all(tokensToRemove); }); });
Ionic端代码修改(处理按钮点击回调)
你还需要调整Ionic组件中的onNotification订阅逻辑,来处理操作按钮的点击事件:
firebase.auth().onAuthStateChanged(this.onAuthStateChanged.bind(this)); } onAuthStateChanged(user) { console.log('user', user) if (user && this.currentUid === user.uid) { return; } this.platform.ready().then(() => { if(!this.platform.is('cordova')) return; this.fcm.subscribeToTopic('all'); if(user){ this.saveToken(); this.currentUid = user.uid; } this.fcm.onNotification().subscribe(data => { // 处理通知接收 if(data.wasTapped) { console.log("Received in background"); // 判断是否是操作按钮点击 if(data.callback) { this.handleNotificationAction(data.callback, data); } } else { console.log("Received in foreground"); // 前台接收时可解析actions,按需展示本地通知按钮 if(data.actions) { const actions = JSON.parse(data.actions); console.log('前台通知操作按钮:', actions); // 可结合本地通知插件展示带按钮的通知 } }; }); this.fcm.onTokenRefresh().subscribe(token => { this.saveToken(); }); }); } // 新增处理操作按钮回调的方法 handleNotificationAction(callbackName: string, data: any) { switch(callbackName) { case 'replyAction': console.log('用户点击了回复按钮', data); // 在这里添加回复逻辑,比如跳转到聊天页面 break; case 'markReadAction': console.log('用户点击了标记已读按钮', data); // 添加标记已读的逻辑 break; case 'dismissAction': console.log('用户点击了删除按钮', data); // 添加删除通知的逻辑 break; default: console.log('未知的回调动作'); break; } } saveToken() { this.fcm.getToken().then(currentToken => { if (currentToken) { firebase.database().ref('users/' + this.currentUid + '/notificationTokens/' + currentToken).set(true); } }).catch(err => { console.error('Unable to get messaging token.', err); if (err.code === 'messaging/permission-default') { console.log('You have not enabled notifications on this browser. To enable notifications reload the page and allow notifications using the permission dialog.'); } else if (err.code === 'messaging/notifications-blocked') { console.log('You have blocked notifications'); } }) }
关键注意事项
- 操作按钮的配置必须放在
data字段中,并且用JSON.stringify转为字符串,因为FCM的data字段只支持字符串类型的值。 foreground字段设置为true时,点击按钮会唤醒APP到前台;设置为false时,只会执行回调而不唤醒APP。- 确保你的Ionic FCM插件版本适配Ionic3,建议使用稳定版本避免兼容性问题。
内容的提问来源于stack exchange,提问作者Sam van beastlo
相关产品推荐
相关产品推荐

