推送通知已交付,但 didReceiveRemoteNotification 从未被称为 Swift

Posted

技术标签:

【中文标题】推送通知已交付,但 didReceiveRemoteNotification 从未被称为 Swift【英文标题】:Push Notifications are delivered but didReceiveRemoteNotification is never called Swift 【发布时间】:2019-05-30 10:17:19 【问题描述】:

我已通过 FCM 在我的两个相关应用中成功实现推送通知,并尝试实现一些逻辑以在收到通知时增加徽章编号。

我意识到 didReceiveRemoteNotificationdelegate 方法根本没有被调用,因为我没有得到任何打印,但我确实从 willPresent notificationdidReceive response 得到打印。所以在didFinishLaunchingWithOptions中设置UIApplication.shared.applicationIconBadgeNumber没有效果,但是在里面设置didReceive response可以。

应该调用文档didReceiveRemoteNotification,但是当通知到达时我从来没有打印出来。

我尝试将整个 didReceiveRemoteNotificationmethod 注释掉,但通知仍会发送。

为什么会这样?我想我真的不明白谁在这个设置中处理消息。你能帮我澄清一下吗?

AppDelegate 方法:

didFinishLaunchingWithOptions:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool 
        window?.tintColor = UIColor.blue
        // Use Firebase library to configure APIs
        FirebaseApp.configure()
        Messaging.messaging().delegate = self
        Crashlytics().debugMode = true
        Fabric.with([Crashlytics.self])
        // setting up notification delegate
        if #available(ios 10.0, *) 
            //iOS 10.0 and greater
            UNUserNotificationCenter.current().delegate = self
            let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
            //Solicit permission from the user to receive notifications
            UNUserNotificationCenter.current().requestAuthorization(options: authOptions, completionHandler:  granted, error in
                DispatchQueue.main.async 
                    if granted 
                        print("didFinishLaunchingWithOptions iOS 10: Successfully registered for APNs")
                        UIApplication.shared.registerForRemoteNotifications()
//                        UIApplication.shared.applicationIconBadgeNumber = 1
                        AppDelegate.badgeCountNumber = 0
                        UIApplication.shared.applicationIconBadgeNumber = 0
                     else 
                        //Do stuff if unsuccessful...
                        print("didFinishLaunchingWithOptions iOO 10: Error in registering for APNs: \(String(describing: error))")
                    
                
            )
         else 
            //iOS 9
            let type: UIUserNotificationType = [UIUserNotificationType.badge, UIUserNotificationType.alert, UIUserNotificationType.sound]
            let setting = UIUserNotificationSettings(types: type, categories: nil)
            UIApplication.shared.registerUserNotificationSettings(setting)
            UIApplication.shared.registerForRemoteNotifications()
//            UIApplication.shared.applicationIconBadgeNumber = 1
            UIApplication.shared.applicationIconBadgeNumber = 0
            print("didFinishLaunchingWithOptions iOS 9: Successfully registered for APNs")
        
        // setting up remote control values
        let _ = RCValues.sharedInstance
        GIDSignIn.sharedInstance().clientID = FirebaseApp.app()?.options.clientID
        Crashlytics().debugMode = true
        Fabric.with([Crashlytics.self])
        //        // TODO: Move this to where you establish a user session
        //        self.logUser()
        var error: NSError?
        do 
            try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
         catch let error1 as NSError
            error = error1
            print("could not set session. err:\(error!.localizedDescription)")
        
        do 
            try AVAudioSession.sharedInstance().setActive(true)
         catch let error1 as NSError
            error = error1
            print("could not active session. err:\(error!.localizedDescription)")
        
        // goggle only
        GIDSignIn.sharedInstance().clientID = FirebaseApp.app()?.options.clientID
//        GIDSignIn.sharedInstance().delegate = self
        // Facebook SDK
        return FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
//        return true
    

didReceiveRemoteNotification:

 // foreground
        func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) 
            print("didReceiveRemoteNotification: Received new push Notification")
            // 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)
            AppDelegate.badgeCountNumber += userInfo["badge"] as! Int
            print("AppDelegate.badgeCountNumber is : \(String(describing: AppDelegate.badgeCountNumber))")
//            UIApplication.shared.applicationIconBadgeNumber = AppDelegate.badgeCountNumber
            UIApplication.shared.applicationIconBadgeNumber =  10//AppDelegate.badgeCountNumber
            // Print full message.
            print("didReceiveRemoteNotification: Push notificationMessage is: \(userInfo)")
        




        // background
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                     fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) 
        print("didReceiveRemoteNotification with handler : Received new push Notification while in background")
        // 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)
        if let messageID = userInfo[ userDetails.fcmToken]  // working for looged in
            print("didReceiveRemoteNotification: Message ID: \(messageID)")
        

        // Print full message.
        print("didReceiveRemoteNotification: Push notificationMessage is: \(userInfo)")
        AppDelegate.badgeCountNumber += userInfo["badge"] as! Int
        print("AppDelegate.badgeCountNumber is : \(String(describing: AppDelegate.badgeCountNumber))")
        UIApplication.shared.applicationIconBadgeNumber +=  userInfo["badge"] as! Int
        completionHandler(UIBackgroundFetchResult.newData)
    

【问题讨论】:

请检查您添加的 didReceiveRemoteNotification 委托方法是否已弃用? @Ranjani 我更新了代码以显示didReceiveRemoteNotificationcode。不,我没有收到任何关于它被贬值的警告。关于发生了什么的任何想法?应该叫吧? 由于我即将实现丰富的远程通知,这是我必须在开始之前解决的问题,否则我猜这会很沮丧.. 请出示 didReceiveRemoteNotification 声明代码并参考此链接***.com/questions/35724945/… @Ranjani 我确实提出了didReceiveRemoteNotification 代码问题。感谢您的链接 【参考方案1】:

我终于找到了解决办法。警报需要"content_available": true 在从 App2 到 App1 的帖子发送功能的警报定义中设置,否则通知会被传递,但不会调用“didReceiveRemoteNotification”,并且您不能使用“userInfo”。希望这对其他人有所帮助,因为我没有找到有关此问题的太多信息。如果您使用 Postman 或类似工具设置通知,请在此处查看 didReceiveRemoteNotification function doesn't called with FCM notification server,因为这是我在此问题上找到的唯一帖子并解决了我的问题。 感谢@Ranjani 尝试帮助我。

let postParams: [String : Any] = [
                "to": receiverToken,
                "notification": [
                    "badge" : 1,
                    "body": body,
                    "title": title,
                    "subtitle": subtitle,
                    "sound" : true, // or specify audio name to play
                    "content_available": true, // this will call didReceiveRemoteNotification in receiving app, else won't work
                    "priority": "high"
                ],
                "data" : [
                    "data": "ciao",
            ]
                ]

【讨论】:

不适合我的情况T_T 即使答案没有这么说,这个答案中的代码是用于 FIREBASE CLOUD MESSAGING ("FCM"),并且不会帮助任何其他推送通知服务。 (唯一的其他提示是添加到问题中的标签。) @RobinDaugherty 嗨,事实上,答案是针对 FCM,因为问题是关于 FCM。但好点。谢谢。【参考方案2】:

对于 Node.js(发送到主题示例)

var admin = require("firebase-admin");

var serviceAccount = require("path/to/serviceAccountKey.json");

admin.initializeApp(
    credential: admin.credential.cert(serviceAccount),
    databaseURL: "<your database URL>"
);

var topic = "topicA";

var payload = 
    notification: 
        title: "title",
        body: "body",
        sound: "default"
    ,
    data: 
        a: "dataA",
        b: "dataB"
    
;

var options = 
    content_available: true,
    priority: "high",
    timeToLive: 1
;

// Send a message to devices subscribed to the provided topic.
admin.messaging().sendToTopic(topic, payload, options)
    .then((response) => 
        // Response is a message ID string.
        console.log('Successfully sent message:', response);
    )
    .catch((error) => 
        console.log('Error sending message:', error);
    );

【讨论】:

以上是关于推送通知已交付,但 didReceiveRemoteNotification 从未被称为 Swift的主要内容,如果未能解决你的问题,请参考以下文章

如何使用消息 ID 跟踪 FCM 推送通知是不是已交付

缺少推送通知权利?

停止向 Apple 发送推送通知以进行交付

PHP - APNs 消息已交付但在 iOS 设备上未收到

为啥在 iOS10 上滑动推送通知功能不运行?

苹果推送通知错误