首页 > 解决方案 > iOS 中的推送通知突然无法通过 Firebase 传递

问题描述

最近我停止接收 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 中没有禁用应用程序通知。

标签: iosswiftfirebasepush-notificationfirebase-cloud-messaging

解决方案


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


推荐阅读