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

Ionic3集成FCM推送:如何为通知添加操作按钮?

解决Ionic3 FCM推送添加操作按钮的报错问题

我看你现在在Ionic3项目中使用FCM插件实现推送通知,想要给推送添加三个操作按钮,但尝试添加按钮时Firebase函数控制台会报错,目前不带按钮的推送可以正常运行。下面我来帮你排查并解决这个问题:

问题根源分析

你之前注释掉的操作按钮配置存在两个核心问题:

  1. Payload结构错误:FCM的通知操作按钮不能直接放在notification字段下,对于Ionic的FCM插件来说,需要将操作按钮配置放在data字段中,同时要遵循插件要求的格式。
  2. 平台兼容性配置缺失: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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 09:04:09