Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI 2 Firebase push notification

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.

like image 321
Hattori Hanzō Avatar asked Oct 23 '20 19:10

Hattori Hanzō


People also ask

How do I register for push notifications on Swiftui?

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.

Can Firebase send push notification?

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.

What is Swizzling Firebase?

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.


1 Answers

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.

like image 152
Andrew Avatar answered Oct 12 '22 14:10

Andrew