iOS 12 未收到 FCM 通知

Posted

技术标签:

【中文标题】iOS 12 未收到 FCM 通知【英文标题】:iOS 12 not received FCM notifications 【发布时间】:2018-11-08 17:37:13 【问题描述】:

您好,我正在使用 XCode 版本: 10.1 (10B61) 和 iPhone SEiOS 版本: 12.0.1 (16A404),我按照文档说明正确安装了所有配置,我上传了 Auth .p8 证书和 p.12 开发和生产证书,但是当我尝试从 Firebase 控制台发送推送通知时,我没有收到任何信息,我是否遗漏了什么?还是我做错了什么?有什么帮助吗?

//
//  AppDelegate.swift
//  SpriteKit Game Demo
//
//  Created by Dennis Mostajo on 9/2/18.
//  Copyright © 2018 Mostys Studios.. All rights reserved.
//

import UIKit
import Fabric
import Crashlytics

import Firebase
import UserNotifications

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate

    var window: UIWindow?
    var navigationVC: UINavigationController?
    let gcmMessageIDKey = "gcm.message_id"

    override init() 
    // set Firebase configuration
        FirebaseApp.configure()
    

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool 
        // Override point for customization after application launch.
        debugPrint("didFinishLaunchingWithOptions")
        Fabric.with([Crashlytics.self])
        DataBaseHelper.DBUpdate() // Run migrations

        // Enable Push Notifications
        Messaging.messaging().delegate = self
        Messaging.messaging().shouldEstablishDirectChannel = true

        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()

        return true
    

    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 invalidate graphics rendering callbacks. Games should use this method to pause the game.
        debugPrint("applicationWillResignActive")
    

    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.
        debugPrint("applicationDidEnterBackground")
    

    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.
        debugPrint("applicationWillEnterForeground")
    

    func applicationDidBecomeActive(_ application: UIApplication)
    
        // 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.
        debugPrint("applicationDidBecomeActive")
    

    func applicationWillTerminate(_ application: UIApplication) 
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
        debugPrint("applicationWillTerminate")
    

    // MARK: - FIREBASE

    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any])
    
        Messaging.messaging().appDidReceiveMessage(userInfo)
        if let messageID = userInfo[gcmMessageIDKey]
        
            debugPrint("Message ID: \(messageID)")
        
        // Print full message.
        debugPrint(userInfo)
    

    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                     fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void)
    
        Messaging.messaging().appDidReceiveMessage(userInfo)
        if let messageID = userInfo[gcmMessageIDKey]
        
            debugPrint("Message ID: \(messageID)")
        
        // Print full message.
        debugPrint(userInfo)
        completionHandler(UIBackgroundFetchResult.newData)
    
    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error)
    
        debugPrint("Unable to register for remote notifications: \(error.localizedDescription)")
    

    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)
    
        debugPrint("didRegisterForRemoteNotificationsWithDeviceToken: DATA")
        let token = String(format: "%@", deviceToken as CVarArg)
        debugPrint("*** deviceToken: \(token)")
        let deviceTokenString = deviceToken.reduce("", $0 + String(format: "%02X", $1))
        debugPrint("deviceTokenString: \(deviceTokenString)")
        Messaging.messaging().apnsToken = deviceToken
//        debugPrint("Firebase Token:",InstanceID.instanceID().token() as Any)
    


// [START ios_10_message_handling]
@available(iOS 10, *)
extension AppDelegate : UNUserNotificationCenterDelegate 

    // Receive displayed notifications for iOS 10 devices.
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent notification: UNNotification,
                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) 

        //Handle the notification ON APP
        Messaging.messaging().appDidReceiveMessage(notification.request.content.userInfo)
        completionHandler([.sound,.alert,.badge])
    

    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                didReceive response: UNNotificationResponse,
                                withCompletionHandler completionHandler: @escaping () -> Void) 

        //Handle the notification ON BACKGROUND
        Messaging.messaging().appDidReceiveMessage(response.notification.request.content.userInfo)
        completionHandler()
    

// [END ios_10_message_handling]

extension AppDelegate : MessagingDelegate 
    // [START refresh_token]
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) 
        print("Firebase registration token: \(fcmToken)")
        InstanceID.instanceID().instanceID
            
                (result, error) in
                if let error = error
                
                    debugPrint("Error fetching remote instange ID: \(error)")
                
                else if let result = result
                
                    debugPrint("Remote instance ID token: \(result.token)")
                
            
        let dataDict:[String: String] = ["token": fcmToken]
        NotificationCenter.default.post(name: Notification.Name("FCMToken"), object: nil, userInfo: dataDict)
        // TODO: If necessary send token to application server.
        // Note: This callback is fired at each app startup and whenever a new token is generated.
    
    // [END refresh_token]
    // [START ios_10_data_message]
    // Receive data messages on iOS 10+ directly from FCM (bypassing APNs) when the app is in the foreground.
    // To enable direct data messages, you can set Messaging.messaging().shouldEstablishDirectChannel to true.
    func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingRemoteMessage) 
        debugPrint("Received data message: \(remoteMessage.appData)")
    
    // [END ios_10_data_message]

Pod 文件:

# Uncomment the next line to define a global platform for your project
platform :ios, '10.0'

def shared_pods
    pod 'Fabric'
    pod 'Crashlytics'
    pod 'Alamofire', '~> 4.7'
    pod 'RealmSwift'
    pod 'SwiftyJSON'
    pod 'PKHUD', '~> 5.0'
    pod 'Siren'
    pod 'Firebase/Core'
    pod 'Firebase/Messaging'
    pod 'Firebase/DynamicLinks'
    pod 'Firebase/Crash'
end

target 'Sprite Kit Game' do
  # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
  use_frameworks!
  # Pods for Sprite Kit Game
    shared_pods
end

target 'Sprite Kit GameTests' do
    # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
    use_frameworks!
    # Pods for testing
    shared_pods
end

target 'Sprite Kit GameUITests' do
    # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
    use_frameworks!
    # Pods for testing
    shared_pods
end

post_install do |installer|
    installer.pods_project.targets.each do |target|
        target.build_configurations.each do |config|
            # This works around a unit test issue introduced in Xcode 10.
            # We only apply it to the Debug configuration to avoid bloating the app size
            if config.name == "Debug" && defined?(target.product_type) && target.product_type == "com.apple.product-type.framework"
                config.build_settings['ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES'] = "YES"
            end
        end
    end
end

前台和后台都没有收到任何通知,请帮忙?

【问题讨论】:

您正在现场设备上进行测试,对吗?我记得在某处读到它只能在真实设备上运行,并且必须至少在 TestFlight 上,但我对后者可能是错误的。 是的,@Torewin 我在真正的 iPhone SE 上进行测试,我尝试了开发和发布的方式,但我都没有收到通知 【参考方案1】:

问题已解决,以更新处理来自 Firebase 控制台的消息/推送通知的这部分代码

// [START ios_10_message_handling]
@available(iOS 10, *)
extension AppDelegate : UNUserNotificationCenterDelegate 

    // Receive displayed notifications for iOS 10 devices.
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent notification: UNNotification,
                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) 

        let userInfo = notification.request.content.userInfo
        if let messageID = userInfo[gcmMessageIDKey] 
            debugPrint("Message ID: \(messageID)")
        
        debugPrint(userInfo)
        //Handle the notification ON APP
        Messaging.messaging().appDidReceiveMessage(userInfo)
        completionHandler([.sound,.alert,.badge])
    

    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                didReceive response: UNNotificationResponse,
                                withCompletionHandler completionHandler: @escaping () -> Void) 

        let userInfo = response.notification.request.content.userInfo
        if let messageID = userInfo[gcmMessageIDKey] 
            debugPrint("Message ID: \(messageID)")
        
        //Handle the notification ON BACKGROUND
        Messaging.messaging().appDidReceiveMessage(userInfo)
        completionHandler()
    

// [END ios_10_message_handling]

问题已在 GitHub 上跟踪

【讨论】:

以上是关于iOS 12 未收到 FCM 通知的主要内容,如果未能解决你的问题,请参考以下文章

iOS 12 中未提供 FCM 通知

通过 FCM 发送时未收到推送通知,但在 IOS 上通过 APN 发送时收到

如果应用程序终止,则未收到 iOS FCM 推送通知

未收到 Flutter FCM IOS 静默(仅数据)通知

IOS 上未收到 Cordova FCM 通知,而应用程序在后台

在 IOS 中未收到 FCM 推送通知。而应用程序在后台或终止。我使用 FirebaseMessaging 6.0.9 Pub