[英]Swizzling, Simulator, and Remote Push Notifications - iOS 14
關於 iOS 和Firebase Cloud Messaging (FCM)
上的遠程通知,我在 iOS 14 中遇到了奇怪的行為。
首先,我無法從 FCM 控制台向我的設備發送測試通知。 我逐字閱讀了文檔,以及一些很好的教程。 這是我的AppDelegate
:
import SwiftUI
import Firebase
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
FirebaseApp.configure()
FirebaseConfiguration.shared.setLoggerLevel(.min)
Messaging.messaging().delegate = self
UNUserNotificationCenter.current().delegate = self
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) {
(granted, error) in
print("Permission granted: \(granted)")
// 1. Check if permission granted
guard granted else {
print("Permission not granted")
return
}
// 2. Attempt registration for remote notifications on the main thread
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
}
application.registerForRemoteNotifications()
return true
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
Messaging.messaging().appDidReceiveMessage(userInfo)
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
print(userInfo)
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
Messaging.messaging().appDidReceiveMessage(userInfo)
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
print(userInfo)
completionHandler(UIBackgroundFetchResult.newData)
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("Unable to register for remote notifications: \(error.localizedDescription)")
}
}
@available(iOS 10, *)
extension AppDelegate : UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
let userInfo = notification.request.content.userInfo
Messaging.messaging().appDidReceiveMessage(userInfo)
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
print(userInfo)
completionHandler([[.banner, .sound]])
}
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
Messaging.messaging().appDidReceiveMessage(userInfo)
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
print(userInfo)
completionHandler()
}
}
extension AppDelegate: MessagingDelegate {
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
print("Firebase registration token: \(fcmToken ?? "")")
let dataDict:[String: String] = ["token": fcmToken ?? ""]
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "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.
}
func application(application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Messaging.messaging().apnsToken = deviceToken
}
}
let gcmMessageIDKey = "gcm_Message_ID_Key"
我嘗試過的其他事情:
在 Info.pList 中禁用方法Info.pList
(FirebaseAppDelegateProxyEnabled - Boolean - 0)
添加Messaging.messaging().appDidReceiveMessage(userInfo)
以在 App Delegate 中禁用 swizzling 后更新相應的方法。
將應用程序發送到后台(我們可以在應用程序運行時在前台進行測試嗎?如果它可以在前台工作,它會在前台工作嗎?)
其次,我無法向模擬器發送通知,除非我將aps file
從 Finder 拖到所述模擬器。 這個aps file
是一個 JSON 文件,可用於在模擬器上測試推送通知。 注意:“alert”鍵在 iOS 14 中已棄用。
{
"Simulator Target Bundle": "com.Example.app",
"aps": {
"sound": "default",
"badge": 1
}
}
終端命令實用程序如下所示
xcrun simctl push <device> com.Example example.apns
其中<device>
是模擬器設備標識符(如果只打開一個模擬器,您也可以使用“booted”代替設備標識符)並且example.apns
是您的文件。 我在Atom中創建了我的apns file
。
這是我在日志中得到的:
這些是我來自 FCM 控制台的報告:
我的實現一定是錯誤的。 我逐字逐句地按照它在模擬器和設備上運行。 模擬器讀取,作為默認錯誤, remote notifications are not supported in the simulator
。
出現這種情況有幾個原因:
11FG89IK4-SHEN-13H4-AJD9-SN39FNS82JR
用於模擬器。 當我在真實設備上嘗試時,終端也出現錯誤Invalid device: [identifier]
。 原因是我在Windows > Devices and Simulator
for my iPhone 中使用了設備標識符,而不是通過這種方法從控制台返回的設備令牌:
func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
let tokenParts = deviceToken.map { data in String(format: "%02.2hhx", data) }
let token = tokenParts.joined()
print("Device Token: \(token)")
}
我還使用了Push Notifications Tester而不是 FCM。 我不知道我做錯了什么。 我確定 Firebase 工具可以正常工作。 合理的東西在我這邊。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.