4

I am using FCM for push notification. FCM is connected, device is registered successfully and I am able to print device token but the device is not receiving notification. In general -> capabilities tab -> enabled push notification and remote notification in back ground mode.

Here registering device for remote notification.

  func application(
    _ application: UIApplication,
    didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
    ) {

    let trimEnds:String! = {
        deviceToken.description.trimmingCharacters(
            in: CharacterSet(charactersIn: "<>"))
    }()


    let cleanToken:String! = {
        trimEnds.replacingOccurrences(of: " ", with: "")
    }()

    let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
    print(token)

    UserDefaults.standard.set(token, forKey: "deviceToken")
    UserDefaults.standard.synchronize()

    #if DEBUG
    //For Firebase
    FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenType.sandbox)
    #else
    FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenType.prod)
    #endif

    print("Device Token:", token)


}

Here I called didReceiveRemoteNotification method to receive notification on the registered device:

   func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
    print("-=-=-=-=-\nDid receive notification\n-=-=-=-",userInfo)
    print("-=-=-=-=-\n")

       NotificationCenter.default.post(name: Notification.Name(rawValue: "notification_recieved"), object: nil)

    if userInfo.index(forKey: "chat_id") != nil {
        print("messag push")
        if (AppUtility?.hasValidText(User.userID))! {
            //let friendImage = userInfo["path"] as! String
            let chatID = userInfo["chat_id"] as! String
            let friendId = userInfo["to"] as! String
            let unRead = userInfo["unread"] as! String
            print(unRead)
            UnReadMsgs = unRead

            let dictAPS = userInfo["aps"] as! NSDictionary
            let dict = dictAPS["alert"] as! NSDictionary
            let friendName = dict["title"] as! String
            let friendMsg = dict["body"] as! String

            if(UIApplication.shared.applicationState == UIApplicationState.active){

                print("app is Active")
                if let wd = self.window {
                    var VC = wd.rootViewController
                    if(VC is UINavigationController){
                        VC = (VC as! UINavigationController).visibleViewController
                        if(VC is ChatViewController!){
                            print("Chat Screen")
                            let chatVC : ChatViewController = VC as! ChatViewController
                            if chatVC.chatId == chatID{
                                print("Same Chat")
                                self.clearChatWithChatID(chatID)
                            }else{
                                CustomNotificationView.showNotificationPopUp(self.window!, name: friendName, msg: friendMsg, image: "", chat: chatID, friendID: friendId)

                                playSound()
                                print("Other Chat")
                            }
                        }else{
                            let nc = NotificationCenter.default
                            nc.post(name: Notification.Name(rawValue: "MessageGet"),
                                                    object: nil,
                                                    userInfo: ["unRead":unRead,
                                                        "date":Date()])
                            CustomNotificationView.showNotificationPopUp(self.window!, name: friendName, msg: friendMsg, image: "", chat: chatID, friendID: friendId)

                            playSound()
                            print("Other Screen")
                        }
                    }
                }

            }else{

                print("app is in BG")

                var vc:ChatViewController!
                vc = ChatViewController(nibName: "ChatViewController", bundle: nil)
                vc.chatId = chatID
                vc.otherUserId = friendId
                vc.otherUserName = friendName
                vc.channelRef = self.channelRef.child("\(chatID)")
                vc.friendImageLink = "\(resourceUrl)\("")"

                let nav = UINavigationController(rootViewController: vc)
                nav.isNavigationBarHidden = false

                if let wd = self.window {
                    var VC = wd.rootViewController
                    if(VC is UINavigationController){
                        VC = (VC as! UINavigationController).visibleViewController
                    }


                    VC!.present(nav, animated: false, completion: {
                    })

                }


            }


        }

    }else{
        let val = userInfo["aps"] as! [String:AnyObject];
        let alert  =   NSString(string: val["alert"] as! String)
        if(UIApplication.shared.applicationState == UIApplicationState.inactive || UIApplication.shared.applicationState == UIApplicationState.background)
        {
            showUserInfo(application, didReceiveRemoteNotification: userInfo)
                      }
        else
        {

            print("top most vc \(String(describing: UIApplication.shared.keyWindow!.rootViewController!.topMostViewController().presentingViewController)) and presentedvc \(String(describing: UIApplication.shared.keyWindow!.rootViewController!.topMostViewController().presentedViewController))")

            if UIApplication.shared.keyWindow!.rootViewController!.topMostViewController() is NYAlertViewController{

                let newAlert = AppUtility?.getDisplayAlertController(title: "FitFlow", messageText: alert as String)
                let nvVc = UIApplication.shared.keyWindow!.rootViewController!.topMostViewController().presentedViewController
                nvVc?.present(newAlert!, animated: true, completion: nil)

                return

            }

                AppUtility?.displayAlert(title:"FitFlow", messageText: alert as String,UIApplication.shared.keyWindow!.rootViewController!.topMostViewController())




        }

    }
}

I have tested by keeping breakpoints, it does not called didReceiveRemoteNotification method at all. How to receive push notification using above method?

christopherdrum
  • 1,513
  • 9
  • 25
PvDev
  • 791
  • 21
  • 67
  • what does your payload look like? Do you have notifications enabled on the device? Are you testing on device or simulator? – mfaani May 05 '18 at 12:09
  • if your `didReceiveRemoteNotification` isn't getting called at all then kindly delete all its code block until you find out why it's not getting hit. I mean the rest of the code isn't necessary to see to help. – mfaani May 05 '18 at 12:18
  • @Honey Hey still could not able to find solution for this ??? any idea – PvDev May 07 '18 at 06:44
  • Hello PvDev, have you tested notification through Firebase console? – Mannam Brahmam May 07 '18 at 10:10
  • @MannamBrahmam nope!!.. – PvDev May 07 '18 at 11:26
  • Can you try to send notification from Firebase console instead of your server? and then let me know, you are receiving notification from firebase or not.. – Mannam Brahmam May 07 '18 at 11:43
  • 1
    -generate APNs key. https://firebase.google.com/docs/cloud-messaging/ios/certs -upload APNs key to firebase project. in firebase project => settings => cloud messaging => iOS app configuration => APNs Authentication Key -also Make sure your application requested notification permissions upon first launch. // requests permissions from the user FCM.requestPermissions(); FCM.getToken() – Mannam Brahmam May 07 '18 at 12:19
  • @MannamBrahmam I have already done this – PvDev May 07 '18 at 12:40
  • 4
    Don't you think, adding bounty when you haven't already tried/replied to the comments is useless. – mfaani May 07 '18 at 17:03
  • Can you share the payload? – SHN May 08 '18 at 06:55
  • @PvDev did you set delegate ? – Vivek May 08 '18 at 07:07
  • @PvDev Please follow steps from this url https://firebase.google.com/docs/cloud-messaging/ios/client – Vivek May 08 '18 at 07:08
  • Please consider adding the FCM tag to this question and defining the acronym (any acronym) the first time you use it. Thanks. – Tony Adams May 10 '18 at 19:19
  • make breakpoint to didReceiveRemoteNotification with fetchCompletionHandler and check if it is getting called or not? – Parth Bhuva May 11 '18 at 11:43
  • can I know to whom you are working with production certificate or development certificate for push notification? – Abhishek Mitra May 12 '18 at 20:01
  • Does requesting authorization to display notifications make a difference? UNUserNotificationCenter.current() .requestAuthorization(options: [.alert, .sound]) { (granted, error) in // Enable or disable features based on authorization. } Also, would you be able to implement func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { ... } to see if there's any error? – John Dough May 13 '18 at 16:24
  • https://stackoverflow.com/questions/39434093/swift-3-firebase-push-notification-how-can-i-do Please go through this link... some methods are deprecated – Manish Mahajan May 14 '18 at 03:54
  • @PvDev have you upload .p12 file in firebase console – Naresh May 14 '18 at 05:42
  • @PvDev Please check my answer and confirm if that works for you? – Saurabh Yadav May 14 '18 at 06:24

2 Answers2

3

I was also stuck with this earlier.

This requires FCM token, and not the APNS token.

To do so, Your AppDelegate class needs to have these -

import Firebase
import UserNotifications
import FirebaseMessaging

class AppDelegate: UIResponder,
                   UIApplicationDelegate,
                UNUserNotificationCenterDelegate,
                FIRMessagingDelegate {
                
                }
  • Then subscribe the messaging delegate in didFinishLaunchingWithOptions
func application(_ application: UIApplication,
                 didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    
    GIDSignIn.sharedInstance().clientID =
    "Your client id"
    DispatchQueue.main.async {
        FIRApp.configure()
    }
    
    FIRMessaging.messaging().remoteMessageDelegate = self


    if #available(iOS 10, *) {
        UNUserNotificationCenter.current().requestAuthorization(options:[.badge, .alert, .sound]){ (granted, error) in }
        application.registerForRemoteNotifications()
    }
        // iOS 9 support
    else if #available(iOS 9, *) {
        UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.badge, .sound, .alert], categories: nil))
        UIApplication.shared.registerForRemoteNotifications()
    }
        // iOS 8 support
    else if #available(iOS 8, *) {
        UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.badge, .sound, .alert], categories: nil))
        UIApplication.shared.registerForRemoteNotifications()
    }
        // iOS 7 support
    else {
        application.registerForRemoteNotifications(matching: [.badge, .sound, .alert])
    }
    

    return true
}

// You dont need didRegisterForRemoteNotificationsWithDeviceToken method anymore

 func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { }

the token you received from the delegate didRegisterForRemoteNotificationsWithDeviceToken is not useful,

You need to use the FIRInstanceID.instanceID().token()

Add below code in your applicationDidBecomeActive, this will check for FCM token refreshes, and handle that elegantly.

func applicationDidBecomeActive(_ application: UIApplication) {
    
    NotificationCenter.default.addObserver(self, selector:
        #selector(tokenRefreshNotification), name:
        NSNotification.Name.firInstanceIDTokenRefresh, object: nil)
}

@objc func tokenRefreshNotification(notification: NSNotification) {

    if let refreshedToken = FIRInstanceID.instanceID().token() {
        print("InstanceID token: \(refreshedToken)")
        UserDefaults.standard.set(refreshedToken, forKey: "deviceToken")
        self.sendFCMTokenToServer(token: refreshedToken)
    }
    /* 
    Connect to FCM since connection may
    have failed when attempted before having a token.
    */
    else { 
        connectToFcm()
    }
}

func updatePushNotificationWebservice() {
    /*
     if you want to save that token on your server 
     Do that here.
     else use the token any other way you want.
    */
}

func connectToFcm() {
     
        FIRMessaging.messaging().connect { (error) in
            if (error != nil) {
                print("Unable to connect with FCM. \(String(describing: error))")                   
            }
            else {
                print("Connected to FCM.")
                /*
                **this is the token that you have to use**
                print(FIRInstanceID.instanceID().token()!)
                if there was no connection established earlier,
                you can try sending the token again to server.
                */

                let token = FIRInstanceID.instanceID().token()!
                self.sendFCMTokenToServer(token: token)

            }
        }
}
    
    

For debugging use the token obtained from FIRInstanceID.instanceID().token()!, and use the push notification firebase console with same token in the >project>Cloud messaging tab.

https://console.firebase.google.com/u/0/

Community
  • 1
  • 1
Saurabh Yadav
  • 957
  • 10
  • 20
-2

Setting priority to high from backend solves my problem.

Please check from firebase console->cloud messaging(down left item) to send push notification.

Arnav
  • 668
  • 6
  • 14