PvDev
PvDev

Reputation: 829

Push notification is not receiving in iOS swift?

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?

Upvotes: 4

Views: 5557

Answers (2)

Saurabh Yadav
Saurabh Yadav

Reputation: 957

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/

Upvotes: 3

Arnav
Arnav

Reputation: 688

Setting priority to high from backend solves my problem.

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

Upvotes: -2

Related Questions