So, I am building iOS app with SwiftUI 2 and new Application life cycle, trying to implement AppsDelegate and Firebase push notification
here my codes sample
import SwiftUI
@main
struct App: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
var body: some Scene {
WindowGroup {
ContentView().environmentObject(AppSettings())
}
}
}
and AppDelegate
import Firebase
import FirebaseMessaging
import UserNotifications
import Foundation
import UIKit
class AppDelegate: NSObject {
let gcmMessageIDKey = "gcm.message_id"
private func setupFirebase(application: UIApplication) {
FirebaseApp.configure()
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)
}
Messaging.messaging().delegate = self
application.registerForRemoteNotifications()
}
}
extension AppDelegate: UIApplicationDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
setupFirebase(application: application)
return true
}
}
extension AppDelegate: MessagingDelegate {
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
print("Firebase registration token: \(fcmToken)")
}
}
@available(iOS 10, *)
extension AppDelegate: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
let userInfo = notification.request.content.userInfo
// With swizzling disabled you must let Messaging know about the message, for Analytics
// Messaging.messaging().appDidReceiveMessage(userInfo)
// Print message ID.
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
// Print full message.
// print(userInfo)
completionHandler([.banner, .badge, .sound])
}
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
// Print message ID.
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
// Print full message.
print(userInfo)
completionHandler()
}
}
but when I’m testing notifications from firebase console, it's not coming.
Get an APNs Authentication key Enter a key name, check the Apple Push Notifications service (APNs) option, then download you APNs Authentication Key - save it in a secure place, as you'll need it later and it's a one-time download only! You are allowed a maximum of two Keys for APNs.
Firebase Cloud Messaging (FCM) provides a reliable and battery-efficient connection between your server and devices that allows you to deliver and receive messages and notifications on iOS, Android, and the web at no cost.
Method swizzling in Firebase Cloud Messaging The FCM SDK performs method swizzling in two key areas: mapping your APNs token to the FCM registration token and capturing analytics data during downstream message callback handling.
I was able to get your code to work. I think that Firebase has an issue with swizzling the AppDelegate
.
If you disable swizzling by adding the key FirebaseAppDelegateProxyEnabled
to your Info.plist
, making it a Boolean
and setting it to NO
.
Then in your AppDelegate
you need to add the following, so that it registers the APNS token with Firebase.:
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Messaging.messaging().apnsToken = deviceToken
}
For Firebase Cloud Messaging to work it needs to make a link between the APNS token and its token. If no link is made then you will not be able to send messages.
Note that by disabling swizzling there will be certain properties that you will have to update manually.
You should read the documentation carefully. At the time of writing this answer there are several places that you need to update if you disable swizzling.
There are three in the AppDelegate. The first is shown above, the other two are here and are to do with receiving background messages.
You are adding the following line to the delegate methods:
Messaging.messaging().appDidReceiveMessage(userInfo)
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
// If you are receiving a notification message while your app is in the background,
// this callback will not be fired till the user taps on the notification launching the application.
// TODO: Handle data of notification
// With swizzling disabled you must let Messaging know about the message, for Analytics
Messaging.messaging().appDidReceiveMessage(userInfo) // <- this line needs to be uncommented
// Print message ID.
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
// Print full message.
print(userInfo)
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
// If you are receiving a notification message while your app is in the background,
// this callback will not be fired till the user taps on the notification launching the application.
// TODO: Handle data of notification
// With swizzling disabled you must let Messaging know about the message, for Analytics
Messaging.messaging().appDidReceiveMessage(userInfo) // <- this line needs to be uncommented
// Print message ID.
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
// Print full message.
print(userInfo)
completionHandler(UIBackgroundFetchResult.newData)
}
There are two in the UNUserNotificationCenterDelegate. Where you add the follow line to the delegate methods
Messaging.messaging().appDidReceiveMessage(userInfo)
extension AppDelegate : UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
let userInfo = notification.request.content.userInfo
// With swizzling disabled you must let Messaging know about the message, for Analytics
Messaging.messaging().appDidReceiveMessage(userInfo) // <- this line needs to be uncommented
// Print message ID.
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
// Print full message.
print(userInfo)
// Change this to your preferred presentation option
completionHandler([[.alert, .sound]])
}
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
// Print message ID.
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
// With swizzling disabled you must let Messaging know about the message, for Analytics
Messaging.messaging().appDidReceiveMessage(userInfo) // <- this line needs to be uncommented
// Print full message.
print(userInfo)
completionHandler()
}
}
This above code is lifted from Firebase's Cloud Messaging documentation. They are very clear in the comments of their code what needs to be done if you have disabled swizzling.
Depending on which other Firebase modules you may include in your project you may have other values you need to update manually. This is where you will need to check carefully with the documentation and code samples to see what changes you have to make.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With