K. Mitra
K. Mitra

Reputation: 613

Push notification receiving, but not showing up in the device ios

I am working on an app in which I'm using FCM to send a push notification. I have followed the necessary steps to configure the push notification, i.e generating the certificate to adding entitlements and switch on remote notification in background mode, also uploaded the .p12 certificates with correct password in firebase console. The code I'm using for this is

@UIApplicationMain

class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate, MessagingDelegate {

let gcmMessageIDKey = "gcm.message_id"

/// This method will be called whenever FCM receives a new, default FCM token for your
/// Firebase project's Sender ID.
/// You can send this token to your application server to send notifications to this device.
func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String)
{
    debugPrint("--->messaging:\(messaging)")
    debugPrint("--->didRefreshRegistrationToken:\(fcmToken)")
}

@available(iOS 10.0, *)
public func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingRemoteMessage)
{
    debugPrint("--->messaging:\(messaging)")
    debugPrint("--->didReceive Remote Message:\(remoteMessage.appData)")
    let action_url = remoteMessage.appData["action_url"]! as! String
    if let remoteDiscussion = action_url.slice(from: "https://xxxxxxxx.in/d/", to: "-"){
        discussion = remoteDiscussion
        window?.rootViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "notificationDetailedItemNavigation") as! UINavigationController
    }
}

var window: UIWindow?

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

    debugPrint("###> 1 AppDelegate DidFinishLaunchingWithOptions")
    self.initializeFCM(application)
    if let token = InstanceID.instanceID().token(){
        debugPrint("GCM TOKEN = \(String(describing: token))")
    }
    return true
}

func applicationDidEnterBackground(_ application: UIApplication) {
    //FIRMessaging.messaging().disconnect()

    debugPrint("###> 1.2 AppDelegate DidEnterBackground")
    //        self.doServiceTry()
}


func applicationDidBecomeActive(_ application: UIApplication) {
    //        connectToFcm()
    application.applicationIconBadgeNumber = 0
    debugPrint("###> 1.3 AppDelegate DidBecomeActive")
}

func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error)
{
    debugPrint("didFailToRegisterForRemoteNotificationsWithError: \(error)")
}

func application(received remoteMessage: MessagingRemoteMessage)
{
    debugPrint("remoteMessage:\(remoteMessage.appData)")
}

func initializeFCM(_ application: UIApplication)
{
    print("initializeFCM")
    //-------------------------------------------------------------------------//
    if #available(iOS 10.0, *) // enable new way for notifications on iOS 10
    {
        let center = UNUserNotificationCenter.current()
        center.delegate = self
        center.requestAuthorization(options: [.badge, .alert , .sound]) { (accepted, error) in
            if !accepted
            {
                print("Notification access denied.")
            }
            else
            {
                print("Notification access accepted.")
                DispatchQueue.main.async {
                    UIApplication.shared.registerForRemoteNotifications()
                    Messaging.messaging().subscribe(toTopic: "/topics/Men")
                }
            }
        }
    }
    else
    {
        let type: UIUserNotificationType = [UIUserNotificationType.badge, UIUserNotificationType.alert, UIUserNotificationType.sound];
        let setting = UIUserNotificationSettings(types: type, categories: nil);
        UIApplication.shared.registerUserNotificationSettings(setting);
        UIApplication.shared.registerForRemoteNotifications();
    }

    FirebaseApp.configure()
    Messaging.messaging().delegate = self
    Messaging.messaging().shouldEstablishDirectChannel = true

    NotificationCenter.default.addObserver(self, selector: #selector(self.tokenRefreshNotificaiton), name: NSNotification.Name.InstanceIDTokenRefresh, object: nil)
}

func tokenRefreshNotificaiton(_ notification: Foundation.Notification)
{
    if let refreshedToken = InstanceID.instanceID().token()
    {
        debugPrint("InstanceID token: \(refreshedToken)")
    }
    //        connectToFcm()
}

//    func application(_ application: UIApplication, didRegister notificationSettings: UIUserNotificationSettings)
//    {
//        debugPrint("didRegister notificationSettings")
//        if (notificationSettings.types == .alert || notificationSettings.types == .badge || notificationSettings.types == .sound)
//        {
//            application.registerForRemoteNotifications()
//        }
//    }

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    if application.applicationState == .active {
        if let aps = userInfo["data"] as? NSDictionary {
            if let action_url = aps["action_url"] as? String {
                //                    let alert = UIAlertController(title: "Notification", message: alertMessage, preferredStyle: UIAlertControllerStyle.alert)
                //                    let action = UIAlertAction(title: "Ok", style: .default, handler: nil)
                //                    alert.addAction(action)
                //                    self.window?.rootViewController?.present(alert, animated: true, completion: nil)
                print(action_url)
            }
        }
    }
    completionHandler(.newData)
}

func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData)
{
    debugPrint("didRegisterForRemoteNotificationsWithDeviceToken: NSDATA")

    let token = String(format: "%@", deviceToken as CVarArg)
    debugPrint("*** deviceToken: \(token)")
    Messaging.messaging().apnsToken = deviceToken as Data
    debugPrint("Firebase Token:",InstanceID.instanceID().token() as Any)
    Messaging.messaging().subscribe(toTopic: "/topics/Men")
}

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)
{
    debugPrint("didRegisterForRemoteNotificationsWithDeviceToken: DATA")
    let token = String(format: "%@", deviceToken as CVarArg)
    debugPrint("*** deviceToken: \(token)")
    //        #if RELEASE_VERSION
    //            FIRInstanceID.instanceID().setAPNSToken(deviceToken as Data, type:FIRInstanceIDAPNSTokenType.prod)
    //        #else
    //            InstanceID.instanceID().setAPNSToken(deviceToken as Data, type:InstanceIDAPNSTokenType.sandbox)
    //        #endif
    Messaging.messaging().apnsToken = deviceToken
    debugPrint("Firebase Token:",InstanceID.instanceID().token() as Any)
}
//-------------------------------------------------------------------------//

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 notification
    // Print message ID.

    Messaging.messaging().appDidReceiveMessage(userInfo)

    if let messageID = userInfo["gcm.message_id"] {
        debugPrint("Message ID: \(messageID)")
    }

    // Print full message.
    print(userInfo)
}

func application(_ application: UIApplication, shouldSaveApplicationState coder: NSCoder) -> Bool {
    return true
}

func application(_ application: UIApplication, shouldRestoreApplicationState coder: NSCoder) -> Bool {
    return true
}

//------------------------------------------------------------------
}

 // [START ios_10_message_handling]
 @available(iOS 10, *)
 extension AppDelegate {

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

    // Print full message.
    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 userInfo = response.notification.request.content.userInfo
    // Print message ID.
    if let messageID = userInfo[gcmMessageIDKey] {
        print("Message ID: \(messageID)")
    }

    // Print full message.
    print(userInfo)

    completionHandler()
}
}

On did receive method I've implemented printing the received message and instantiating a viewController which is working fine and whenever I'm sending a notification from postman if the app is running, it is opening up the targeted view controller, but notification is not coming.

I've checked many solutions in StackOverflow but can't figure out the problem. I'm stuck here for like 2 weeks, can anyone please help.

xcode log

Upvotes: 5

Views: 5622

Answers (1)

Devang Tandel
Devang Tandel

Reputation: 3008

For iOS10 and Above

Use UNUserNotificationCenterDelegate

@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {


    completionHandler([.alert, .badge, .sound])

    let userInfo:NSDictionary = notification.request.content.userInfo as NSDictionary
    print(userInfo)
    let dict:NSDictionary = userInfo["aps"] as! NSDictionary
    let data:NSDictionary = dict["alert"] as! NSDictionary

    RNNotificationView.show(withImage: UIImage(named: "image_Logo_Small"),
                            title: data["title"] as? String,
                            message: data["message"] as? String,
                            duration: 2,
                            onTap: {
                                print("Did tap notification")
    })
}

This is code shows both native and RNNotifcation usage, i have kept in one code so you can use when it is needed(ios9/ios10). You will need to change the aspect that needs to be displayed according to your payload.

For below iOS10

The default Push Notification will not be shown when your App is in the foreground.

Push Notification gets displayed when your App is closed or is in Background. For Push to be shown when an app is in the background, you must select "Remote Notification" in "Background Mode".

Now to resolve your concern,

  1. You can create a view identical to push notification,
  2. Display content of notification in it.
  3. Animate your view same like push notification, you can also keep action when notification tapped.

If you are looking for Third Party Library then I will recommend: https://github.com/souzainf3/RNNotificationView

Upvotes: 2

Related Questions