【问题标题】:Trigger notification at certain condition meets on Firebase在特定条件下触发通知在 Firebase 上满足
【发布时间】:2018-12-25 07:24:00
【问题描述】:

您好,我想向那些将商品添加到购物车并且在 7 天内未购买的用户触发通知。

我想自动完成。在 firebase 上实现这个的正确方法是什么?

【问题讨论】:

    标签: android firebase firebase-realtime-database google-cloud-functions


    【解决方案1】:
    const functions = require('firebase-functions');
    var admin = require("firebase-admin");
    admin.initializeApp();
    
    // timestamp the cart with last item added date/time
    exports.timestampCartItem =
      functions.database.ref('/users/{uid}/cart/{item}')
        .onCreate((snapshot, context) => {
          return snapshot.ref.parent('timestamp').set((new Date()).getTime()); // milliseconds
        })
    
    
    
    // Call this function every hour using https://cron-job.org/en/
    const CART_EXPIRE_TIME = Number(7 * 24 * 60 * 60 * 1000); // days * hours * minutes * seconds * milliseconds
    exports.scanZombieCarts = functions.https.onRequest((request, response) => {
    
      const server_time = Number((new Date()).getTime());
      const usersDBRef = admin.database().ref('users');
      const notifyDBRef = admin.database().ref('notify'); // queue to send notifications with FCM
    
      return usersDBRef.once('value')
        .then(users => {
          let zombie_promises = [];
          users.forEach(usersnap => {
            let userid = usersnap.key;
            let user = usersnap.val();
            if (user.hasOwnProperty('cart')) {
              let cart_timestamp = Number(user.cart.timestamp || 0) + CART_EXPIRE_TIME;
              if (cart_timestamp < server_time) {
                zombie_promises.push(
                  notifyDBRef.push({
                    'notification': {
                      'body': `You have ${Object.keys(user.cart).length} items in your Cart.`,
                      'title': 'Sales end soon!'
                    },
                    'token': user.devicetoken
                  })
                );
              }
            }
          })
    
          return Promise.all(zombie_promises);
        })
        .then(() => {
          let elapsed_time = ((new Date()).getTime() - (server_time)) / 1000;
          response.status(200);
          response.send(`<h2>Finished scan of Zombie Carts...${elapsed_time} seconds</h2>`);
          return null;
        })
        .catch(err => {
          response.status(500);
          response.send(`<h2>Scan failed</h2>`);
          console.log(err);
        })
    });
    
    // IMPORTANT:
    // https://console.developers.google.com/apis search for and enable FCM
    exports.sendReminder =
      functions.database.ref('/notify/{message}')
        .onCreate((snapshot, context) => {
          let message = snapshot.val();
    
          let send_and_consume = [
            admin.messaging().send(message), // send message to device
            snapshot.ref.remove()            // consumes message from queue
          ]
    
          return Promise.all(send_and_consume)
            .catch(err => {
              console.log(err); // probably bad token
            })
        })
    

    注意事项 这假设当用户打开应用程序时,应用程序会使用从消息中获取的设备令牌写入一个 'users/{uid}/devicetoken' 键。

    请参阅有关启用 FCM 和 CRON 触发器的内部 cmets。

    测试 将所有这些添加到您的 index.js 文件中,使用 firebase deploy 上传到服务器。

    在控制台中手动编辑 Firebase 数据库,以观察触发器自动添加/更新时间戳。

    使用firebase serve --only functions 从您的机器本地测试/调试您的 https 触发器。它会给你一个 localhost 链接来运行,你可以在控制台中捕获错误。

    【讨论】:

    • 这将部署在 Firebase 云功能上,对吗?如何执行?
    • 正确。有 2 个 DB 触发器和 1 个导出的 Cloud Function。使用任何 CRON 服务按计划调用 https 函数。
    • 你的意思是这些应该部署在firebase云功能上,然后在https://cron-job.org/en/的帮助下安排这个javascript文件?
    • 当你将它部署到 firebase 时,它​​会创建一个带有链接的 HTTPs Trigger 函数(在 Cloud Functions 下的 Firebase Console 中查看)。当您调用该 URL 时,它将在您的数据库上运行该函数。在您的 cron 作业中使用该 URL。
    • 是的,它是正确的,它会在我调用该 URL 时执行。我需要什么来自动运行它
    【解决方案2】:

    不幸的是,目前 FCM 中没有类似的东西,但您可以在自己的服务器或应用程序中使用 AlarmManager 实现预定推送,如下所示: 在您的清单中

    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    

    在你看来

    Calendar sevendayalarm = Calendar.getInstance();
    
                    sevendayalarm.add(Calendar.DATE, 7);
    
                    Intent intent = new Intent(this, AlarmReciever.class);
                    PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 001, intent, 0);
    
                    AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
                    am.set(AlarmManager.RTC_WAKEUP, sevendayalarm.getTimeInMillis(), pendingIntent);
    

    你的闹钟接收者在哪里

    public  class AlarmReciever extends BroadcastReceiver{
    
            @Override
            public void onReceive(Context context, Intent intent) {
                // push notification
            }
        }
    

    别忘了在你的清单中声明接收者

    <receiver android:name=".AlarmReceiver" >
             <intent-filter>
               <action android:name="NOTIFICATION_SERVICE" />
             </intent-filter>
         </receiver>
    

    【讨论】:

    • 谢谢 :) 我不想在我的应用程序中这样做。我读到它可以使用firebase。不知道这样做的正确方法是什么
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-21
    • 1970-01-01
    • 1970-01-01
    • 2020-02-22
    • 1970-01-01
    • 2021-01-24
    相关资源
    最近更新 更多