应用在后台时的Firebase监听器

时间:2017-01-16 21:35:07

标签: ios swift firebase firebase-cloud-messaging unnotificationrequest

我的应用中的通知表有一个Firebase childAdded事件侦听器,当应用在后台时,我想触发推送通知。

以下是听众:

@objc func observeNotificationsChildAddedBackground() {
    self.notificationsBackgroundHandler = FIREBASE_REF!.child("notifications/\(Defaults.userUID!)")
    self.notificationsBackgroundHandler!.queryOrdered(byChild: "date").queryLimited(toLast: 99).observe(.childAdded, with: { snapshot in
        let newNotificationJSON = snapshot.value as? [String : Any]
        if let newNotificationJSON = newNotificationJSON {
            let status = newNotificationJSON["status"]
            if let status = status as? Int {
                if status == 1 {
                    self.sendPushNotification()
                }
            }
        }
    })
}

func sendPushNotification() {
    let content = UNMutableNotificationContent()
    content.title = "Here is a new notification"
    content.subtitle = "new notification push"
    content.body = "Someone did something which triggered a notification"
    content.sound = UNNotificationSound.default()

    let request = UNNotificationRequest(identifier: "\(self.notificationBackgroundProcessName)", content: content, trigger: nil)
    NotificationCenter.default.post(name: notificationBackgroundProcessName, object: nil)
    UNUserNotificationCenter.current().delegate = self
    UNUserNotificationCenter.current().add(request){ error in
        if error != nil {
            print("error sending a push notification :\(error?.localizedDescription)")
        }
    }
}

当应用程序位于前台时,这非常有用。然后我在我的app委托applicationWillResignActive方法中添加了一个背景观察器,以便在后台观察它:

func applicationWillResignActive(_ application: UIApplication) {
     NotificationCenter.default.addObserver(self, selector: #selector(MainNavViewController.observeNotificationsChildAdded), name: notificationBackgroundProcessName, object: nil)
}

但是当应用程序在后台时,事件观察者不会触发。我调查了Firebase Cloud Messenger来解决这个问题并遇到这样的帖子:

Is it possible to send PushNotifications, using Firebase Cloud Messaging (FCM) to special UDID, directly from device?

但是我并没有尝试从一个用户向另一个用户发送推送通知,我正在尝试从数据库侦听器中激活UNNotificationRequest

我也发现这篇文章: FCM background notifications not working in iOS 但同样,这与我的用例不同,因为它在FIRMessaging框架内使用。

那么,当应用程序在后台时,是否可以运行此数据库侦听器?如果没有,我是否可以让Firebase Cloud Messenger观察表中的更改并发送通知?

4 个答案:

答案 0 :(得分:3)

我遇到了同样的问题,几个月前发现了你的帖子。我已经设法最终了解在后台观察通知所需的内容。

我详细介绍了我在这篇文章中使用的解决方案https://stackoverflow.com/a/42240984/7048719

技术如下

  1. 使用自定义数据服务类
  2. 初始化数据服务类的sharedInstance
  3. 调用数据服务类中的相应函数 来自初始视图控制器的sharedInstance。
  4. 这样观察者就会留在记忆中

    更新:Apple已针对后台模式实施了更新,这些更新已停止此方法的运行。

答案 1 :(得分:1)

设备有自己管理后台网络呼叫的方式,因此处理这样的后台推送通知将无法在真实设备上运行。应用程序进入后台后不久,观察者将从内存中删除。我能够通过创建一个观察notifications表并使用Firebase-Messenger框架处理推送通知的Node.js服务器来解决这个问题。这实际上非常简单。我用这篇博文作为我的向导: Sending notifications between Android devices with Firebase Database and Cloud Messaging

然而,只要将包含观察者(在本例中为app委托)的对象传递给后台线程调用,此方法将在模拟器(但不在实际设备)中起作用:

func applicationWillResignActive(_ application: UIApplication) {
     NotificationCenter.default.addObserver(self,
                                            selector: #selector(self.observeNotificationsChildAddedBackground),
                                            name: notificationBackgroundProcessName,
                                            object: self)
}

答案 2 :(得分:1)

简单的解决方案是使用后台提取。您还可以使用后台提取来定期获取新条目的表,并在添加新行时显示通知。

这并不能确保立即收到通知。但与使用APN相比,实现要简单得多。

答案 3 :(得分:0)

您可以将后台任务添加到Firebase观察器

@objc函数funcobserveNotificationsChildAddedBackground(){

var backgroundTask: UIBackgroundTaskIdentifier = UIBackgroundTaskInvalid

backgroundTask = UIApplication.shared.beginBackgroundTask {
        [unowned self] in
        UIApplication.shared.endBackgroundTask(backgroundTask)
        backgroundTask = UIBackgroundTaskInvalid
    }
    assert(backgroundTask != UIBackgroundTaskInvalid)

self.notificationsBackgroundHandler = FIREBASE_REF!.child("notifications/\(Defaults.userUID!)")
self.notificationsBackgroundHandler!.queryOrdered(byChild: "date").queryLimited(toLast: 99).observe(.childAdded, with: { snapshot in
    let newNotificationJSON = snapshot.value as? [String : Any]
    if let newNotificationJSON = newNotificationJSON {
        let status = newNotificationJSON["status"]
        if let status = status as? Int {
            if status == 1 {
                self.sendPushNotification()
            }
        }
    }
})

}