didReceiveRemoteNotification not called in foreground firebase cloud messaging for iOS - ios

I tried to implement firebase cloud messaging on my app.
I register the notification using the following codes
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: {_, _ in })
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
Everything works fine when the app is in the back ground, but when the app is in the foreground, didReceiveRemoteNotification is not called at all.
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
// Print message ID.
print("please help")
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
// Print full message.
print(userInfo)
completionHandler(.newData)
}
Anyone knows possible error with this? Thanks!
EDIT: I do not need to see a notification display when the app is in foreground, I merely want to handle the message from the notification

iOS 10.x has a new function that handles push notification when in foreground, you should implement this one:
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler(
[UNNotificationPresentationOptions.alert,
UNNotificationPresentationOptions.sound,
UNNotificationPresentationOptions.badge])
}

Please implement below method to receive push notifications in foreground
For iOS10, Swift3:
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void)
{
completionHandler([.alert, .badge, .sound])
}
For iOS10, Swift 2.3:
#available(iOS 10.0, *)
func userNotificationCenter(center: UNUserNotificationCenter, willPresentNotification notification: UNNotification, withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void)
{
//Handle the notification
completionHandler(
[UNNotificationPresentationOptions.Alert,
UNNotificationPresentationOptions.Sound,
UNNotificationPresentationOptions.Badge])
}
Try this once:
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
print("Recived: \(userInfo)")
completionHandler(.NewData)
}

If you use Push Notification Firebase for IOS 10.
Please add this code. Hope to help you solve this problem :
#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
// Print message ID.
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
// Print full message.
print(userInfo)
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[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
// Print full message.
print(userInfo)
completionHandler()
}
}
extension AppDelegate : FIRMessagingDelegate {
// Receive data message on iOS 10 devices while app is in the foreground.
func applicationReceivedRemoteMessage(_ remoteMessage: FIRMessagingRemoteMessage) {
print(remoteMessage.appData)
}
}

Related

iOS push notification willPresent notification delegate method is not calling when app is in foreground

I have implemented the push notification in the app. I am getting callbacks on the following delegate method whenever the push comes.
func application(_: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void)
I have implemented the following delegate method To show the push notification when the app is in the foreground.
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void)
{
completionHandler([.alert, .badge, .sound])
}
Unfortunately, it is not working every time. Irrespective of the app state I'm getting the callback on didReceiveRemoteNotification method. Is there any particular reason for this behavior? Am I missing something?
Thanks in advance
I think you have to use the userNotificationCenter with the "didReceive response" signature instead of the application(didReceiveRemoteNotification userInfo:..)
// MARK: Notification handling
// If the app is in the background
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
let id = response.notification.request.identifier
print("Received notification with ID = \(id)")
completionHandler()
}
// If the app is in the foreground
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
let id = notification.request.identifier
print("Received notification with ID = \(id)")
completionHandler([.sound, .alert])
}
Also have your AppDelegate be UNUserNotificationCenter delegate.
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
UNUserNotificationCenter.current().delegate = self
}
.
.
.
}

AppDelegate method is only called from a notification when the app is already open

I'm trying to have a push notification take the user to a specific view controller when pressed on it.
I currently have this in my AppDelegate:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
if let error = error {
print(error.localizedDescription)
} else {
application.registerForRemoteNotifications()
}
}
UNUserNotificationCenter.current().delegate = self
return true
}
When I press on the notification and open the app from the background, none of these are being called:
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.alert, .sound, .badge])
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
}
if your app is not running in the background you will handle notification in didFinishLaunchingWithOptions like this
let notificationInfo = launchOptions?[UIApplication.LaunchOptionsKey.remoteNotification] as? [String : Any]
and if your app is running in background/foreground you will handle notification tap in
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void)

Remote notifications from background

I am creating an app in swift which will use UNNotificationAction buttons.
I have userNotificationCenter set up properly and I can call didReceive properly while the app is open... From here I show a modal window.
The issue is that when the app is not running in foreground or background (user hasn't opened app yet) I can't get didFinishLaunchingWithOptions to parse my code when I check on launchOptions?[UIApplication.LaunchOptionsKey.remoteNotification]
Is there a new technique for processing when a user fresh opens the app when tapping on a push notification using a UNNotificationAction?
In didFinishLaunchingWithOptions, when you discover that you are launching because of a notification, set yourself as the UNUserNotificationCenter's delegate and return false. Now your didReceive implementation will be called.
Kindly Check this code below , Hope this helps.
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate,CLLocationManagerDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
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: {_, _ in })
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
}
#available(iOS 10, *)
// 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)
completionHandler([.alert, .badge, .sound])
// 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[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
switch response.actionIdentifier {
case "action1":
print("Action First Tapped")
case "action2":
print("Action Second Tapped")
default:
break
}
// Print full message.
print(userInfo)
Messaging.messaging().appDidReceiveMessage(userInfo)
completionHandler()
}

Show notification in iOS app While app in foreground / Active in swift 3

I am trying to show the Banner notification when the app is active.
I used given method but there is no result , Banner notification are appearing only when the app is closed :
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
print("Push notification received: \(userInfo)")
if application.applicationState == .active {
print("active")
let localNotification = UILocalNotification()
localNotification.userInfo = userInfo
localNotification.alertAction = "Test"
localNotification.soundName = UILocalNotificationDefaultSoundName
localNotification.alertBody = "Notification test!!"
localNotification.fireDate = Date()
UIApplication.shared.scheduleLocalNotification(localNotification)
}
}
It prints "active" but the notification is not showing. Am i missing any step ?
Thank you.
If the application is running in the foreground, iOS won't show a notification banner/alert. You have to write some code to deal with the situation of your app receiving a notification while it is in the foreground.
Or you can use popular Third party library : github.com/bryx-inc/BRYXBanner
Use it like below
import BRYXBanner // import in your class
// Put this code where you are getting notification
let banner = Banner(title: "title", subtitle: "subtitle", image: UIImage(named: "addContact"), backgroundColor: UIColor(red:137.0/255.0, green:172.0/255.0, blue:2.0/255.0, alpha:1.000))
banner.dismissesOnTap = true
banner.show(duration: 1.0)
But if You are using iOS 10.0+ then you can approach goal for displaying banner message while app is in foreground, use the following method.
// This method will be called when app received push notifications in foreground for iOS 10+
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.alert, .badge, .sound])
}
To show notification in foreground. you need to write delegate methods\
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (_ options: UNNotificationPresentationOptions) -> Void) {
//Called when a notification is delivered to a foreground app.
let userInfo = notification.request.content.userInfo as? NSDictionary
print("\(userInfo)")
}
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
// Called to let your app know which action was selected by the user for a given notification.
let userInfo = response.notification.request.content.userInfo as? NSDictionary
print("\(userInfo)")
}
Add this code. You need to parse userInfo.
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
let userInfo = notification.request.content.userInfo
let notification = JSON(userInfo)
print(notification)
}

How to set badge count in iOS 10 for pushnotification?

I want to set badge count on app icon when notification recieved.Below method is called when notification is recieved.But the badge count does not set.
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
var userData = userInfo as NSDictionary? as? [AnyHashable: Any] ?? [:]
var aps = userData["aps"] as! NSDictionary
var badge = aps["badge"]
print("data is \(badge!)")
UIApplication.shared.applicationIconBadgeNumber = badge! as! Int
if #available(iOS 10.0, *) {
let content = UNMutableNotificationContent()
content.badge = 10
} else {
// Fallback on earlier versions
}
// your badge count
}
Actually in iOS 10 these two methods are called:
If the app is in the foreground:
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void)
If the app is in the background:
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void)
You need to get the content of the request of the notification
foreground method
let content = notification.request.content
background method
let content = response.notification.request.content
The badge number is in the property badge of content
let badgeNumber = content.badge as! Int
I was missing the authorization for badge.I added badge in code
if #available(iOS 10.0, *) {
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert, .sound,.badge]) { (granted, error) in
// actions based on whether notifications were authorized or not
}
application.registerForRemoteNotifications()
}
I added this in didFinishLaunchWithOptions

Resources