Firebase云消息传递通知未发送iOS有效载荷格式

5m1hhzi4  于 2023-02-19  发布在  iOS
关注(0)|答案(9)|浏览(78)

昨晚我在应用程序中使用FCM测试推送通知,结果崩溃了(几天前还在工作)。我用firebase控制台中的通知菜单测试了它。
我进一步调查了通知有效载荷格式的变化,不包括像Apple Documentation中那样的iOS格式。
我重新检查我的APNs证书和开发一个不见了,我试图重新上传证书,它得到了类似这样的错误。
我向firebase团队提交了一份反馈,他们说这是他们最终的问题。(注:我也在上面的链接中发布了firebase团队的回应)。我的Dev APNs证书回来了,但格式仍然相同。
这是我得到的负载(来自Swift Print函数)

{
    "collapse_key" = "com.xxx.xxx";
    from = xxx;
    notification =     {
        badge = 3;
        body = "Firebase console";
        e = 1;
        title = Test;
    };
}

而这个payload使得iOS不会显示推送通知.
基于this FCM documentation for iOS
下面的代码将使应用程序崩溃时通知到来

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject],
                 fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
  // 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

  // Print message ID.
  print("Message ID: \(userInfo["gcm.message_id"]!)")

  // Print full message.
  print("%@", userInfo)
}
  • 我已经尝试重新上传我的Dev APNs证书,但仍然错误
  • 我还提交了另一个反馈,但Firebase团队尚未回复

我错过了什么吗?

    • 编辑:**

就像我上面说的,几天前它就工作了,当这个问题出现时它就崩溃了。
具体来说,这一行会使应用程序崩溃,我怀疑这是因为有效负载格式改变了(aps有效负载丢失)。

print("Message ID: \(userInfo["gcm.message_id"]!)")

代码在删除时运行良好(并生成上面),但我仍然没有得到aps有效载荷格式,所以当应用程序在后台时,通知永远不会弹出。此外,我的通知处理程序将不工作时,应用程序在前台。

    • 编辑2**:

我已在AppDelegate中注册通知

let setting = UIUserNotificationSettings(forTypes: [.Sound, .Alert, .Badge] , categories: nil)
    application.registerUserNotificationSettings(setting)
    application.registerForRemoteNotifications()

我知道这一点,并已启用推送通知和远程通知后台模式。

    • 编辑2016年6月28日**:

我再次尝试从firebase控制台推送通知,仍然得到了相同的有效载荷格式

%@ [notification: {
    badge = 2;
    body = "Test Message";
    e = 1;
    sound = default;
    sound2 = default;
    title = Test;
}, collapse_key: com.xxx, from: 717xxxxxx]

我的FCM Firebase控制台设置如下所示

    • 编辑2016年7月8日**:

这是我的AppDelegate代码

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, GIDSignInDelegate {

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

        // Firebase 
        let setting = UIUserNotificationSettings(forTypes: [.Sound, .Alert, .Badge] , categories: nil)
        application.registerUserNotificationSettings(setting)
        application.registerForRemoteNotifications()

        FIRApp.configure()

        print(FIRInstanceID.instanceID().token())

        FIRAnalytics.logEventWithName(kFIREventAppOpen, parameters: nil)

        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(tokenRefreshNotificaiton), name: kFIRInstanceIDTokenRefreshNotification, object: nil)

        return true
    }

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

    func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
        // 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

        // Print message ID.
//        print("Message ID: \(userInfo["gcm.message_id"]!)")

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

        var body = ""
        var title = "20Fit"

        guard let aps = userInfo["aps"] as? [String : AnyObject] else {
            print("Error parsing aps")
            return
        }

        if let alert = aps["alert"] as? String {
            body = alert
        } else if let alert = aps["alert"] as? [String : String] {
            body = alert["body"]!
            title = alert["title"]!
        }

        let banner = Banner(title: title, subtitle: body, image: nil, backgroundColor: UIColor.blackColor(), didTapBlock: nil)
        banner.show(duration: 5.0)
    }

    func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
           FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: .Sandbox)
    }

    func tokenRefreshNotificaiton(notification: NSNotification) {
        let refreshedToken = FIRInstanceID.instanceID().token()!
        print("InstanceID token: \(refreshedToken)")

        sendTokenToServer()

        // Connect to FCM since connection may have failed when attempted before having a token.
        connectToFcm()
    }

    func applicationWillResignActive(application: UIApplication) {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
    }

    func applicationDidEnterBackground(application: UIApplication) {
        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
        FIRMessaging.messaging().disconnect()
        print("Disconnected from FCM")
    }

    func applicationWillEnterForeground(application: UIApplication) {
        // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
    }

    func applicationDidBecomeActive(application: UIApplication) {
        connectToFcm()
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }

    func applicationWillTerminate(application: UIApplication) {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
        FIRAnalytics.logEventWithName("app_terminated", parameters: nil)
    }

}

以下是我的应用程序的完整日志

2016-07-08 19:26:48.022 20FIT Member[2525:1122556] WARNING: Firebase Analytics App Delegate Proxy is disabled. To log deep link campaigns manually, call the methods in FIRAnalytics+AppDelegate.h.
2016-07-08 19:26:48.273 20FIT Member[2525:1122556] Configuring the default app.
2016-07-08 19:26:48.318 20FIT Member[2525:] <FIRAnalytics/DEBUG> Debug mode is on
2016-07-08 19:26:48.338 20FIT Member[2525:] <FIRAnalytics/INFO> Firebase Analytics v.3200000 started
2016-07-08 19:26:48.338 20FIT Member[2525:] <FIRAnalytics/INFO> To enable debug logging set the following application argument: -FIRAnalyticsDebugEnabled (see google link)
2016-07-08 19:26:48.343: <FIRInstanceID/WARNING> Failed to fetch APNS token Error Domain=com.firebase.iid Code=1001 "(null)"
2016-07-08 19:26:48.350: <FIRMessaging/INFO> FIRMessaging library version 1.1.0
2016-07-08 19:26:48.339 20FIT Member[2525:] <FIRAnalytics/DEBUG> Debug logging enabled
2016-07-08 19:26:48.365 20FIT Member[2525:] <FIRAnalytics/DEBUG> Uploading data. Host: https://play.googleapis.com/log
2016-07-08 19:26:48.366 20FIT Member[2525:] <FIRAnalytics/DEBUG> Firebase Analytics is monitoring the network status
Optional("cXwsIWfiJas:APA91bGjUnL-oztH9LntO4EaKdJxPQN_-Za5ydC-hPR-_HPZXNm4m_mzqSztvbBG7HczNN5Jr7Btr8h4ETF5FyOOUn8Ombk4c3RoTL6GDFrh6BnG0ECs_r_Hqx1dnVHeJVwLQo4JInn2")
2016-07-08 19:26:48.406 20FIT Member[2525:] <FIRAnalytics/DEBUG> Successfully parsed a configuration. Version: 1464617411301000
2016-07-08 19:26:48.429 20FIT Member[2525:] <FIRAnalytics/DEBUG> Firebase Analytics is ready to receive events
2016-07-08 19:26:48.432 20FIT Member[2525:] <FIRAnalytics/DEBUG> No network. Upload task will not be scheduled
2016-07-08 19:26:48.434 20FIT Member[2525:] <FIRAnalytics/DEBUG> Cancelling background upload task.
2016-07-08 19:26:48.437 20FIT Member[2525:] <FIRAnalytics/DEBUG> Scheduling user engagement timer
2016-07-08 19:26:48.438 20FIT Member[2525:] <FIRAnalytics/DEBUG> Timer scheduled to fire in approx. (s): 3600
2016-07-08 19:26:48.441 20FIT Member[2525:] <FIRAnalytics/INFO> Firebase Analytics enabled
2016-07-08 19:26:48.445 20FIT Member[2525:] <FIRAnalytics/DEBUG> Logging event: origin, name, params: app, app_open, {
        "_o" = app;
    }
2016-07-08 19:26:48.477 20FIT Member[2525:] <FIRAnalytics/DEBUG> Scheduling user engagement timer
2016-07-08 19:26:48.478 20FIT Member[2525:] <FIRAnalytics/DEBUG> Canceling active timer
2016-07-08 19:26:48.479 20FIT Member[2525:] <FIRAnalytics/DEBUG> Timer scheduled to fire in approx. (s): 3600
2016-07-08 19:26:48.562 20FIT Member[2525:] <FIRAnalytics/DEBUG> Network status has changed. code, status: 2, Connected
2016-07-08 19:26:48.566 20FIT Member[2525:] <FIRAnalytics/DEBUG> Network status has changed. code, status: 2, Connected
2016-07-08 19:26:48.618 20FIT Member[2525:] <FIRAnalytics/DEBUG> Event logged. Event name, event params: app_open, {
        "_o" = app;
    }
2016-07-08 19:26:48.635 20FIT Member[2525:] <FIRAnalytics/DEBUG> Timer scheduled to fire in approx. (s): 3143.319384038448
2016-07-08 19:26:48.636 20FIT Member[2525:] <FIRAnalytics/DEBUG> Upload task scheduled to be executed in approx. (s): 3143.319384038448
2016-07-08 19:26:48.637 20FIT Member[2525:] <FIRAnalytics/DEBUG> Do not schedule an upload task. Task already exists
2016-07-08 19:26:48.710 20FIT Member[2525:] <FIRAnalytics/DEBUG> Received SSL challenge for host. Host: https://play.googleapis.com/log
2016-07-08 19:26:49.408 20FIT Member[2525:] <FIRAnalytics/DEBUG> Uploading data. Host: https://play.googleapis.com/log
Connected to FCM.
2016-07-08 19:26:49.869 20FIT Member[2525:] <FIRAnalytics/DEBUG> Received SSL challenge for host. Host: https://play.googleapis.com/log
2016-07-08 19:26:50.206 20FIT Member[2525:] <FIRAnalytics/DEBUG> Uploading data. Host: https://play.googleapis.com/log
2016-07-08 19:26:50.723 20FIT Member[2525:] <FIRAnalytics/DEBUG> Received SSL challenge for host. Host: https://play.googleapis.com/log
%@ [notification: {
    badge = 2;
    body = "Test Message";
    e = 1;
    sound = default;
    sound2 = default;
    title = Yoiii;
}, collapse_key: com.xxx.xxx, from: 717xxxx]
Error parsing aps
lkaoscv7

lkaoscv71#

我也有同样的问题
关于FCM指南的这一部分:www.example.com https://firebase.google.com/docs/cloud-messaging/ios/client#swizzling_disabled_receive_messages_through_the_messaging_apns_interface
我解决了添加setAPNSToken:type:的问题

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    [[FIRInstanceID instanceID] setAPNSToken:deviceToken type:FIRInstanceIDAPNSTokenTypeSandbox];
}

之后,fcm开始发送push,其有效载荷格式正确适用于iOS。
当然对于生产环境使用FIRInstanceIDAPNSTokenTypeProd

mutmk8jj

mutmk8jj2#

你打印的“有效载荷”在我看来是正确的。但是,请注意,这不是APN有效载荷。它实际上是一个用户信息字典。如果我理解你的问题,你似乎担心"aps"字段丢失。您不会在用户信息字典中看到该字段。
你是在真实设备上运行还是在模拟器中运行?请记住,模拟器无法显示远程通知,在真实设备上,应用程序需要在后台显示通知。
尝试发送本地通知(安排30秒时间):

localNotif.fireDate = [[NSDate date] dateByAddingTimeInterval:30];

然后按home键等待。

slsn1g29

slsn1g293#

您提供的“有效负载”(大概是)由didReceiveRemoteNotification方法的最后一行产生,即:print("%@", userInfo)
你声称上面的代码使应用程序崩溃,这与成功打印到日志的代码相矛盾。
我觉得你的应用程序被别的东西给破坏了。你看过系统日志了吗?(如果您使用的是模拟器,请转到Debug>Open System Log)。
我建议运行Firebase演示应用程序(pod try Firebase),以说服自己它正如你所期望的那样工作。

8fq7wneg

8fq7wneg4#

我正在调查为什么你的gcm.message_id是空的,给予我几天时间。
若要在应用处于后台时无法收到通知,请确保您已注册远程通知,如快速入门示例所示(请参阅didFinishLaunchingWithOptions):https://github.com/firebase/quickstart-ios/blob/master/messaging/FCMSwift/AppDelegate.swift
另外,确保在Xcode中设置了允许处理后台通知的功能。

qni6mghb

qni6mghb5#

同样的问题。此外,带有键'aps'的Firebase消息似乎不会在使用控制台发送时传递。必须是一些错误与Firebase改变负载格式。
关于在后台模式下获取Firebase通知,在这种情况下,我认为iOS不会识别有效载荷格式->根本没有通知。后台读取Firebase消息,切换到后台模式时不要调用FIRMessaging.messaging().disconnect()。然后你应该得到你的消息并通过你自己的句柄处理它(仍然没有系统通知)。

n6lpvg4x

n6lpvg4x6#

我浏览了苹果的开发者论坛,似乎didRegisterForRemoteNotificationsWithDeviceToken不能在沙箱模式下工作,只能在生产环境下工作。didRegisterForRemoteNotificationsWithDeviceToken是我在firebase注册deviceToken的地方。由于没有发生这种情况,Firebase发送了带有notification密钥的有效载荷,因为它不知道该设备是苹果。今天苹果解决了这个问题,现在我可以发送通知了。

x8goxv8g

x8goxv8g7#

我有同样的问题,我添加了‘高‘优先级,它为我工作!

{
    "collapse_key" :"com.xxx.xxx",
    to: "xxx",
    priority : "high",
    notification :{..}
}
ckx4rj1h

ckx4rj1h8#

为了强制ios模拟器消化.apns,指定为firebase“aps”字典必须复制并粘贴到“apns”和Co旁边的顶层。

kuhbmx9i

kuhbmx9i9#

切换您的wifi/移动的数据将做的技巧。

相关问题