Fcm Push Notifications Do Not Work on iOS 11

FCM Push notifications do not work on iOS 11

It appears that with FirebaseInstanceID 2.0.3 push notifications don't work. It helped me to set: pod 'FirebaseInstanceID', "2.0.0".
Maybe in next version this will be fixed.

FCM Push notification not working in iOS 11

Please Check as
enter image description here

enter image description here

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Use Firebase library to configure APIs
FirebaseApp.configure()
self.registerForPushNotifications(application: application)
Messaging.messaging().delegate = self

if let token = InstanceID.instanceID().token() {
NSLog("FCM TOKEN : \(token)")
DataModel.sharedInstance.onSetUserFCMStringToken(FCM: token)
self.connectToFcm()
}
if launchOptions != nil {
//opened from a push notification when the app is closed
_ = launchOptions?[UIApplicationLaunchOptionsKey.remoteNotification] as? [AnyHashable: Any] ?? [AnyHashable: Any]()
}
else {
//opened app without a push notification.
}
return true
}

@available(iOS 10, *)

extension AppDelegate: UNUserNotificationCenterDelegate {
// iOS10+, called when presenting notification in foreground
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
let userInfo = notification.request.content.userInfo
NSLog("[UserNotificationCenter] willPresentNotification: \(userInfo)")
//TODO: Handle foreground notification
completionHandler([.alert])
}

// iOS10+, called when received response (default open, dismiss or custom action) for a notification
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
NSLog("[UserNotificationCenter] didReceiveResponse: \(userInfo)")
//TODO: Handle background notification
completionHandler()
}}

extension AppDelegate : MessagingDelegate {
//MARK: FCM Token Refreshed
func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String) {
NSLog("[RemoteNotification] didRefreshRegistrationToken: \(fcmToken)")
}

// Receive data message on iOS 10 devices while app is in the foreground.
func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingRemoteMessage) {
NSLog("remoteMessage: \(remoteMessage.appData)")
}}

//Register for push notification.
func registerForPushNotifications(application: UIApplication) {
if #available(iOS 10.0, *) {
let center = UNUserNotificationCenter.current()
center.delegate = self
center.requestAuthorization(options: [.alert,.sound]) { (granted, error) in
if error == nil{
DispatchQueue.main.async(execute: {
application.registerForRemoteNotifications()
})
}
}
}
else {

let settings = UIUserNotificationSettings(types: [.alert,.sound], categories: nil)
application.registerUserNotificationSettings(settings)
application.registerForRemoteNotifications()
}

// Add observer for InstanceID token refresh callback.
NotificationCenter.default.addObserver(self, selector: #selector(self.tokenRefreshNotification), name: NSNotification.Name.InstanceIDTokenRefresh, object: nil)

}

@objc func tokenRefreshNotification(_ notification: Notification) {
print(#function)
if let refreshedToken = InstanceID.instanceID().token() {
NSLog("Notification: refresh token from FCM -> \(refreshedToken)")

}
// Connect to FCM since connection may have failed when attempted before having a token.
connectToFcm()
}

func connectToFcm() {
// Won't connect since there is no token
guard InstanceID.instanceID().token() != nil else {
NSLog("FCM: Token does not exist.")
return
}

Messaging.messaging().shouldEstablishDirectChannel = true
}

func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
NSLog("Notification: Unable to register for remote notifications: \(error.localizedDescription)")
}

// This function is added here only for debugging purposes, and can be removed if swizzling is enabled.
// If swizzling is disabled then this function must be implemented so that the APNs token can be paired to the InstanceID token.
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {

Messaging.messaging().apnsToken = deviceToken

}

// iOS9, called when presenting notification in foreground
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
NSLog("didReceiveRemoteNotification for iOS9: \(userInfo)")

}

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

}

Firebase FCM push notifications stopped working iOS 11.1.1

Ok, fixed it. I disable firebase's message swizzling by adding this to my Info.plist: FirebaseAppDelegateProxyEnabled: NO

Further I removed all firebase messaging delegate methods. And generated my own APN token in didRegisterForRemoteNotificationsWithDeviceToken and setting Messaging.messaging().apnsToken = deviceToken in the didRegisterForRemoteNotificationsWithDeviceToken method once token generated.

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
if let refreshedToken = InstanceID.instanceID().token() {
defaults.set(refreshedToken, forKey: Constant.UserDefaults.token)

Messaging.messaging().apnsToken = deviceToken

print("Token generated: ", refreshedToken)
} else {
print("Could not save token becuase error with instance id token")
}
}

Previously I used the firebase swizzling, it appears as if this stopped working for some reason.

As this was a tough experience for me, I would like to post the steps that I would now reccommend to enable iOS client for FCM:

  1. In the Apple Developer console generate your APN and then select APNs. Select Continue and download your APN certificate. Take note of your Key ID.

enter image description here

Then in the firebase console under settings, cloud messaging, upload your APN key, add the key ID and bundle id, do not upload any p12 certificates.

enter image description here


  1. Disable firebase message swizzling by adding this to your Info.plist:

FirebaseAppDelegateProxyEnabled: NO


  1. Then add the following in your AppDelegate.swift file in the didFinishLaunchingWithOptions method:

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    // [START set_messaging_delegate]
    Messaging.messaging().delegate = self
    // [END set_messaging_delegate]

    // get push notification token id for user
    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)
    }

    application.registerForRemoteNotifications()

    return true

    }

Since swizzling is disabled you need to take care of generating your APN token and assigning it to the firebase messaging apnsToken. You do this by having the following method in your AppDelegate.swift file:

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
if let refreshedToken = InstanceID.instanceID().token() {
defaults.set(refreshedToken, forKey: Constant.UserDefaults.token)

Messaging.messaging().apnsToken = deviceToken

print("Token generated: ", refreshedToken)
} else {
print("Could not save token becuase error with instance id token")
}
}

I then save the token in the userdefaults to later persist to the database see above:

defaults.set(refreshedToken, forKey: Constant.UserDefaults.token)

You can test that your token is working by copying the token printed out in the console and using the FCM messaging console. Or by using a curl request in the terminal as below. Note you have to replace YOUR_LEGACY_SERVER_KEY with the legacy server key which you can find in the firebase console under settings and cloud messaging and replace YOUR_TOKEN with the token printed in the console (which was generated above):

curl -X "POST" "https://fcm.googleapis.com/fcm/send" \
-H "Authorization: key=YOUR_LEGACY_SERVER_KEY” \
-H "Content-Type: application/json" \
-d $'{
"notification": {
"body": "Testing with direct FCM API",
"title": "Test Message",
"badge": "0",
"sound": "default"
},
"registration_ids": [YOUR_TOKEN]
}'

Firebase Push notification not working in iOS 11

I was able to solve the problem with push notifications and scheduled push notifications on iOS 11.1 by replicating the same code present in the sample firebase project - https://github.com/firebase/quickstart-ios/tree/master/messaging

The steps given here are clear and helps you resolve the issue.

Firebase notifications not working in iOS 11

This is an issue with Firebase. It seems to be related to a recent update of theirs instead of iOS 11. They are working on a fix for it.

In the meantime if you add pod 'FirebaseInstanceID', '2.0.0' to your podfile it will fix it.

You can read more here: https://github.com/firebase/quickstart-ios/issues/327#issuecomment-332655731

Unable to receive IOS notifications from Firebase Console

Go to firebase->Project Settings->Cloud Messaging -> then scroll down to Apple app configuration and make sure you've provided APNs Production Certificate or not, if not then generate production certificate and upload it there. Alternatively i suggest you to upload APNs Authentication Key instead of certificates.

Preview Image

Firebase Push Notifications with Swift not working in ios 11.4

first make sure you have a paid developer account, activate notification from the project capabilities section, set up all the certificate with apple member center and add this certificate to gcm (see this How to use Apple's new .p8 certificate for APNs in firebase console) , you also must test with a real device

I assume that you already have these 3 Pods

import FirebaseInstanceID
import FirebaseMessaging
import UserNotifications

first you need to add this to didfinishlaunchingwithoptions

FirebaseApp.configure()
Messaging.messaging().delegate = self
registerForPushNotifications()

then add this two func to get the user permission

func getNotificationSettings() {
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().getNotificationSettings { (settings) in
guard settings.authorizationStatus == .authorized else { return }
DispatchQueue.main.async(execute: {
UIApplication.shared.registerForRemoteNotifications()
})
}
} else {
// Fallback on earlier versions
}
}

func registerForPushNotifications() {
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) {
(granted, error) in
guard granted else { return }
self.getNotificationSettings()
}
} else {
let settings = UIUserNotificationSettings(types: [.sound, .alert, .badge], categories: nil)
UIApplication.shared.registerUserNotificationSettings(settings)
UIApplication.shared.registerForRemoteNotifications()
}
}

to get the firebase token add this

func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
print(fcmToken)
}

from now you should be able to see the permission prompt and to push notification from the Firebase console

if you need to perform a notification from code here is what I do (make sure to replace with your api key from firebase)

func sendPushNotification(notData: [String: Any]) {
let url = URL(string: "https://fcm.googleapis.com/fcm/send")!
var request = URLRequest(url: url)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("key=YOUR-SERVER-API-KEY", forHTTPHeaderField: "Authorization")
request.httpMethod = "POST"

request.httpBody = try? JSONSerialization.data(withJSONObject: notData, options: [])
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
print(error ?? "")
return
}

if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print(response ?? "")
}

let responseString = String(data: data, encoding: .utf8)
print(responseString ?? "")
}
task.resume()
}

then call this func when you need

let notifMessage: [String: Any] = [
"to" : "fcm token you need to send the notification",
"notification" :
["title" : "title you want to display", "body": "content you need to display", "badge" : 1, "sound" : "default"]
]

sendPushNotification(notData: notifMessage)


Related Topics



Leave a reply



Submit