【问题标题】:Firebase Cloud Messaging iOS: No background push notificationFirebase Cloud Messaging iOS:没有后台推送通知
【发布时间】:2016-11-21 21:07:22
【问题描述】:

当我的应用被前景化时,使用带有方法调配的较新 Firebase 云消息传递,我可以成功地在我的应用委托中的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 证书未上传或注册令牌不正确的所有担忧。如果不是这种情况,请发表评论,我会再次进入那个兔子洞。 我可能忽略了一些简单的事情,但是如何在应用程序后台显示通知?谢谢

【问题讨论】:

  • 我今天面临着类似的斗争:当应用程序在前台时调用应用程序委托中的处理程序,但当应用程序在后台时没有显示托盘通知。有趣的是看看是否有任何事情发生。如果我弄清楚了,会告诉你的。
  • 你看过github上的这个issue了吗?
  • 当您的应用程序在前台时,您可以直接从 FCM 接收消息,而不是通过应用程序在后台时使用的 APNs。为了确保 APNs 配置正确,您是否可以通过实现 didRegisterForRemoteNotificationsWithDeviceToken 方法来确认您正在接收 APNs 令牌。
  • @ArthurThompson 在此版本的代码之前,我没有使用方法调配技术,而是实现了 didRegisterForeRemoteNotificationsWIthDeviceToken 方法,我可以在其中获得令牌。起初我希望我已经完成了,但是当这个令牌对 FCM 不起作用时,我不得不重构。这能回答你的问题吗?
  • @Kazimieras 是的,我读了整本书。我尝试将优先级设置为高,内容可用设置为 true。但没有运气。我也尝试同时使用两者。但其他人说那是行不通的,就我而言,这又是真的。

标签: ios swift firebase apple-push-notifications firebase-cloud-messaging


【解决方案1】:

我很难理解为什么我的 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 日更新。

【讨论】:

    【解决方案2】:

    确保您在 JSON 有效负载中添加了 "content_available" : true。否则你不会在后台模式下收到推送通知。

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

    【讨论】:

      【解决方案3】:

      至少对于我的应用程序而言,所需的行为是推送通知的到来,其中 PN(推送通知)的内容应显示在应用程序的所需页面中。

      我有 PN 可以到达的三种不同的应用状态: (当然这取决于你的实现,但你应该知道苹果在这些状态下是如何处理 PN 的)

      (行为由苹果决定!)

      1) 应用在前台:

      • 收到 PN
      • 在通知中心弹出(您可以点击或不点击 - 没关系)
      • 徽章将更新
      • PN 在所需页面中可用

      在这种情况下,应用总是处理 PN

      2) 应用在后台:

      • 收到 PN
      • 在通知中心弹出(您可以点击或不点击 - 没关系)
      • 徽章将会更新
      • PN 在所需页面中可用

      在这种情况下,应用总是处理 PN

      3) 应用被杀死/关闭:

      • 收到 PN
      • 在通知中心弹出
      • 现在有三种可能的方法

        1. 滑动通知 -> PN 将由应用处理

        2. 直接通过启动器图标打开应用 -> PN 将由应用处理

        3. 点击通知 -> PN 将由应用处理

      对于这种情况,如果用户通过点击通知没有打开应用,则无法获取通知数据

      要独立于应用程序状态,您需要设置一个服务器,您可以在其中请求特定数据。例如。您有一个显示所有通知的视图,您需要一个 API 来请求特定数据。您不应该在 Pushnotification 的接收方法中处理数据。

      希望对大家有所帮助!

      【讨论】:

        【解决方案4】:

        从 FCM 成功获取令牌后,按照以下步骤使用 FCM 启用后台负载数据提取:

        1. 打开 Project Navigator > AppCapabilities > 背景模式 > 检查远程通知

        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. 根据苹果指南正确格式化您的有效负载: enter link description here

        4. 不要忘记添加键值对: {"content-available":1} 除非您无法在后台获取有效负载。

        现在尝试使用 FCM 令牌再次发送通知。祝你编码愉快

        【讨论】:

          【解决方案5】:

          与 Daniel George 的解决方案类似,我可以通过以下方式解决我的问题:

          Messaging.messaging().apnsToken = deviceToken
          

          FirebaseInstanceID 2.0.8,FirebaseMessaging 2.0.8

          【讨论】:

          • 到底什么是 deviceToken ?我们怎样才能找到它?
          • 这里有:func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) 你可以在这里找到相关信息:firebase.google.com/docs/cloud-messaging/ios/client 它应该是firebase用来识别你的设备的令牌。
          【解决方案6】:

          AFAIK,对于 ios,您将无法使用 FCM 为处于后台或已终止状态的应用发送推送通知消息。

          Firebase Push Notification

          【讨论】:

            【解决方案7】:

            显然,(尽管使用了应该自动执行的方法调配)您仍然必须在 Firebase 实例上设置 APNS 令牌。因此,这意味着您还必须使用类似的方法实现 didRegisterForRemoteNOtificationsWithDeviceToken 方法

            func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
            
            
                    // set firebase apns token
                    FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenType.Unknown)
            }
            

            作为补充说明。使用"priority":"high" 对测试很有用,因为它会立即发送通知。

            【讨论】:

            • 一切正常后,我进行了全新安装,现在 FIRInstanceID.instanceID().token 对象为零,我无法连接ToFcm,错误代码为 501。有什么想法吗?跨度>
            • 对我来说关键是选择“未知”作为类型。以前我尝试过“沙盒”和“开发”,但无论哪种方式都不能正常工作。启动全新安装时,令牌对象为零,但是我通过警卫检查解决了这个问题,并且从我所看到的情况下多次触发令牌刷新通知。
            • 当应用启用 swizzling 时,它会自动设置 APNs 令牌,因此无需实现 didRegisterForRemoteNotificationsWithDeviceToken
            • @ArthurThompson 那么,为什么即使使用更新版本,我也必须这样做来解决这个后台通知问题?事实上,Google 的 Firebase 文档有很多指南,其中包含已弃用和不清楚的方法。
            猜你喜欢
            • 2022-11-30
            • 1970-01-01
            • 2022-12-14
            • 2018-09-11
            • 2020-12-12
            • 2017-01-05
            • 2016-11-03
            • 2016-06-24
            • 1970-01-01
            相关资源
            最近更新 更多