0

In my application I'm using Firebase to receive notification but I have a problem: when I send a notification from the Firebase console I hear only the vibration of the notification and I can see message body in the log. I can't show the banner notification with the message body as text and an icon.

I follow the official guide from here but it doesn't work.

This is my AppDelegate:

import UIKit
import Firebase
import FirebaseInstanceID
import FirebaseMessaging

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?


func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

        let settings: UIUserNotificationSettings =
            UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil)
        application.registerUserNotificationSettings(settings)
        application.registerForRemoteNotifications()

    FIRApp.configure()

    // Add observer for InstanceID token refresh callback.
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.tokenRefreshNotification),
                                                     name: kFIRInstanceIDTokenRefreshNotification, object: nil)
    return true
}


func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject],
                 fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {

    // TODO: Handle data of notification
    print("This is userInfo -> \(userInfo)")

    print("")
    print(userInfo["notification"]!["body"])
    print("")

    FIRMessaging.messaging().appDidReceiveMessage(userInfo)
    completionHandler(.NoData)


    NSLog("startLocalNotification")
    var notification: UILocalNotification = UILocalNotification()
    notification.fireDate = NSDate(timeIntervalSinceNow: 7)
    notification.alertBody =  userInfo["body"] as? String
    notification.timeZone = NSTimeZone.defaultTimeZone()
    notification.soundName = UILocalNotificationDefaultSoundName
    notification.applicationIconBadgeNumber = 5
    notification.alertAction = "open"
    UIApplication.sharedApplication().scheduleLocalNotification(notification)

}

func tokenRefreshNotification(notification: NSNotification) {
    let refreshedToken = FIRInstanceID.instanceID().token()!
    print("InstanceID token: \(refreshedToken)")

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

// [START connect_to_fcm]
func connectToFcm() {
    FIRMessaging.messaging().connectWithCompletion { (error) in
        if (error != nil) {
            print("Unable to connect with FCM. \(error)")
        } else {
            print("Connected to FCM.")
        }
    }
}
// [END connect_to_fcm]


func applicationWillResignActive(application: UIApplication) {

}

func applicationDidEnterBackground(application: UIApplication) {
    //Uncomment below to disconnect
    //FIRMessaging.messaging().disconnect()
    //print("Disconnected from FCM.")
}

func applicationWillEnterForeground(application: UIApplication) {
    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}

func applicationDidBecomeActive(application: UIApplication) {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    connectToFcm()
}
}

This is my ViewController:

import UIKit
import Firebase
import FirebaseInstanceID
import FirebaseMessaging

class ViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


@IBAction func handleLogTokenTouch(sender: UIButton) {
    let token = FIRInstanceID.instanceID().token()
    //        print("InstanceID token: \(token!)")
    print("InstanceID token: \(token)")

}

@IBAction func handleSubscribeTouch(sender: UIButton) {
    // [START subscribe_topic]
    FIRMessaging.messaging().subscribeToTopic("/topics/news")
    print("Subscribed to news topic")
    // [END subscribe_topic]
} 
}

How can I do to show notification in a banner?

Thanks in advance.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Jigen
  • 465
  • 1
  • 7
  • 20
  • 1
    If you application is running or in Foreground, Application will just invoke delegate method, NO alert or banner will be displayed. Alert or Banner will be displayed if your app is in background or killed (Not in foreground). To show banner while app is running you need to write your own code for it. Refer [this post](http://stackoverflow.com/questions/4974512/uilocalnotification-isnt-working-at-all) – Dipen Panchasara Jun 29 '16 at 13:17
  • @DipenPanchasara if I kill my app and then I send a notification from console nothing appears on my device – Jigen Jun 29 '16 at 13:19
  • Alert or Banner is handled by OS itself, if you want to display it comment out your `UILocalNotification` it won't work. When your app is not running system will automatically handle Notification and show appropriate alert or banner. I believe you understand context. – Dipen Panchasara Jun 29 '16 at 13:21
  • Read More about it in [UIApplicationDelegate section](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplicationDelegate_Protocol/#//apple_ref/occ/intfm/UIApplicationDelegate/application:didReceiveRemoteNotification:fetchCompletionHandler:) of Apple Documentation. – Dipen Panchasara Jun 29 '16 at 13:26
  • @DipenPanchasara I delated my UILocalNotification but it only vibrate when I re-open the app and show the log with the data. – Jigen Jun 29 '16 at 13:30
  • is your phone in silent mode? – Dipen Panchasara Jun 30 '16 at 05:29
  • @DipenPanchasara in vibrate mode – Jigen Jun 30 '16 at 06:45
  • Then how could System play Notification alert sound, while your device is in vibrate mode? And what is your Notification display style in setting for your app? check that as well. – Dipen Panchasara Jun 30 '16 at 08:28

2 Answers2

0

You need to handle the notifications as per your application's state as follows, 1. Background : Application will show notification as per the users setting for notification. (Banner, Alert, etc) 2. Forground : Application will not show any notification when app is in the foreground.

If you wish to notify user even when app is in the foreground you need to customize your code a bit. add following code into your didReceivedRemoteNotification method

    func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject],
                     fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {

        // TODO: Handle data of notification
        print("This is userInfo -> \(userInfo)")

        print("")
        print(userInfo["notification"]!["body"])
        print("")
       // I don't what the following two lines of code doing extactly 
        FIRMessaging.messaging().appDidReceiveMessage(userInfo)
        completionHandler(.NoData)
      // My code is as follows
      if application.applicationState == UIApplicationState.Active {
            //show a alert here
       }
    }
NSAnant
  • 816
  • 8
  • 18
  • I can't make the banner appears for now – Jigen Jun 29 '16 at 13:31
  • If you want to show the custom banner in the app when user using the app (App is the foreground) then there is 3rd party banner available on git / pod https://github.com/bryx-inc/BRYXBanner – NSAnant Jun 29 '16 at 13:35
0
you have to implement the message handling 

[START ios_10_message_handling]

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

        // Print full message.
        print(userInfo)

        completionHandler()

    }
    }
    // [END ios_10_message_handling]
    extension AppDelegate : MessagingDelegate {
    // [START refresh_token]
    func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String) {
    print("Firebase registration token: (fcmToken)")
    }

    // Receive data messages on iOS 10+ directly from FCM (bypassing APNs) when the app is in the foreground.
    // To enable direct data messages, you can set Messaging.messaging().shouldEstablishDirectChannel to true.
    func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingRemoteMessage) {
    print("Received data message: (remoteMessage.appData)")
    }
    }

reference : https://github.com/firebase/quickstart-ios/issues/286#issuecomment-304978967

hope fully it will helps you

naga
  • 397
  • 2
  • 12
  • 26