ios - 当应用程序在推送通知iOS Swift中终止时如何调用API?
问题描述
我们正在处理推送通知。当我们在活动、后台、前台和终止中收到通知时,我们需要调用 Web 服务。但是当我们终止应用程序时,我们会收到通知但无法调用 Web 服务。调用 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**
}
}
是否有任何其他方式来识别消息是在服务器端的移动应用程序中传递的?
解决方案
根据 Apple 指南,您可以获得后台和前台状态的推送通知,但是当涉及到终止状态时,苹果不允许您自动打开应用程序或执行任何类型的操作,除非您通过通知启动应用程序.
尽管您可以在应用程序启动时使用启动选项处理终止状态期间的通知。
编码示例:
在您的 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 获取设备令牌
//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 令牌更新:
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...
}
}
}
推荐阅读
- r - 使用 UDF 在 R 数据框中添加 6 小时
- javascript - Vue 3 过渡在开始时闪烁
- r - R函数根据重复时间组合行
- java - 将 retrfofit 与 rx java 一起使用时,观察者未捕获任何值
- java-8 - JAVA 8 和 Instant truncateTo 错误
- mysql - MariaDB 真的缓存或重用“WITH”中间结果吗?
- godot - CollisionShape2d 附加到 Bone2d
- c# - 如何使用 Task.WhenAll 一次运行 2 个计算
- regex - 厨师检查中的正则表达式
- android - gradle 的 sonarqube 插件是否生成本地报告?