2

Push notifications not working at all. I have tried all the possible measures so far:

This is the code that i have tried:

In didFinishLaunchingWithOptions

FirebaseApp.configure()

if #available(iOS 10.0, *) {
    let center = UNUserNotificationCenter.current()
    center.delegate = self
    center.requestAuthorization(options: [.badge, .alert, .sound]) {
        (granted, error) in
        if granted {
            DispatchQueue.main.async {
                application.registerForRemoteNotifications()
                //UIApplication.shared.registerForRemoteNotifications()
            }
        } else {
            //print("APNS Registration failed")
            //print("Error: \(String(describing: error?.localizedDescription))")
        }
    }
} else {
    let type: UIUserNotificationType = [UIUserNotificationType.badge, UIUserNotificationType.alert, UIUserNotificationType.sound]
    let setting = UIUserNotificationSettings(types: type, categories: nil)
    application.registerUserNotificationSettings(setting)
    application.registerForRemoteNotifications()
    //UIApplication.shared.registerForRemoteNotifications()
}

Then the register and fail method:

private func application(application: UIApplication,
                 didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
    Messaging.messaging().apnsToken = deviceToken as Data
    print("Registered Notification")
}

func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {

        print(error.localizedDescription)
        print("Not registered notification")
}

@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

        // With swizzling disabled you must let Messaging know about the message, for Analytics
        // Messaging.messaging().appDidReceiveMessage(userInfo)

        // Print message ID.
        if let messageID = userInfo["gcm.message_id"] {
            print("Message ID: \(messageID)")
        }

        // Print full message.
        print(userInfo)

        // Change this to your preferred presentation option
        completionHandler([])
    }

    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["gcm.message_id"] {
            print("Message ID: \(messageID)")
        }

        // Print full message.
        print(userInfo)

        completionHandler()
    }
}

Note:

  • I have tried it on real device no push notifications so far.
  • I have double checked the certificates and regenerated the provisioning file after turning on the push notifications in capabilities.
  • I have also added background modes -> remote notifications on.
  • I have tried with legacy build also no luck.
  • I have tried reinstalling apps many times not working.
  • FirebaseAppDelegateProxyEnabled is set to NO in plist still no luck.
  • Also updated the pods still no luck.
  • .p12 certificate is at the firebase console, still not working.

Trying from last 1 week with different projects with different authentication methods with Apple key i have also tried still no luck.

Harjot Singh
  • 535
  • 7
  • 24

1 Answers1

1

here is the code i have used to generate push notification hope this helps you out.

put the whole following code in ur appdelegate.

Imported Libraries

 import Firebase
import FirebaseMessaging
import UserNotifications
import FirebaseInstanceID
import UserNotifications

add MessagingDelegate to ur appdelegate.

then

In didFinishLaunchingWithOptions

 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: { (bool, err) in

        })

    } else {

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

    }

    application.registerForRemoteNotifications()
    UIApplication.shared.applicationIconBadgeNumber = 0

    FirebaseApp.configure()
    // [START set_messaging_delegate]
    Messaging.messaging().delegate = self
    let token = Messaging.messaging().fcmToken
    print("FCM token: \(token ?? "")")

Then Add these Two function

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)

    // 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)

    // put your json parameters here Print message ID.
    if let messageID = userInfo[gcmMessageIDKey] {
        print("Message ID: \(messageID)")
    }

    if let msg = userInfo["desc"] as? String
    {
        let title = userInfo["noti_title"] as? String
        createNotification(message: msg, title: title ?? "" )

    }

    // Print full message.
    print(userInfo)

    completionHandler(UIBackgroundFetchResult.newData)
}


func createNotification(message: String, title: String) {

    let content = UNMutableNotificationContent()
    content.title =  title
    content.body = message


    let triger = UNTimeIntervalNotificationTrigger(timeInterval: 2, repeats: false )
    let request = UNNotificationRequest(identifier: "TextMessage", content: content, trigger: triger)



    UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
}

Then add these functions to get FCMToken

    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        print("APNs token retrieved: \(deviceToken)")

        // With swizzling disabled you must set the APNs token here.
        if let refreshedToken = InstanceID.instanceID().token() {
            print("InstanceID token: \(refreshedToken)")

        }
        let tokenT = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
        print(tokenT)
        guard let token = InstanceID.instanceID().token() else {return}
        AppDelegate.DEVICEID = token
        print(token)
        UserDefaults.standard.set(token, forKey: "token")

        connectToFCM()


    }
    func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String) {
        guard  let newToken = InstanceID.instanceID().token() else {return}
        AppDelegate.DEVICEID = newToken
        UserDefaults.standard.set(newToken, forKey: "token")

        connectToFCM()
    }
    func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingRemoteMessage) {
        print("Received data message: \(remoteMessage.appData)")
        print(remoteMessage.appData["notification"]!)
//        let info = response.notification.request.content.userInfo

//        if let message = info["messages"] {
//            print(message)
//        }
    }
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
        print("Firebase registration token: \(fcmToken)")
        UserDefaults.standard.set(fcmToken, forKey: "token")




    }

then add the following extention in your app delegate

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

        if let messageID = userInfo[gcmMessageIDKey] {
            print("Message ID: \(messageID)")
        }

        print(userInfo)

        // Change this to your preferred presentation option
        completionHandler([.alert,.badge,.sound])
    }


    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        let application = UIApplication.shared

        if(application.applicationState == .active){
            print("user tapped the notification bar when the app is in foreground")

            window = UIWindow(frame: UIScreen.main.bounds)
            window?.makeKeyAndVisible()

            //        let layout = UICollectionViewFlowLayout()
            window?.rootViewController = UINavigationController(rootViewController: NotificationViewController())


        }

        if(application.applicationState == .inactive)
        {
            print("user tapped the notification bar when the app is in background")
            window = UIWindow(frame: UIScreen.main.bounds)
            window?.makeKeyAndVisible()

            //        let layout = UICollectionViewFlowLayout()
            window?.rootViewController = UINavigationController(rootViewController: NotificationViewController())

        }

        /* Change root view controller to a specific viewcontroller */
        // let storyboard = UIStoryboard(name: "Main", bundle: nil)
        // let vc = storyboard.instantiateViewController(withIdentifier: "ViewControllerStoryboardID") as? ViewController
        // self.window?.rootViewController = vc

        completionHandler()
    }

    func connectToFCM()
    {
        Messaging.messaging().shouldEstablishDirectChannel = true
    }
    func initializeNotificationServices() -> Void {
        let settings = UIUserNotificationSettings(types: [.sound, .alert, .badge], categories: nil)
        UIApplication.shared.registerUserNotificationSettings(settings)

        // This is an asynchronous method to retrieve a Device Token
        // Callbacks are in AppDelegate.swift
        // Success = didRegisterForRemoteNotificationsWithDeviceToken
        // Fail = didFailToRegisterForRemoteNotificationsWithError
        UIApplication.shared.registerForRemoteNotifications()
    }

}

hoping this will help you out.

Hasnain ahmad
  • 301
  • 1
  • 10
  • 33
  • So you are saying that while i am in development phase i still need to give production .p12 certificate to firebase to make it work right? – Harjot Singh Apr 25 '19 at 10:13
  • noo i just said use the code provided in question its works perfect. And for certificate key you should use production key if you want to publish your app. development certificate doesn't work for released or published app where as production certificate works for both scenarios for development as well as for release. – Hasnain ahmad Apr 25 '19 at 11:15
  • 1
    can you give me link how are you saying? I have tried with production certificate also? Still not working? – Harjot Singh Apr 26 '19 at 07:50
  • i have added my code and updated my answer please match and compare your code with mine this will help you.... fingers crossed... :) and to test the code go to firebase messaging and generate a notification from there if u get same generated notification poped down on ur screen then its working – Hasnain ahmad Apr 26 '19 at 11:44
  • still not working now tried with APN key also still not working. – Harjot Singh Apr 26 '19 at 13:45
  • 1)have you added push notification permissions in info.plist?? 2) have you added capabilities in your xcode?? – Hasnain ahmad Apr 29 '19 at 09:34
  • @ahmed Yes , i have added it. I have tried your code its perfect, but the problem is with the swizzling of the firebase, FirebaseAppDelegateProxyEnabled is set to no to do it manually update the Firebase messaging but the real problem is that it is not syncing the FCM token with its own server, now the notifications is working if i have set FirebaseAppDelegateProxyEnabled to YES which let swizzle the firebase methods to get the notification, strangely i have added every possible method with swizzling off. – Harjot Singh Apr 29 '19 at 16:10
  • firebase works as third party communication between notification generating party and notification fetching party and FCM token then take place if you are not generating your own notification without using firebase cloud messaging console then you dont need FCM tokens. – Hasnain ahmad Apr 30 '19 at 07:07
  • got it but still this is very strange that manually i am missing nothing and notification is not working but by swizzling notification is working. – Harjot Singh Apr 30 '19 at 14:08
  • Have you filled target field while generating manual notification from firebase cloud messaging console?? – Hasnain ahmad May 02 '19 at 07:31
  • i have tried with target field also, but still the same problem is there. You mean to select the right app right? – Harjot Singh May 02 '19 at 13:26