ios - 如何在推送通知 iOS Swift 中终止应用程序时调用 API?

标签 ios swift firebase push-notification

我们正在处理推送通知。当我们在事件、后台、前台和终止时收到通知时,我们需要调用 Web 服务。但是当我们终止应用程序时,我们会收到通知但无法调用网络服务。调用网络服务的原因是为了识别消息是为移动应用程序接收的。

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        if ( application.applicationState == .inactive || application.applicationState == .background ) {
                **// Need to call API**
        }
    }

有没有其他方法可以识别消息是在服务器端的移动应用程序中传递的?

最佳答案

As per Apple guidelines, you can get push notification for the background as well as on foreground state but when it comes to Terminate state apple don't allow you to automatically open the app or do any kind of operation unless you launch the app through notification.

虽然您可以在应用启动时使用启动选项处理终止状态期间的通知。

代码示例:

在你的 AppDelegate.swift 中导入 firebase 库

import Firebase
import FirebaseInstanceID
import FirebaseMessaging
import UserNotifications

每当应用启动注册推送通知服务时,将以下代码行添加到您的 didFinishLaunchingWithOptions

func application(_ application: UIApplication,
                 didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    registerForPushNotifications(application: application)
    handleNotificationWhenAppIsKilled(launchOptions)
    return true
}

func handleNotificationWhenAppIsKilled(_ launchOptions: [UIApplicationLaunchOptionsKey: Any]?) {
    // Check if launched from the remote notification and application is close
    if let remoteNotification = launchOptions?[.remoteNotification] as?  [AnyHashable : Any] {
        // Handle your app navigation accordingly and update the webservice as per information on the app.
    }
}

添加appDelegate的扩展方法,用于注册远程通知和从APNS获取设备 token

//MARK: - Notifications related...
extension AppDelegate {
    func registerForPushNotifications(application: UIApplication) {
        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 })
            // For iOS 10 data message (sent via FCM
            Messaging.messaging().delegate = self
        } else {
            let settings: UIUserNotificationSettings =
                UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
            application.registerUserNotificationSettings(settings)
        }

        application.registerForRemoteNotifications()
    }

    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
        let savedAPNSToken = UserDefaults.standard.object(forKey: "savedAPNSToken") as? String
        if savedAPNSToken != token {
            UserDefaults.standard.set(token, forKey: "savedAPNSToken")
            UserDefaults.standard.synchronize()
            Messaging.messaging().apnsToken = deviceToken
        }
    }

    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        print(error.localizedDescription)
    }

    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                     fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        completionHandler(UIBackgroundFetchResult.newData)
    }

}

使用notificationCenter的以下方法处理前台和后台状态的通知:

// MARK: - UNUserNotificationCenterDelegate
@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
        completionHandler([.alert])
    }


    /// Handle tap on the notification banner
    ///
    /// - Parameters:
    ///   - center: Notification Center
    ///   - response: Notification response
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                didReceive response: UNNotificationResponse,
                                withCompletionHandler completionHandler: @escaping () -> Void) {

        let userInfo = response.notification.request.content.userInfo
        completionHandler()
    }

Firebase token 更新:

extension AppDelegate : MessagingDelegate {
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
        // Note: This callback is fired at each app startup and whenever a new token is generated.
        let savedFCMToken = UserDefaults.standard.object(forKey: "savedFCMToken") as? String
        if savedFCMToken != fcmToken {
            UserDefaults.standard.set(fcmToken, forKey: "savedFCMToken")
            UserDefaults.standard.synchronize()
            // Update FCMToken to server by doing API call...
        }
    }
}

关于ios - 如何在推送通知 iOS Swift 中终止应用程序时调用 API?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54236296/

相关文章:

ios - 如何过滤时间戳数组以保持特定时间?

swift - 在 View 上添加约束

swift - 观察 Realm 变化不触发

ios - 导航 View Controller 中的 SplitviewController

swift - 如果用户已存在于数据库中,则拒绝创建用户

firebase - 多对多使用 Firebase

ios - NSURLConnection 在另一个线程中启动。未调用委托(delegate)方法

ios - 返回 {AppName} 未显示 | iOS9 开放网址

ios - mac/ios 从命令行设置 webrtc 并创建 .bash_profile

firebase - 使用 Firebase 托管初始化脚本创建 react 应用程序