【问题标题】:Flutter Firebase Messaging: How to send push notifications to users at specified timeFlutter Firebase Messaging:如何在指定时间向用户发送推送通知
【发布时间】:2021-10-14 10:27:22
【问题描述】:

目前我有一个应用程序在特定时间有一个包含待办事项的 Firestore 集合,例如 5:00pm - Go for a walk

我创建了一个功能,一旦用户指定时间,我的cloud functions 可以使用 Firebase 云消息传递创建推送通知。

但是,我希望能够在特定时间和日期向用户发送推送通知。

这是我的cloud functions 文件

async function onCreateNotification(uid, time, text) {
    const user = admin.firestore().collection('users').doc(uid).get();
    // Make this function execute at a specific time
    await admin.messaging().sendToDevice(
        user.tokens,
        {
            data: {
                user: JSON.stringify(user),
                text: JSON.stringify(text)
            }
        },
        {
            // Required for background/quit data-only messages on iOS
            contentAvailable: true,
            // Required for background/quit data-only messages on Android
            priority: "high"
        }
    ).then((response) => {
        // See the MessagingDevicesResponse reference documentation for
        // the contents of response.
        console.log('Successfully sent message:', response);
    }).catch((error) => {
        console.log('Error sending message:', error);
    });

}

【问题讨论】:

    标签: firebase google-cloud-functions firebase-cloud-messaging


    【解决方案1】:

    Firebase Cloud Messaging API 在您调用它后会尽快传送消息。它没有办法安排未来的交付。所以你必须自己实现。

    一些选项:

    • 您可以使用scheduled Cloud Function 定期检查是否有任何消息需要传送。
    • 您可以使用 Cloud Tasks 动态安排交付,而不是定期检查。

    对于这两个,也可以在这里查看我的答案:Is there any TTL (Time To Live ) for Documents in Firebase Firestore

    作为另一种选择:

    • 如果消息本身不是动态的,您可以立即将send a data message 发送到设备,然后仅在通知到期时才在设备上显示。

    另见:

    【讨论】:

    • 您认为这两种方法的结合是否可行?我正在考虑可能执行一个预定的云功能,该功能将每天检查定时条目,然后为当天的每个定时条目创建一个谷歌任务。我正在尝试最小化平台上的负载位置
    • 这可行,但这只是为了确保顶级操作不会花费太长时间,您也可以通过更定期地运行它来做到这一点,或者通过 PubSub 触发个人发送主题(这是迄今为止分散 Functions 工作负载的最常见方式)。
    【解决方案2】:

    使用上面 Frank 的回答,我能够成功地利用 Cloud Tasks 和 Firebase Cloud Messaging 来实现我的功能!它还有一些问题需要解决,但我想如果需要,以后有人可以使用它。

    我的代码主要来自suggested article

    这是生成的代码 cloud functions

    const functions = require("firebase-functions");
    const admin = require('firebase-admin')
    const { CloudTasksClient } = require('@google-cloud/tasks');
    admin.initializeApp()
    
    exports.createTask = functions.https.onCall(async (data, context) => {
        log("Create Task")
        const taskClient = new CloudTasksClient();
        let { time, uid, id } = data
    
        // Get Date from time in format mm-dd-yyyy
        let entryDate = new Date(time[0], time[1], time[2], time[3], time[4],);
        const date = join(entryDate, '-');
        let prevEntry = await admin.firestore().doc(`/users/${uid}/${date}/${id}`).get()
        let prevEntryData = await prevEntry.data()
    
        if (prevEntryData.hasOwnProperty('expirationTask')) {
            // Delete old expiration task
            await taskClient.deleteTask({ name: prevEntryData.expirationTask })
        }
        // This works now! Now I should create a task on google tasks
        const todayDate = new Date()
    
        const expirationAtSeconds = (entryDate.getTime() - new Date().getTime()) / 1000 
    
        const project = JSON.parse(process.env.FIREBASE_CONFIG).projectId
        const location = 'us-central1'
        const queue = 'firestore-ttl'
        const queuePath = taskClient.queuePath(project, location, queue)
        const url = `https://${location}-${project}.cloudfunctions.net/firestoreTtlCallback`
        const docPath = `/users/${uid}/${date}/${id}`
        const payload = {
            docPath,
            uid,
        }
        const task = {
            httpRequest: {
                httpMethod: 'POST',
                url,
                body: Buffer.from(JSON.stringify(payload)).toString('base64'),
                headers: {
                    'Content-Type': 'application/json'
                },
            },
            scheduleTime: {
                seconds: expirationAtSeconds
            }
        }
        const [response] = await taskClient.createTask({ parent: queuePath, task })
        const expirationTask = response.name;
        const update = { expirationTask }
        // update the entry with the expiration task name
        await admin.firestore().doc(docPath).update(update)
        log("Done with Create Task")
        return ['Success!']
    })
    
    // Callback to send message to users
    exports.firestoreTtlCallback = functions.https.onRequest(async (req, res) => {
        try {
            const payload = req.body;
            let entry = await (await admin.firestore().doc(payload.docPath).get()).data();
            let tokens = await (await admin.firestore().doc(`/users/${payload.uid}`).get()).get('tokens')
            // log(entry);
            // log(tokens)
            await admin.messaging().sendToDevice(
                tokens,
                {
                    data: {
                        title: JSON.stringify('App'),
                        body: JSON.stringify(entry['text'])
                    }
                },
                {
                    contentAvailable: true,
                    priority: 'high'
                }
            ).then((response) => {
                log('Successfully sent message:')
                log(response)
                admin.firestore().doc(payload.docPath).update({ expirationTask: admin.firestore.FieldValue.delete() })
            }).catch((error) => {
                log('Error in sending Message')
                log(error)
            })
            res.status(200)
        } catch (err) {
            log(err)
            res.status(500).send(err)
        }
    })
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-29
      • 1970-01-01
      • 1970-01-01
      • 2017-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多