簡體   English   中英

Firebase Cloud Messaging iOS:無后台推送通知

[英]Firebase Cloud Messaging iOS: No background push notification

使用較新的 Firebase 雲消息傳遞和方法 swizzling,當我的應用程序處於前台時,我能夠成功地在我的應用程序委托中的didReceiveRemoteNotification方法中接收有效負載。 但是,我沒有收到任何類型的有效負載,並且當我的應用程序處於后台時, didReceiveRemoteNotification不會被調用,盡管消息已成功發送的 api 響應(見下文)
這是我發送到 FCM api 以觸發推送通知的請求https://fcm.googleapis.com/fcm/send

{
"to": "{valid-registration-token}",
"priority":"high", //others suggested setting priority to high would fix, but did not
  "notification":{
      "body":"Body3",
      "title":"test"  
 } 
}


來自 FCM 的回應

{
      "multicast_id": 6616533575211076304,
      "success": 1,
      "failure": 0,
      "canonical_ids": 0,
      "results": [
        {
          "message_id": "0:1468906545447775%a4aa0efda4aa0efd"
        }
      ]
    }

這是我的 appDelegate 代碼

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

        Fabric.with([Crashlytics.self])
        FIRApp.configure()

        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.tokenRefreshNotification),
                                                         name: kFIRInstanceIDTokenRefreshNotification, object: nil)
        return true
    }



    func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
        // Let FCM know about the message for analytics etc.
        FIRMessaging.messaging().appDidReceiveMessage(userInfo)

        // Print full message.
        print("%@", userInfo)

        // handle your message

//        let localNotification = UILocalNotification()
//        localNotification.fireDate = NSDate()
//        let notification = userInfo["notification"]!
//        localNotification.alertBody = notification["body"] as? String
//        localNotification.alertTitle = notification["title"] as? String
//        localNotification.timeZone = NSTimeZone()
//        application.scheduleLocalNotification(localNotification)

    }

    func tokenRefreshNotification(notification: NSNotification) {
        let refreshedToken = FIRInstanceID.instanceID().token()!
        print("InstanceID token: \(refreshedToken)")
        LoginVC.registerForPushNotifications()
        connectToFcm()
    }


    //foreground messages
    func applicationDidBecomeActive(application: UIApplication) {
        connectToFcm()
    }

    // [START disconnect_from_fcm]
    func applicationDidEnterBackground(application: UIApplication) {
        FIRMessaging.messaging().disconnect()
        print("Disconnected from FCM.")
    }


    func connectToFcm() {
        FIRMessaging.messaging().connectWithCompletion { (error) in
            if (error != nil) {
                print("Unable to connect with FCM. \(error)")
            } else {
                print("Connected to FCM.")
            }
        }
    }

}

我在我的應用程序的稍后流程中調用此代碼以請求權限

static func registerForPushNotifications() {
    let settings: UIUserNotificationSettings =
                UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil)
            UIApplication.sharedApplication().registerUserNotificationSettings(settings)
            UIApplication.sharedApplication().registerForRemoteNotifications()
}

由於我能夠在應用程序處於前台時收到通知,因此我認為這將消除所有關於我的 apns 證書未上傳或注冊令牌不正確的擔憂。 如果不是這種情況,請發表評論,我會再次進入那個兔子洞。 我可能忽略了一些簡單的事情,但是如何在應用程序處於后台時顯示通知? 謝謝

顯然,(盡管使用應該自動執行的方法調配)您仍然必須在 Firebase 實例上設置 APNS 令牌。 因此,這意味着您還必須使用類似的方法實現didRegisterForRemoteNOtificationsWithDeviceToken方法

func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {


        // set firebase apns token
        FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenType.Unknown)
}

作為補充說明。 使用"priority":"high"對測試很有用,因為它會立即發送通知。

至少對於我的應用程序而言,所需的行為是推送通知的到達,其中 PN(推送通知)的內容應顯示在應用程序的所需頁面中。

我有 PN 可以到達的三種不同的應用程序狀態:(當然這取決於您的實現,但您應該了解蘋果在這些狀態下如何處理 PN)

(行為由蘋果決定!)

1)應用程序在前台:

  • 收到 PN
  • 在通知中心彈出(您可以單擊或不單擊它 - 沒關系)
  • 徽章會更新
  • PN 在所需頁面中可用

在這種情況下,應用程序始終處理 PN

2)應用程序在后台:

  • 收到 PN
  • 在通知中心彈出(您可以單擊或不單擊它 - 沒關系)
  • 徽章會更新
  • PN 在所需頁面中可用

在這種情況下,應用程序始終處理 PN

3)應用程序被殺死/關閉:

  • 收到 PN
  • 在通知中心彈出
  • 現在有三種可能的方式

    1. 滑動通知 -> 應用程序不會處理 PN

    2. 直接通過啟動器圖標打開應用程序 -> 應用程序不會處理 PN

    3. 點擊通知 -> PN 將由應用程序處理

對於這種情況,如果用戶沒有通過點擊通知打開應用程序,則無法獲取通知數據

要獨立於應用程序狀態,您需要設置一個服務器,您可以在其中請求特定數據。 例如,您有一個顯示所有通知的視圖,您需要一個 API 來請求特定數據。 您不應該在 Pushnotification 的接收方法中處理數據。

我希望能幫助別人!

與 Daniel George 的解決方案類似,我可以通過以下方式解決我的問題:

Messaging.messaging().apnsToken = deviceToken

FirebaseInstanceID 2.0.8,FirebaseMessaging 2.0.8

確保您在 JSON 負載中添加了 "content_available" : true 。 否則您將不會在后台模式下收到推送通知。

"notification" : {
            "body" : "this is body",
            "title" : "this is title"
}
"content_available" : true

從 FCM 獲取成功令牌后,請按照以下步驟使用 FCM 啟用后台有效負載數據獲取:

  1. 打開 Project Navigator > AppCapabilities > Background Modes > 檢查遠程通知

  2. 在 App.delegate 中定義:

     func application(_ application: UIApplication,didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { print("userinfo in background mode on-\\(userInfo)") completionHandler(UIBackgroundFetchResult.newData) }
  3. 根據蘋果指南正確格式化您的有效負載: 在此處輸入鏈接描述

  4. 不要忘記添加鍵值對: {"content-available":1}除非您無法在后台獲取有效負載。

現在嘗試使用 FCM 令牌再次發送通知。 祝你編碼愉快

我一直在努力理解為什么我的 iOS14 通知沒有通過。 Firebase 文檔中沒有提到這一點。

在 2020 年 12 月的 iOS14 上,我可以確認@Daniel George 的解決方案仍然有效並修復了我的通知無法通過的問題。 使用更新的語法重新發布。

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { Messaging.messaging().apnsToken = deviceToken }

iOS14.1、Swift 5.3、Firebase 和 Firebase Cloud Messaging 於 2020 年 12 月 18 日更新。

AFAIK,對於 ios,您將無法使用 FCM 為處於后台或已終止狀態的應用程序發送推送通知消息。

Firebase 推送通知

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM