簡體   English   中英

Swift & FCM:從后台切換到前台時如何獲取推送通知數據?

[英]Swift & FCM : How to get push notification data when switching from Background to Foreground?

我正在 Swift 中配置推送通知。 到目前為止,我有 3 個場景。

1 - App In Foreground 在前台,我認為我做的一切都是正確的,因為我確實收到了推送通知數據。

func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent notification: UNNotification,
                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        
        print("userNotificationCenter willPresent")
        let content = notification.request.content
        FCMManager.shared.notificationHandler(with: content)
        
        UIApplication.shared.applicationIconBadgeNumber = 0
        UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
        
        completionHandler([.alert, .sound])
        
    }

2 - 用戶點擊推送通知橫幅 這也工作正常。

func userNotificationCenter(_ center: UNUserNotificationCenter,
                                didReceive response: UNNotificationResponse,
                                withCompletionHandler completionHandler: @escaping () -> Void) {
        print("userNotificationCenter didReceive")
       defer {
           completionHandler()
       }
       guard response.actionIdentifier == UNNotificationDefaultActionIdentifier else {
           return
       }
        
        let content = response.notification.request.content
        FCMManager.shared.notificationHandler(with: content)
        
        
        UNUserNotificationCenter.current().removeAllDeliveredNotifications()
    }

3 - 應用在后台,然后用戶進入應用在這種情況下,推送通知到達用戶的手機。 但是,他們不是點擊推送通知本身,而是進入應用程序。 我無法從推送通知中獲取任何信息

任何人都可以幫助如何配置第三個場景? 謝謝你。

完整代碼

import UIKit
import Firebase
import FirebaseMessaging
import UserNotifications

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        FirebaseApp.configure()
        //        application.registerForRemoteNotifications()
        setupNotification(on: application)
        //        UIApplication.shared.applicationIconBadgeNumber = 0
        
        return true
    }
    
    // MARK: UISceneSession Lifecycle
    
    func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
        return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
    }
    
    func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
    }
    
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        print("Received data message: \(userInfo)")
        
        let name = Notification.Name(rawValue: K.Event.pushRequest)
        NotificationCenter.default.post(name: name, object: nil)
        
        completionHandler(.newData)
    }
    
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        print("deviceToken : \(deviceToken)")
    }
    
    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        print("Error : \(error.localizedDescription)")
    }
    
}

//MARK: - UNUserNotificationCenterDelegate
// [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) {
        
        print("userNotificationCenter willPresent")
        let content = notification.request.content
        FCMManager.shared.notificationHandler(with: content)
        
        UIApplication.shared.applicationIconBadgeNumber = 0
        UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
        
        completionHandler([.alert, .sound])
        
    }
    
    // When user click on push notification
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                didReceive response: UNNotificationResponse,
                                withCompletionHandler completionHandler: @escaping () -> Void) {
        print("userNotificationCenter didReceive")
       defer {
           completionHandler()
       }
       guard response.actionIdentifier == UNNotificationDefaultActionIdentifier else {
           return
       }
        
        let content = response.notification.request.content
        FCMManager.shared.notificationHandler(with: content)
        
        
        UNUserNotificationCenter.current().removeAllDeliveredNotifications()
    }
    
}

//MARK: - MessagingDelegate
extension AppDelegate : MessagingDelegate {
    // [START refresh_token]
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
        print("Firebase registration token: \(String(describing: fcmToken))")
        
        let dataDict:[String: String] = ["token": fcmToken ?? ""]
        
        NotificationCenter.default.post(name: Notification.Name("FCMToken"), object: nil, userInfo: dataDict)
        
    }
    // [END refresh_token]
}

extension AppDelegate {
    func setupNotification(on application: UIApplication) {
        let notificationCenter = UNUserNotificationCenter.current()
        notificationCenter.delegate = self
        Messaging.messaging().delegate = self
        notificationCenter.requestAuthorization(options: [.alert, .sound]) { granted, error in
            if let error = error {
                print("Failed to requestion authorization for notification center:  \(error.localizedDescription)")
                return
            }
            
            guard granted else {
                print("Failed to requestion authorization for notification center: not granted")
                return
            }
            
            DispatchQueue.main.async {
                application.registerForRemoteNotifications()
            }
            
        }
//        application.registerForRemoteNotifications()
    }
}

你需要考慮applicationState

UIApplication.State

//AppDelegate
func application(_ application: UIApplication,
                 didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                 fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    
    switch UIApplication.shared.applicationState {
    case .active:
        print("Received push message from APNs on Foreground")
    case .background:
        print("Received push message from APNs on Background")
    case .inactive:
        print("Received push message from APNs back to Foreground")
    }
}

當應用從后台到前台時, UIApplication.State inactive

inactive 是 '應用程序在前台運行但未接收事件。 '

因此,我認為執行您想要的行為的最佳方法是自己編寫。

例如,

//AppDelegate
func application(_ application: UIApplication,
                 didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                 fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    
    switch UIApplication.shared.applicationState {
    case .active:
        print("Received push message from APNs on Foreground")
    case .background:
        print("Received push message from APNs on Background")
    case .inactive:
        print("Received push message from APNs back to Foreground")

        guard let nav = window?.rootViewController as? UINavigationController,
              let currentVC = nav.viewControllers.last else {return}

        if currentVC is 'youWantViewController' { //if you want ViewController, use notification post
            let name = Notification.Name(rawValue: K.Event.pushRequest)
            NotificationCenter.default.post(name: name, object: nil)
        } else { //move to you want ViewController
           let vc = 'yourViewController'()
           root.navigationController?.pushViewController(vc, animated: true)
        }
    }

    completionHandler(.newData)
}

我希望它會有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM