I have integrated Firebase into my project and I think I have followed all the steps required for generating push notifications within the app. I have also tested the push notifications by sending some dummy notifications from the Firebase console.
This is the tutorial I entirely followed.
Now my questions are..
How will I get the FCM ID so that I can send it in my api call.
When a push notification comes, where do I handle it..?
Where do I mention things like when to receive the notifications and the actions to take while tapping on notifications..?
EDIT 1
So this is all the code I have for handling push notifications...
In didFinishLaunchingWithOptions...
if #available(iOS 10.0, *) {
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: {_, _ in })
// For iOS 10 data message (sent via FCM
Messaging.messaging().delegate = self
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
FirebaseApp.configure()
And then,
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
let token = Messaging.messaging().fcmToken
print("FCM token: \(token ?? "")")
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]){
print("userInfo:-> \(userInfo)")
}
Q1 :- First Method
Q2&3 :- Second Method
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
let token = Messaging.messaging().fcmToken
print("FCM token: \(token ?? "")")
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]){
print("userInfo:-> \(userInfo)")
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
print("userInfo:-> \(userInfo)")
let redirect_flag = userInfo["redirect_flag"]as! String
if application.applicationState == .inactive {
// handle when you background
}
}else{
// Here You need to handle all terms which you handle in
didReceiveRemoteNotification method
}
Related
I am sending push notification by using FCM and PushTry, While the app is in suspended mode (App is closed) notification is coming but while app in foreground mode (App is open) notification coming but not showing banner.
didReceiveRemoteNotification notification method is calling when app in foreground mode and print data but not showing banner.
Code:-
import UIKit
import FirebaseCore
import FirebaseMessaging
import IQKeyboardManagerSwift
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window : UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]?) -> Bool {
FirebaseApp.configure()
Messaging.messaging().delegate = self
registerForFirebaseNotification(application: application)
return true
}
func registerForFirebaseNotification(application: UIApplication) {
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()
}
}
extension AppDelegate: MessagingDelegate {
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
print("Firebase token: \(fcmToken ?? "")")
let dataDict: [String: String] = ["token": fcmToken ?? ""]
NotificationCenter.default.post( name: Notification.Name("FCMToken"),object: nil, userInfo: dataDict )
}
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Messaging.messaging().apnsToken = deviceToken
}
//UNUserNotificationCenterDelegate
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
print("APNs received with: \(userInfo)")
}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
let content = notification.request.content
print("\(content.userInfo)")
completionHandler([.banner, .list, .sound]) // Display notification Banner
}
}
Print:-
APNs received with: [AnyHashable("google.c.sender.id"): 0000000000,
AnyHashable("google.c.fid"): 000000000, AnyHashable("google.c.a.e"): 1,
AnyHashable("aps"): {
alert = {
body = 22eeee;
title = 11;
};
"content-available" = 1;
}, AnyHashable("gcm.message_id"): 00000000]
App Notification Setting Screen:-
ScreenShot
Question: Can someone please explain to me how to show banner when app in foreground mode, I've tried with above code but no results yet. If i'm doing wrong please correct me.
Can someone please explain to me show notification banner?
Any help would be greatly appreciated.
Thanks in advance.
I have implemented FCM. There is no error showing. Token successfully generated. But no notification coming into the device.
I followed the google documentations.
Here is my AppDelegate class
import Foundation
import UIKit
import Firebase
//https://github.com/firebase/quickstart-ios/blob/5694c29ac5a8dcc672ec13f55f0ab74a6b9af11e/messaging/MessagingExampleSwift/AppDelegate.swift#L40-L55
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate, MessagingDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
FirebaseApp.configure()
Messaging.messaging().delegate = self
// 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 })
return true
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
print(userInfo)
}
// [START receive_message]
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
// Print full message.
print(userInfo)
completionHandler(UIBackgroundFetchResult.newData)
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("Unable to register for remote notifications: \(error.localizedDescription)")
}
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
print("Firebase registration token: \(String(describing: fcmToken))")
let dataDict:[String: String] = ["token": fcmToken ?? ""]
NotificationCenter.default.post(name: Notification.Name("FCMToken"), object: nil, userInfo: dataDict)
}
}
didReceiveRegistrationToken delegate method callings twice
Here is my Capabilities
I tried send notification from firebase cloud messaging option, but not coming to any Push in device.
I also tried from postman. Here is my payload and output
I have uploaded the APNS certificate in firebabse .
I tried into main project and its not working.
Then I tried to fresh implement into a dummy project its also not working.
Here is my source code. You may check into this.
https://www.dropbox.com/s/22wojqv5u3vwjzt/Swift%20UI%20Push%20Notification.zip?dl=0
I think the payload is different for APNS.From the document I found that the following is the format for FCM payload in APNS
{
"message": {
"token" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"notification" : {
"body" : "This is an FCM notification that displays an image.!",
"title" : "FCM Notification",
},
"apns": {
"payload": {
"aps": {
"mutable-content": 1
}
},
"fcm_options": {
"image": "url-to-image"
}
}
}
}
You can add all the UNUserNotificationCenterDelegate method along with completionHandler([.alert, .badge, .sound]).
I am running into a very weird problem. After uninstalling and reinstalling my iOS 11 app (coded in swift), I have to launch the app multiple times (10 to 20) before my firebase messaging works again. I change nothing in the code (sometimes I just wait and hour or so) and for some reason it seems that Firebase Messaging Notifications only work after relaunching my app multiple times. It's very important for my app to be able to receive notifications right when it's first opened as my app is basically reliant on them. I just need to find a way to get notifications to work when I first launch the app after I install it. I've attached images of my code. (I have method_swizzling enabled)
If someone could please help me I would really appreciate it. I've seen youtube videos doing the same things I'm doing and they're able to get messages to work right away. I've tried a lot of what I've seen online and other questions that seem to be like this but none of their methods seem to work. Thank you so much to anyone who tries to help!
[edit]
This is the code for the application launch function:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
application.statusBarStyle = ColorScheme.isDark ? .lightContent : .default
FirebaseApp.configure()
// Messaging.messaging().delegate = self
// Messaging.messaging().shouldEstablishDirectChannel = true
// UNUserNotificationCenter.current().requestAuthorization(options: [.badge, .alert, .sound]) { (granted, error) in }
// application.registerForRemoteNotifications()
setupMessaging(application: application)
}
This is the code for actually connecting and setting up my Firebase Messaging:
extension AppDelegate {
func setupMessaging(application: UIApplication) {
Messaging.messaging().delegate = self
Messaging.messaging().shouldEstablishDirectChannel = true
print("channel established", Messaging.messaging().isDirectChannelEstablished)
if #available(iOS 10.0, *) {
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()
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Messaging.messaging().setAPNSToken(deviceToken, type: .sandbox)
//TODO: Change for release
}
func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String) {
}
}
And this is the debug functions that are called when I receive the notification:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
print("I got a notification")
print(userInfo)
}
func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingRemoteMessage) {
print("remote message received")
}
P.S. my AppDelegate extends MessagingDelegate and UNUserNotificationCenterDelegate
Please Check the below code
import Firebase
import FirebaseMessaging
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate, MessagingDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
Messaging.messaging().delegate = self
//REMOTE NOTIFICATION
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()
Messaging.messaging().delegate = self
let token = Messaging.messaging().fcmToken
print("FCM token: \(token ?? "")")
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self
} else {
// Fallback on earlier versions
}
return true
}
func application(_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Messaging.messaging().apnsToken = deviceToken as Data
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
// Print full message.
print(userInfo)
}
// This method will be called when app received push notifications in foreground
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void)
{
completionHandler([UNNotificationPresentationOptions.alert,UNNotificationPresentationOptions.sound,UNNotificationPresentationOptions.badge])
}
// MARK:- Messaging Delegates
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
InstanceID.instanceID().instanceID { (result, error) in
if let error = error {
print("Error fetching remote instange ID: \(error)")
} else if let result = result {
print("Remote instance ID token: \(result.token)")
}
}
}
func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingRemoteMessage) {
print("received remote notification")
}
}
I found the answer! The problem was that I was using the online console firebase provides to send my test messages. I guess it time to register devices. I switched over to firebase functions to send my notification and then subscribed to a test topic with my phone and that fixed everything. I get notifications on first app launch now and I'm happy
I am setting up push notifications, and everything is going well until I try to get the FCM token so I can send a test message to an actual device. Using the pods Firebase 5.8.0, FirebaseCore (5.1.3), FirebaseInstanceID (3.2.1), and FirebaseMessaging (3.1.2), I can get the APNS token fine but every time I try to get the FCM token, it comes out as nil or when I use InstanceID.instanceID().instanceID(handler:) it results in some timeout error code 1003 and a result of nil. didReceiveRegistrationToken does not get called either. I've tried a many 2017 solutions but they're either deprecated or don't work. MessageDelegate and UNUserNotificationCenterDelegate are set, push notifications, and keychain sharing are enabled in capabilities, method swizzling is off via p-list and Here is my didRegisterForRemoteNotificationsWithDeviceToken function where I correctly get the apns token. Any ideas? Thanks.
`public func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
print("Registration Successful: Device token \(deviceToken)")
Messaging.messaging().apnsToken = deviceToken
print("Messaging APNS Token:\(Messaging.messaging().apnsToken)")
print("Instance Id: \(InstanceID.instanceID().token())") //deprecated & returns nil
print("Messaging APNS Token:\(Messaging.messaging().apnsToken)")
print("Token:\(Messaging.messaging().fcmToken)") // return nil
InstanceID.instanceID().instanceID { (result, error) in
if let result = result {
print("Result:\(String(describing: result?.token))")
} else {
print("Error:\(error))")
} //returns after about 2 mins with an firebase iid error of 1003
}
Please check the below app delegate code.
import UIKit
import Firebase
import FirebaseMessaging
import UserNotifications
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate, MessagingDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
FirebaseApp.configure()
//REMOTE NOTIFICATION
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()
Messaging.messaging().delegate = self
let token = Messaging.messaging().fcmToken
print("FCM token: \(token ?? "")")
//Added Code to display notification when app is in Foreground
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self
} else {
// Fallback on earlier versions
}
return true
}
func application(_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Messaging.messaging().apnsToken = deviceToken as Data
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
// Print full message.
print(userInfo)
}
// This method will be called when app received push notifications in foreground
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void)
{
completionHandler([UNNotificationPresentationOptions.alert,UNNotificationPresentationOptions.sound,UNNotificationPresentationOptions.badge])
}
// MARK:- Messaging Delegates
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
InstanceID.instanceID().instanceID { (result, error) in
if let error = error {
print("Error fetching remote instange ID: \(error)")
} else if let result = result {
print("Remote instance ID token: \(result.token)")
}
}
}
func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingRemoteMessage) {
print("received remote notification")
}
}
I've implemented Firebase Cloud Messaging as per instructions given on their website. So when I generate notification from here:
And in AppDelegate.swift I've added didReceiveRemoteNotification function as:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
Messaging.messaging().appDidReceiveMessage(userInfo)
print(userInfo)
completionHandler(UIBackgroundFetchResult.newData)
}
Other methods I've implemented are
func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String)
func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingRemoteMessage)
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)
Whereas my didFinishLaunchingWithOptions has:
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 })
// For iOS 10 data message (sent via FCM
Messaging.messaging().delegate = self
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
FirebaseApp.configure()
NotificationCenter.default.addObserver(self, selector: #selector(self.tokenRefreshNotification), name: NSNotification.Name.InstanceIDTokenRefresh, object: nil)
return true
Please take a look this gist file
AppDelegate file for FCM
In XCode Goto Targets > Capabilities & make sure your Push Notifications is on.
Hope it helps.