iOS 中的推送通知突然无法通过 Firebase 传递

Posted

技术标签:

【中文标题】iOS 中的推送通知突然无法通过 Firebase 传递【英文标题】:Push notifications in iOS suddenly not delivering via Firebase 【发布时间】:2020-06-29 20:48:02 【问题描述】:

最近我停止接收 Firebase Cloud Messaging APNs 通知。我决定更新到最新版本的 Firebase pod,而我的 AppDelegate.swift 有一些功能已弃用,因此它现在看起来像这样:

import UIKit
import SwiftyJSON
import IQKeyboardManagerSwift
import Firebase
import FirebaseInstanceID
import FirebaseMessaging
import UserNotifications
import AVFoundation
import Crittercism


@UIApplicationMain

class AppDelegate: UIResponder, UIApplicationDelegate, MessagingDelegate, UNUserNotificationCenterDelegate 
    
    var window: UIWindow?
    var isPulltoRefreshInProgress: Bool = Bool(false)
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool 
        
        Crittercism.enable(withAppID: Config.sharedInstance.apteligentAppID())

        //To find Home Directory
        print("Home Directory - \(NSHomeDirectory())")
        IQKeyboardManager.shared.enable = true
        IQKeyboardManager.shared.enableAutoToolbar = false
        IQKeyboardManager.shared.shouldShowToolbarPlaceholder = false
        // IQKeyboardManager.shared.shouldResignOnTouchOutside = true
      //  UIApplication.shared.statusBarStyle = .lightContent
        configureForPushNotification()
        registrationForNotification(application: application )
        self.startOver()
        
        return true
    
    
    func registrationForNotification(application: UIApplication) 
        // ios 10 support
        if #available(iOS 10, *) 
            DLog("registrationForNotification")
            UNUserNotificationCenter.current().delegate = self
            UNUserNotificationCenter.current().requestAuthorization(options:[.badge, .alert, .sound]) (granted, error) in 
            application.registerForRemoteNotifications()
        
        else 
            application.registerForRemoteNotifications(matching: [.badge, .sound, .alert])
        
    
    
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) 
        
        Tokens.sharedInstance.isNotificationCame = true
        NotificationCenter.default.post(name: NSNotification.Name(NotificationCenterIDs.kPushNotificationReceivedNotification), object:self)
        
        if application.applicationState == UIApplication.State.active 
            DLog("App is in foreground when notification received")
            // app was already in the foreground
         else 
            DLog("App was just brought from background to foreground via PUSH")
            // app was just brought from background to foreground via PUSH
            self.startOver()
        
    
    
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) 
//      let application = UIApplication.shared
      
//      if(application.applicationState == .active)
//        DLog("user tapped the notification bar when the app is in foreground")
        if let window = self.window 
            if let viewController = UIStoryboard(name: StoryboardControllerIDs.kStoryboardId, bundle: nil).instantiateViewController(withIdentifier: StoryboardController.kNotificationsViewController) as? NotificationsViewController
                if let rootViewController = window.rootViewController as? UINavigationController
//                    DLog("Root: " + String(describing: type(of: rootViewController)))
                    Tokens.sharedInstance.isNotificationCame = true
                    rootViewController.pushViewController(viewController, animated: true)
                
            
        
//      
      
//      if(application.applicationState == .inactive)
//      
//        DLog("user tapped the notification bar when the app is in background")
//      
      
      /* Change root view controller to a specific viewcontroller */
      // let storyboard = UIStoryboard(name: "Main", bundle: nil)
      // let vc = storyboard.instantiateViewController(withIdentifier: "ViewControllerStoryboardID") as? ViewController
      // self.window?.rootViewController = vc
      
      completionHandler()
    
    
    func configureForPushNotification() 
        var fileName : String = "GoogleServiceQA-Info"
        
        let currentConfiguration = Bundle.main.object(forInfoDictionaryKey: "Config")! as! String
        
        if currentConfiguration.lowercased() == "production" 
            fileName = "GoogleServiceProd-Info"
         
        
        let filePath = Bundle.main.path(forResource: fileName, ofType: "plist")!
        let options = FirebaseOptions(contentsOfFile: filePath)
        FirebaseApp.configure(options: options!)
        Messaging.messaging().delegate = self
        
//        if let refreshedToken = InstanceID.instanceID().token() 
//            print("InstanceID token: \(refreshedToken)")
//            DeviceTokenConstants.deviceToken = refreshedToken
//        
        InstanceID.instanceID().instanceID  (result, error) in
            if let error = error 
                DLog("Error fetching remote instange ID: \(error)")
             else if let result = result 
                DLog("configureForPushNotification - Remote instance ID token: \(result.token)")
                DeviceTokenConstants.deviceToken = result.token
            
        
        
        NotificationCenter.default.addObserver(self, selector:
            #selector(tokenRefreshNotification), name:
            NSNotification.Name.InstanceIDTokenRefresh, object: nil)
    
    
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) 
        //Getting errors in Xcode10 for iOS12
        let hexString = deviceToken.map  String(format: "%02.2hhx", $0) .joined()
        DLog("===DEVICE-TOKEN: \(hexString)")
        // In debug mode
        Messaging.messaging().apnsToken = deviceToken
        Messaging.messaging().setAPNSToken(deviceToken, type: .sandbox)
        Messaging.messaging().setAPNSToken(deviceToken, type: .prod)
        // In release mode
//        InstanceID.instanceID().setAPNSToken(deviceToken, type: InstanceIDAPNSTokenType.prod)
    
    
    // This method will be called when app received push notifications in foreground
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void)
    
        completionHandler([.alert, .badge, .sound])
    
    
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) 
        print("Firebase registration token: \(fcmToken)")
        DeviceTokenConstants.deviceToken = fcmToken
        FireBaseToken.didReceived = true
    
    
    @objc func tokenRefreshNotification(_ notification: Notification) 
        
        InstanceID.instanceID().instanceID  (result, error) in
        if let error = error 
            print("Error fetching remote instange ID: \(error)")
         else if let result = result 
            print("tokenRefreshNotification - Remote instance ID token: \(result.token)")
            DeviceTokenConstants.deviceToken = result.token
            let dataDict:[String: String] = ["token": result.token]
            NotificationCenter.default.post(name: Notification.Name("FCMToken"), object: nil, userInfo: dataDict)
         
        

//        Deprecated code
//        if let refreshedToken = InstanceID.instanceID().token() 
//            print("InstanceID token: \(refreshedToken)")
//            DeviceTokenConstants.deviceToken = refreshedToken
//        
        // Connect to FCM since connection may have failed when attempted before having a token.
//        connectToFcm()
    

此代码中是否有某些内容可能会阻止发送通知,或者这是 iOS 应用程序之外的外部问题?我可以看到在我的控制台中为设备令牌和 fcm 令牌打印了令牌,所以我觉得 iOS 应用程序中的设置不是问题。我确保我的 iPhone 中没有禁用应用通知。

【问题讨论】:

【参考方案1】:

如果您使用keyid而不是证书,您可以尝试将您的调试模式更改为发布模式,然后您可以尝试查看是否收到推送,或者您可以上传到TestFlight并检查是否收到推送。 但是最好使用证书而不是可以在调试和发布模式下使用的 keyid。

【讨论】:

在 APNs 证书中的认证?如果是这样,那么这就是我正在使用的 你有发布和调试apn认证吗? 我在控制台上传了一个开发 APN 证书,而发行版有自己的项目,该项目只导入了生产 APNs 证书 两者分配的捆绑包 ID 略有不同,因此它们的设置方式允许它们被视为 2 个不同的应用程序。【参考方案2】:

我从您的代码中不明白为什么它不起作用,您是否尝试过关注firebase's guide 的信函?它从来没有给我带来任何问题。

【讨论】:

我想是我上传的APNS证书。这需要先得到确认。一旦他们向我发送正确的证书,就会更新您。我可能必须在 Firebase 控制台的生产 APNs 证书中上传推送证书。

以上是关于iOS 中的推送通知突然无法通过 Firebase 传递的主要内容,如果未能解决你的问题,请参考以下文章

为啥推送通知不能在 iOS 中使用 Firebase 从设备到设备?

iOS Swift 使用 Firebase 云消息发送丰富的推送通知

在应用程序被杀死后,使用 HTTP 请求通过 Firebase(FCM)向 iOS 设备发送推送通知 [重复]

无法使用java在IOS中发送firebase推送通知

如何使用 react-native-firebase 在 iOS 设备的推送通知中添加按钮?

IONIC FCM推送通知ios,无法接收