简体   繁体   English

如何在 Firebase 控制台之外发出计划的 Firebase 云消息通知?

[英]How can scheduled Firebase Cloud Messaging notifications be made outside of the Firebase Console?

Inside the Firebase Console, under the Cloud Messaging view, users are able to create test notifications.在 Firebase 控制台中,在云消息视图下,用户可以创建测试通知。 This functionality also allows you to schedule the time at which the notification will send to a device or set of devices.此功能还允许您安排通知将发送到一个设备或一组设备的时间。

Is it possible to create and send scheduled FCM notifications to specific devices by using firebase cloud functions and the Firebase Admin SDK?是否可以使用 firebase 云功能和 Firebase 管理员 SDK 创建预定的 FCM 通知并将其发送到特定设备? Is there an alternative way to solving this?有没有解决这个问题的替代方法?

The current way that I send scheduled messages to users is like so:我向用户发送预定消息的当前方式是这样的:

const functions = require('firebase-functions');
const admin = require('firebase-admin');
const schedule = require('node-schedule');
admin.initializeApp();

exports.setScheduledNotification = functions.https.onRequest(async (req, res) => {
    const key = req.query.notification_key;

    const message = {
        notification: {
            title: 'Test Notification',
            body: 'Test Notification body.'
        }
    };

    var currentDate = new Date();
    var laterDate = new Date(currentDate.getTime() + (1 * 60000));

    var job = schedule.scheduleJob(key, laterDate, () => {
        const snapshot = admin.messaging().sendToDevice(key, message);
    });

    return res.status(200).send(`Message has been scheduled.`);
});

First of all, I am unsure how node-schedule interacts with firebase cloud functions.首先,我不确定node-schedule如何与 firebase 云函数交互。 The logs appear that the function terminates very quickly which I would think would be correct.日志显示 function 终止非常快,我认为这是正确的。 The longer the operation runs the more costly it is in our firebase bills.操作运行的时间越长,我们的 firebase 账单中的成本就越高。 The notification does still run on a scheduled time though.不过,通知仍然会在预定时间运行。 I'm confused on how that all is working behind the scenes.我对这一切在幕后如何运作感到困惑。

Secondly, I am having issues canceling these scheduled notifications.其次,我在取消这些预定通知时遇到问题。 The notifications will most likely be on a 2hr timed schedule from the point it gets created.从创建之日起,通知很可能会按照 2 小时的时间安排进行。 Before the 2hrs is up, I'd like the have the ability to cancel/overwrite the notification with an updated scheduled time.在 2 小时结束之前,我希望能够使用更新的预定时间取消/覆盖通知。

I tried this to cancel the notification and it failed to find the previously created notification.我尝试这样做以取消通知,但找不到先前创建的通知。 Here is the code for that:这是代码:

exports.cancelScheduledNotification = functions.https.onRequest(async (req, res) => {
    const key = req.query.notification_key;

    var job = schedule.scheduledJobs[key];
    job.cancel();

    return res.status(200).send(`Message has been canceled.`);
});

Is it possible to tap into the scheduling functionality of firebase cloud messaging outside of the firebase console?是否可以在 firebase 控制台之外利用 firebase 云消息传递的调度功能? Or am I stuck with hacking my way around this issue?或者我是否坚持解决这个问题?

A Cloud Function can run for a maximum of 9 minutes. Cloud Functions 最多可以运行 9 分钟。 So unless you're using node-schedule for periods shorter than that, your current approach won't work.因此,除非您在更短的时间内使用node-schedule ,否则您当前的方法将不起作用。 Even if it would work, or if you are scheduling for less than 9 minutes in advance, using this approach is very uneconomic as you'll be paying for the Cloud Functions for all this time while it's waiting.即使它可以工作,或者如果您提前不到 9 分钟进行安排,使用这种方法也非常不经济,因为您将在等待期间为 Cloud Functions 支付所有费用。


A more common approach is to store information about what message you want to be delivered to whom at what time in a database, and then use regular scheduled functions to periodically check what messages to send.一种更常见的方法是将有关您希望在什么时间发送给谁的消息的信息存储在数据库中,然后使用常规调度函数定期检查要发送的消息。 For more on this, see these previous questions:有关这方面的更多信息,请参阅这些先前的问题:


A recent improvement on this is to use the Cloud Tasks API to programmatically schedule Cloud Functions to be called at a specific time with a specific payload, and then use that to send the message through FCM.最近对此的改进是使用 Cloud Tasks API 以编程方式安排要在特定时间使用特定负载调用的 Cloud Functions,然后使用它通过 FCM 发送消息。 Doug Stevenson wrote a great blog post about this here: How to schedule a Cloud Function to run in the future with Cloud Tasks (to build a Firestore document TTL) .道格史蒂文森在这里写了一篇很棒的博客文章: 如何安排云函数在未来使用云任务运行(构建 Firestore 文档 TTL) While the post is about deleting documents at a certain time, you can combine it with the previous approach to schedule FCM messages too.虽然帖子是关于在特定时间删除文档,但您也可以将其与之前的方法结合来​​安排 FCM 消息。


One final thing to note: while Firebase Cloud Messaging will automatically handle the display of notification messages when the application isn't active, you can also use it for only the delivery part using data messages and then handling all display in your application code.最后要注意的一件事:虽然 Firebase Cloud Messaging 会在应用程序不活动时自动处理通知消息的显示,但您也可以将它仅用于使用数据消息的传递部分,然后处理应用程序代码中的所有显示。 If you use that approach, you can deliver the FCM data message straight away with the time to display the message, and then wake the device up to display the message at that time.如果您使用这种方法,您可以立即发送 FCM数据消息以及显示消息的时间,然后唤醒设备以显示该消息。

To make Frank's answer more tangible, I am including some sample code below for scheduled cloud functions, that can help you achieve the 'scheduled FCM notifications'.为了使弗兰克的回答更加具体,我在下面包含了一些用于预定云功能的示例代码,可以帮助您实现“预定的 FCM 通知”。

You should store the information required to send your notification(s) in Firestore (eg the when-to-notify parameter and the FCM token(s) of the users you want to send the notification to) and run a cloud function every minute to evaluate if there is any notification that needs to be delivered.您应该将发送通知所需的信息存储在 Firestore 中(例如,何时通知参数和您要向其发送通知的用户的 FCM 令牌)并每分钟运行一次云 function 以评估是否有任何需要发送的通知。

The function checks what Firestore documents have a WhenToNofity parameter that is due, and send the notifications to the receiver tokens immediately. function 检查哪些 Firestore 文档具有到期的 WhenToNofity 参数,并立即将通知发送到接收者令牌。 Once sent, the function sets the boolean 'notificationSent' to true, to avoid that the users receive the same notification again on the next iteration.发送后,function 将 boolean 'notificationSent' 设置为 true,以避免用户在下一次迭代中再次收到相同的通知。

The code below achieves just that:下面的代码实现了这一点:

const admin = require('firebase-admin');
admin.initializeApp();
const database = admin.firestore();

exports.sendNotification = functions.pubsub.schedule('* * * * *').onRun(async (context) => {
    //check whether notification should be sent
    //send it if yes

    const query = await database.collection("experiences")
        .where("whenToNotify", '<=', admin.firestore.Timestamp.now())
        .where("notificationSent", "==", false).get();

    query.forEach(async snapshot => {
        sendNotification(snapshot.data().tokens);
        await database.doc('experiences/' + snapshot.id).update({
            "notificationSent": true,
        });
    });

    function sendNotification(tokens) {

        let title = "INSERT YOUR TITLE";
        let body = "INSERT YOUR BODY";

        const message = {
            notification: { title: title, body: body},
            tokens: tokens,
                    android: {
                        notification: {
                            sound: "default"
                        }
                    },
                    apns: {
                        payload: {
                            aps: {
                                sound: "default"
                            }
                        }
                    }
        };
        admin.messaging().sendMulticast(message).then(response => {
            return console.log("Successful Message Sent");
        }).catch(error => {
            console.log(error);
            return console.log("Error Sending Message");
        });
    }
    return console.log('End Of Function');
});

If you're unfamiliar with setting up cloud functions, you can check how to set them up here .如果您不熟悉设置云功能,可以在此处查看如何设置它们。 Cloud functions require a billing account, but you get 1M cloud invocations per month for free, which is more than enough to cover the costs of this approach.云功能需要一个计费帐户,但您每月免费获得 100 万次云调用,这足以支付这种方法的成本。

Once done, you can insert your function in the index.js file.完成后,您可以将 function 插入 index.js 文件中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在没有控制台的情况下创建 Firebase 云消息循环通知? - How to create Firebase Cloud messaging recurring notifications without console? 如何处理Django中的Firebase云消息通知? - How to handle Firebase Cloud Messaging Notifications in Django? 如何通过firebase云消息发送定时通知到flutter app - how to send scheduled notification to flutter app through firebase cloud messaging 如何使用 firebase 云消息和云功能设置推送通知? - How can I go about setting up push notifications using firebase cloud messaging and cloud functions? 如何在不使用 Firebase 控制台的情况下发送 Firebase 云消息通知? - How can I send a Firebase Cloud Messaging notification without use the Firebase Console? 如何使用 Firebase 云消息发送组通知? - How to send the Group Notifications using Firebase Cloud messaging? 在 ios 中未收到 Firebase 云消息传递通知 - Not receiving Firebase Cloud Messaging Notifications in ios Twilio Conversations 使用 Firebase Cloud Messaging 推送通知 - Twilio Conversations push notifications with Firebase Cloud Messaging 通过 Firebase 云消息控制台在 iOS 推送通知中发送图像 - Sending an Image in iOS Push-Notifications through Firebase Cloud Messaging Console 在 Firebase 云消息传递中,React 本机应用程序未通过 TOPIC 接收通知 - React native app not receiving notifications via TOPIC in Firebase cloud messaging
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM