【问题标题】:Firebase Notification To Device with FCM Token Says Sent but not received带有 FCM 令牌的设备的 Firebase 通知说已发送但未收到
【发布时间】:2017-07-25 17:41:37
【问题描述】:

我正在尝试使用 FCM 令牌从 firebase 通知控制台向特定设备发送一个简单的推送通知。 Firebase 通知控制台将通知显示为已发送,但设备未收到通知。我已尝试发送通知,然后等待查看控制台是否从didReceiveRemoteNotification 记录日志,但通知需要很长时间(数小时)才能显示为在 firebase 控制台中发送(即使我将优先级设置为high) .

应用代理

import UIKit
import Firebase
import FirebaseStorage
import FirebaseDatabase
import FirebaseMessaging
import CoreData
import UserNotifications

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.

        // Use Firebase library to configure APIs
        FirebaseApp.configure()

        /////
        // For Firebase Cloud Messaging (FCM)
        if #available(iOS 10.0, *) {
            // For iOS 10 display notification (sent via APNS)
            UNUserNotificationCenter.current().delegate = self
            let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
            UNUserNotificationCenter.current().requestAuthorization(
                options: authOptions,
                completionHandler: {_, _ in })
        } else {
            let settings: UIUserNotificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
            application.registerUserNotificationSettings(settings)
        }
        application.registerForRemoteNotifications()
        // End of [for Firebase Cloud Messaging (FCM)]
        /////

        return true
    }

    ///////////////////////
    // FCM Setup

    // Monitor token generation for FCM: Be notified whenever the FCM token is updated
    func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String) {
        print("Firebase registration token: \(fcmToken)")
    }

    // Monitor token generation for FCM:
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        Messaging.messaging().apnsToken = deviceToken
    }    // Handle messages received through the FCM APNs interface
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
        print("didReceiveRemoteNotification")
        // If you are receiving a notification message while your app is in the background,
        // this callback will not be fired till the user taps on the notification launching the application.
        // TODO: Handle data of notification

        // With swizzling disabled you must let Messaging know about the message, for Analytics
        // Messaging.messaging().appDidReceiveMessage(userInfo)

        // Print message ID.
        // gcm_message_id
        if let messageID = userInfo["gcmMessageIDKey"] {
            print("Message ID: \(messageID)")
        }

^我的猜测是问题可能与“gcm_message_id”/“gcmMessageId”/“gcm.message_id”有关,因为我在下面尝试的三种方法中的每一种都不同

        // Print full message.
        print(userInfo)
    }

    // Handle messages received through the FCM APNs interface
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        print("didReceiveRemoteNotification (withCompletionHandeler)")
        // If you are receiving a notification message while your app is in the background,
        // this callback will not be fired till the user taps on the notification launching the application.
        // TODO: Handle data of notification

        // With swizzling disabled you must let Messaging know about the message, for Analytics
        // Messaging.messaging().appDidReceiveMessage(userInfo)

        // Print message ID.
        if let messageID = userInfo["gcmMessageIDKey"] {
            print("Message ID: \(messageID)")
        }

^我的猜测是问题可能与“gcm_message_id”/“gcmMessageId”/“gcm.message_id”有关,因为我在下面尝试的三种方法中的每一种都不同

        // Print full message.
        print(userInfo)

        completionHandler(UIBackgroundFetchResult.newData)
    }

    // End of [FCM Setup]
    ///////////////////////
}

视图控制器

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Retrieve the current registration token for Firebase Cloud Messaging (FCM)
        let token = Messaging.messaging().fcmToken
        print("FCM token: \(token ?? "")")
      }
}

权利和启用推送通知

我添加了推送权利 并启用了推送通知 的后台模式,并将GoogleService-Info.plist 添加到我的项目中。

通知发送方法

我正在从 Firebase 通知控制台(如下所示)创建通知,因此通知本身的结构应该没有问题。

我尝试了以下方法来解决这个问题,但都产生了相同的结果:

有谁知道为什么通知在 firebase 通知控制台中被标记为已发送但未显示在设备上?

【问题讨论】:

  • 请检查以下内容: 1. 您是否添加了推送权限? 2. 是否添加了 GoogleService-Info.plist?
  • @jn-se,感谢您的评论。我添加了推送权利(并为推送通知启用了后台模式)并将 GoogleService-Info.plist 添加到我的项目中。我已将屏幕截图添加到我上面的问题中
  • 除了权利:1。 “但是通知需要太长时间(小时)才能显示为在 Firebase 控制台中发送(即使我将优先级设置为高)。`” 结构 及其外观。很多时候payload的结构是错误的,因此你什么也得不到!
  • 1.我已经研究过如何解决这个问题,但只发现将优先级设置为high,就像我现在所做的那样;如果您对修复有任何建议,我们将不胜感激。 2. 我已经确定我没有收到错误,并且正在将 FCM 令牌打印到我在 xcode 中的控制台上,并使用它来定位适当的设备。 3. 我自己还没有创建结构(以消除您描述的风险),而是从 Firebase 通知控制台创建通知;我在我的问题中添加了一张图片,以便您查看

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


【解决方案1】:

我在处理推送通知时使用的几个故障排除步骤是:

  1. 首先让推送工作独立于 Firebase 服务。我用这个tool.
  2. 确保您没有任何捆绑标识符命名空间冲突。例如,在设备上拥有 appstore 构建、testflight 构建和/或开发应用程序构建的任意组合。删除除一个应用程序之外的所有实例。捆绑标识符是您的设备如何知道将推送通知路由到哪个应用程序的方式。
  3. 当所有其他方法都失败时 - 我尝试通过构建一个新的示例项目并将其连接到一个新的 firebase 项目来隔离问题,看看我是否可以将我的注意力缩小到能够在没有任何其他业务的情况下进行推送工作我的应用程序中的逻辑。这有助于我向自己证明我并没有发疯,并向我证明这不是什么神秘的网络状况导致了我的困境。

我希望这可以帮助您在工作时弄清楚所有问题。

【讨论】:

  • 感谢您提供故障排除提示!奇怪的是,从我的手机中删除该应用程序,然后从 XCode 再次运行/安装解决了它。代码本身无需更改,通知现在按预期工作。单独安装 Quickstart 项目也有助于防止我感觉自己完全疯了,因为它按预期工作并且具有与我自己的代码相同的代码 (github.com/firebase/quickstart-ios/blob/master/messaging/…)。再次感谢您的提示,并希望答案/问题/评论对其他人有所帮助!
  • 很高兴它有帮助!祝你项目的其余部分好运。
  • 我也有同样的问题,当我删除并重新安装应用程序时,它只工作一次,当我再次运行代码时,iPhone 停止响应 firebase 控制台发送的通知。 FirebaseInstanceID 版本:v3.4.0。
【解决方案2】:

尝试在 didRegisterForRemoteNotificationsWithDeviceToken func 中添加如下代码:

Messaging.messaging().apnsToken = deviceToken

所以它看起来像这样:

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {

    Messaging.messaging().apnsToken = deviceToken
}

这对我有用。

【讨论】:

  • 这解决了问题,但我不知道为什么现在需要它。
【解决方案3】:

有谁知道为什么通知在 firebase 通知控制台中被标记为已发送但未显示在设备上?

因为“已发送”并不意味着“已收到”。

不能保证在设备上收到通知。使用基本的 APNS 基础架构,如果在设备上接收或处理通知,您甚至无法获取信息。

如果您没有在设备上收到成功发送的消息,可能有多种原因。此外,即使您收到 Firebase 令牌,也不意味着您的设备在任何情况下都可以收到通知。

为了隔离问题,我建议建立最小设置并使用不带 Firebase 的 APNS。您可以使用终端或 NWPusher (https://github.com/noodlewerk/NWPusher) 从本地 macOS 系统发送通知,并使用 iOS 原生远程推送通知框架接收通知。

注意将 APNS 设备令牌转换为提交通知所需的正确格式:

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {

    let token = deviceToken.hexEncodedString()
    print("Token: \(token)")
}

数据扩展:

extension Data {
    func hexEncodedString() -> String {
        return map { String(format: "%02hhx", $0) }.joined()
    }
}

【讨论】:

  • 感谢所有建议,但如果我理解正确,您是在建议我根本不使用 firebase 通知,在我的情况下这不是一个选项
  • 这是一个调试发现问题的好选择。如果它不适用于最小的 APNS 设置,则在配置或应用设置中存在错误。如果运行良好,则错误与 Firebase 设置或推送负载有关,但应用配置正确。
【解决方案4】:

我看到您已经完成了项目的Capabilities 中的所有内容。

几点:

  • 使您的班级符合messaging delegate,如下所示:

    Messaging.messaging().delegate = self
    
  • 确保您已正确设置证书并将所有内容上传到 Firebase 推送通知配置(不准确的术语)。

  • 我已经完成了几个使用 Firebase 推送通知服务的应用程序,并且从头开始制作示例应用程序可能会帮助您找出自己做错了什么。

而且...这里有一个更好的代码块,用于注册您的应用程序以获取推送通知。

    // Setup Push Notifications

    if #available(iOS 10.0, *) {
        let center  = UNUserNotificationCenter.current()
        center.delegate = self
        center.requestAuthorization(options: [.sound, .alert, .badge]) { (granted, error) in
            if error == nil{
                DispatchQueue.main.async(execute: {
                    application.registerForRemoteNotifications()
                })
            }
        }
    }
    else {
        let notificationTypes: UIUserNotificationType = [.sound, .alert, .badge]
        let notificationSettings = UIUserNotificationSettings(types: notificationTypes, categories: nil)
        application.registerForRemoteNotifications()
        application.registerUserNotificationSettings(notificationSettings)
    }

【讨论】:

    猜你喜欢
    • 2016-02-11
    • 2020-02-17
    • 2015-02-28
    • 1970-01-01
    • 2021-01-02
    • 2020-04-25
    • 1970-01-01
    • 2017-11-26
    • 1970-01-01
    相关资源
    最近更新 更多