Push notifications not working at all. I have tried all the possible measures so far:
This is the code that i have tried:
In didFinishLaunchingWithOptions
FirebaseApp.configure()
if #available(iOS 10.0, *) {
let center = UNUserNotificationCenter.current()
center.delegate = self
center.requestAuthorization(options: [.badge, .alert, .sound]) {
(granted, error) in
if granted {
DispatchQueue.main.async {
application.registerForRemoteNotifications()
//UIApplication.shared.registerForRemoteNotifications()
}
} else {
//print("APNS Registration failed")
//print("Error: \(String(describing: error?.localizedDescription))")
}
}
} else {
let type: UIUserNotificationType = [UIUserNotificationType.badge, UIUserNotificationType.alert, UIUserNotificationType.sound]
let setting = UIUserNotificationSettings(types: type, categories: nil)
application.registerUserNotificationSettings(setting)
application.registerForRemoteNotifications()
//UIApplication.shared.registerForRemoteNotifications()
}
Then the register and fail method:
private func application(application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
Messaging.messaging().apnsToken = deviceToken as Data
print("Registered Notification")
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print(error.localizedDescription)
print("Not registered notification")
}
#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["gcm.message_id"] {
print("Message ID: \(messageID)")
}
// Print full message.
print(userInfo)
// 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["gcm.message_id"] {
print("Message ID: \(messageID)")
}
// Print full message.
print(userInfo)
completionHandler()
}
}
Note:
I have tried it on real device no push notifications so far.
I have double checked the certificates and regenerated the provisioning file after turning on the push notifications in
capabilities.
I have also added background modes -> remote notifications on.
I have tried with legacy build also no luck.
I have tried reinstalling apps many times not working.
FirebaseAppDelegateProxyEnabled is set to NO in plist still no luck.
Also updated the pods still no luck.
.p12 certificate is at the firebase console, still not working.
Trying from last 1 week with different projects with different authentication methods with Apple key i have also tried still no luck.
here is the code i have used to generate push notification hope this helps you out.
put the whole following code in ur appdelegate.
Imported Libraries
import Firebase
import FirebaseMessaging
import UserNotifications
import FirebaseInstanceID
import UserNotifications
add MessagingDelegate to ur appdelegate.
then
In didFinishLaunchingWithOptions
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: { (bool, err) in
})
} else {
let settings: UIUserNotificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
UIApplication.shared.applicationIconBadgeNumber = 0
FirebaseApp.configure()
// [START set_messaging_delegate]
Messaging.messaging().delegate = self
let token = Messaging.messaging().fcmToken
print("FCM token: \(token ?? "")")
Then Add these Two function
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 of notification
// 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)
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
// 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 of notification
// With swizzling disabled you must let Messaging know about the message, for Analytics
// Messaging.messaging().appDidReceiveMessage(userInfo)
// put your json parameters here Print message ID.
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
if let msg = userInfo["desc"] as? String
{
let title = userInfo["noti_title"] as? String
createNotification(message: msg, title: title ?? "" )
}
// Print full message.
print(userInfo)
completionHandler(UIBackgroundFetchResult.newData)
}
func createNotification(message: String, title: String) {
let content = UNMutableNotificationContent()
content.title = title
content.body = message
let triger = UNTimeIntervalNotificationTrigger(timeInterval: 2, repeats: false )
let request = UNNotificationRequest(identifier: "TextMessage", content: content, trigger: triger)
UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
}
Then add these functions to get FCMToken
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
print("APNs token retrieved: \(deviceToken)")
// With swizzling disabled you must set the APNs token here.
if let refreshedToken = InstanceID.instanceID().token() {
print("InstanceID token: \(refreshedToken)")
}
let tokenT = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
print(tokenT)
guard let token = InstanceID.instanceID().token() else {return}
AppDelegate.DEVICEID = token
print(token)
UserDefaults.standard.set(token, forKey: "token")
connectToFCM()
}
func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String) {
guard let newToken = InstanceID.instanceID().token() else {return}
AppDelegate.DEVICEID = newToken
UserDefaults.standard.set(newToken, forKey: "token")
connectToFCM()
}
func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingRemoteMessage) {
print("Received data message: \(remoteMessage.appData)")
print(remoteMessage.appData["notification"]!)
// let info = response.notification.request.content.userInfo
// if let message = info["messages"] {
// print(message)
// }
}
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
print("Firebase registration token: \(fcmToken)")
UserDefaults.standard.set(fcmToken, forKey: "token")
}
then add the following extention in your app delegate
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
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 application = UIApplication.shared
if(application.applicationState == .active){
print("user tapped the notification bar when the app is in foreground")
window = UIWindow(frame: UIScreen.main.bounds)
window?.makeKeyAndVisible()
// let layout = UICollectionViewFlowLayout()
window?.rootViewController = UINavigationController(rootViewController: NotificationViewController())
}
if(application.applicationState == .inactive)
{
print("user tapped the notification bar when the app is in background")
window = UIWindow(frame: UIScreen.main.bounds)
window?.makeKeyAndVisible()
// let layout = UICollectionViewFlowLayout()
window?.rootViewController = UINavigationController(rootViewController: NotificationViewController())
}
/* Change root view controller to a specific viewcontroller */
// let storyboard = UIStoryboard(name: "Main", bundle: nil)
// let vc = storyboard.instantiateViewController(withIdentifier: "ViewControllerStoryboardID") as? ViewController
// self.window?.rootViewController = vc
completionHandler()
}
func connectToFCM()
{
Messaging.messaging().shouldEstablishDirectChannel = true
}
func initializeNotificationServices() -> Void {
let settings = UIUserNotificationSettings(types: [.sound, .alert, .badge], categories: nil)
UIApplication.shared.registerUserNotificationSettings(settings)
// This is an asynchronous method to retrieve a Device Token
// Callbacks are in AppDelegate.swift
// Success = didRegisterForRemoteNotificationsWithDeviceToken
// Fail = didFailToRegisterForRemoteNotificationsWithError
UIApplication.shared.registerForRemoteNotifications()
}
}
hoping this will help you out.
Related
I am Developing an IOS App using swift language. I have added Firebase based push notifications to my project. they works correctly when my device is attached to xcode or when i debug my app on my device. But when ever i disconnect my device from xcode or i use app without debugging push notification doesn't work. I am looking for a solution
My code in App Delegate File
In didFinishLaunchingWithOptions function
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: { (bool, err) in
})
} else {
let settings: UIUserNotificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
UIApplication.shared.applicationIconBadgeNumber = 0
in didregisterdevicewithtoken function
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
print("APNs token retrieved: \(deviceToken)")
// With swizzling disabled you must set the APNs token here.
if let refreshedToken = InstanceID.instanceID().token() {
print("InstanceID token: \(refreshedToken)")
}
let tokenT = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
print(tokenT)
guard let token = InstanceID.instanceID().token() else {return}
AppDelegate.DEVICEID = token
print(token)
UserDefaults.standard.set(token, forKey: "token")
connectToFCM()
}
And to generate notification
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
// 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 of notification
// 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)")
}
if let msg = userInfo["desc"] as? String
{
let title = userInfo["noti_title"] as? String
createNotification(message: msg, title: title ?? "" )
}
// Print full message.
print(userInfo)
completionHandler(UIBackgroundFetchResult.newData)
}
func createNotification(message: String, title: String) {
let content = UNMutableNotificationContent()
content.title = title
content.body = message
let triger = UNTimeIntervalNotificationTrigger(timeInterval: 2, repeats: false )
let request = UNNotificationRequest(identifier: "TextMessage", content: content, trigger: triger)
UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
}
UNUserNotificationCenterDelegate
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
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 application = UIApplication.shared
if(application.applicationState == .active){
print("user tapped the notification bar when the app is in foreground")
window = UIWindow(frame: UIScreen.main.bounds)
window?.makeKeyAndVisible()
// let layout = UICollectionViewFlowLayout()
window?.rootViewController = UINavigationController(rootViewController: NotificationViewController())
}
if(application.applicationState == .inactive)
{
print("user tapped the notification bar when the app is in background")
window = UIWindow(frame: UIScreen.main.bounds)
window?.makeKeyAndVisible()
// let layout = UICollectionViewFlowLayout()
window?.rootViewController = UINavigationController(rootViewController: NotificationViewController())
}
/* Change root view controller to a specific viewcontroller */
// let storyboard = UIStoryboard(name: "Main", bundle: nil)
// let vc = storyboard.instantiateViewController(withIdentifier: "ViewControllerStoryboardID") as? ViewController
// self.window?.rootViewController = vc
completionHandler()
}
func connectToFCM()
{
Messaging.messaging().shouldEstablishDirectChannel = true
}
func initializeNotificationServices() -> Void {
let settings = UIUserNotificationSettings(types: [.sound, .alert, .badge], categories: nil)
UIApplication.shared.registerUserNotificationSettings(settings)
// This is an asynchronous method to retrieve a Device Token
// Callbacks are in AppDelegate.swift
// Success = didRegisterForRemoteNotificationsWithDeviceToken
// Fail = didFailToRegisterForRemoteNotificationsWithError
UIApplication.shared.registerForRemoteNotifications()
I have solved this problem. Now i have added production Apn certificate in firebase console and removed development apn certificate from firebase console. for those who had same issue please generate ur production apn from apple.developers and change your project scheme from debug to release in build tab.
I have implemented push notification by firebase. Not able to get notifications from background. Having following code in my App delegate,
class AppDelegate: UIResponder, UIApplicationDelegate, MessagingDelegate, UNUserNotificationCenterDelegate {
var window: UIWindow?
let gcmMessageIDKey = "gcm.message_id"
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
sleep(3)
IQKeyboardManager.shared.enable = true
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)
}
Messaging.messaging().delegate = self
Messaging.messaging().shouldEstablishDirectChannel = true
UIApplication.shared.registerForRemoteNotifications()
FirebaseApp.configure()
return true
}
func applicationWillResignActive(_ application: UIApplication) {
}
func applicationDidEnterBackground(_ application: UIApplication) {
Messaging.messaging().shouldEstablishDirectChannel = true
}
func applicationWillEnterForeground(_ application: UIApplication) {
}
func applicationDidBecomeActive(_ application: UIApplication) {
}
func applicationWillTerminate(_ application: UIApplication) {
}
func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String) {
print("Firebase registration token: \(fcmToken)")
let dataDict:[String: String] = ["token": fcmToken]
NotificationCenter.default.post(name: Notification.Name("FCMToken"), object: nil, userInfo: dataDict)
// TODO: If necessary send token to application server.
// Note: This callback is fired at each app startup and whenever a new token is generated.
}
func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingRemoteMessage) {
print("Message Data", remoteMessage.appData)
}
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 of notification
// 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)
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
// 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 of notification
// 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)
completionHandler(UIBackgroundFetchResult.newData)
}
// 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])
}
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()
}
}
And getting print for Message Data at did receive remote Notification
Message Data [AnyHashable("from"): 459345502087, AnyHashable("collapse_key"): www.rwdev.com.TravelSheriff2.1, AnyHashable("notification"): {
body = "Notifications ";
e = 1;
tag = "campaign_collapse_key_4509884114250587926";
title = "Travel Sheriff ";
}]
But I am not able to get push notifications while background and foreground. Even not getting "Message Data" print while app in background.
(Note:Please don't come up with previous stack overflow links and answers have already tried most of them..didnt work out..)
Hey #Aleesha use the request identifier.
I give you example down below follow the code, i hope its worked.
//MARK:- USER NOTIFICATION DELEGATE
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void)
{
print(notification.request.content.userInfo)
if notification.request.identifier == "rig"{
completionHandler( [.alert,.sound,.badge])
}else{
completionHandler([.alert, .badge, .sound])
}
}
func userNotificationCenter(center: UNUserNotificationCenter, willPresentNotification notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void)
{
//Handle the notification
completionHandler(
[UNNotificationPresentationOptions.alert,
UNNotificationPresentationOptions.sound,
UNNotificationPresentationOptions.badge])
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Messaging.messaging().apnsToken = deviceToken
let deviceTokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
print(deviceTokenString)
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
print(userInfo)
switch application.applicationState {
case .active:
let content = UNMutableNotificationContent()
if let title = userInfo["title"]
{
content.title = title as! String
}
if let title = userInfo["text"]
{
content.body = title as! String
}
content.userInfo = userInfo
content.sound = UNNotificationSound.default()
let trigger = UNTimeIntervalNotificationTrigger.init(timeInterval: 0.5, repeats: false)
let request = UNNotificationRequest(identifier:"rig", content: content, trigger: trigger)
UNUserNotificationCenter.current().delegate = self
UNUserNotificationCenter.current().add(request) { (error) in
if let getError = error {
print(getError.localizedDescription)
}
}
case .inactive:
break
case .background:
break
}
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("i am not available in simulator \(error)")
}
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
print("Firebase registration token: \(fcmToken)")
let token = Messaging.messaging().fcmToken
print("FCM token: \(token ?? "")")
}
In FCM notifications when a user clicks on notification it is redirecting to home page but I want to redirect to a specific page other than home page and the app is in foreground. When it was redirected to specific page the app should read the data in the notification and display the data on the page.
Here is the code that represent the above idea but it redirects to home page and nothing is happening(like display data).
My APPDelegate.class
import UIKit
import Firebase
import UserNotifications
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
let gcmMessageIDKey = "gcm.message_id"
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
FirebaseApp.configure()
Messaging.messaging().delegate = self as! MessagingDelegate
//Register for notification
if #available(iOS 10.0, *) {
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
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()
return true
}
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 of notification
// 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)
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
// 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 of notification
// 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)
completionHandler(UIBackgroundFetchResult.newData)
}
// [END receive_message]
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("Unable to register for remote notifications: \(error.localizedDescription)")
}
// This function is added here only for debugging purposes and can be removed if swizzling is enabled.
// If swizzling is disabled then this function must be implemented so that the APNs token can be paired with
// the FCM registration token.
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
print("APNs token retrieved: \(deviceToken)")
// With swizzling disabled you must set the APNs token here.
// Messaging.messaging().apnsToken = deviceToken
}
}
// [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 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()
}
}
// [END ios_10_message_handling]
extension AppDelegate : MessagingDelegate {
// [START refresh_token]
func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String) {
print("Firebase registration token: \(fcmToken)")
// TODO: If necessary send token to application server.
// Note: This callback is fired at each app startup and whenever a new token is generated.
}
// [END refresh_token]
// [START ios_10_data_message]
// 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)")
}
// [END ios_10_data_message]
}
add this code inside didReceive Response method like that:
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)
let storyBoard: UIStoryboard = UIStoryboard(name: "yourStoryboardName", bundle: nil)
let presentViewController = storyBoard.instantiateViewController(withIdentifier: "yourViewControllerStoryboardID") as! YourViewController
presentViewController.yourDict = userInfo //pass userInfo data to viewController
self.window?.rootViewController = presentViewController
presentViewController.present(presentViewController, animated: true, completion: nil)
completionHandler()
}
Application not running
When app is in closed state you should check for launch option in didFinishLaunchingWithOptions
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
var viewController = UIViewController()
if (launchOptions?[UIApplicationLaunchOptionsKey.remoteNotification] as? NSDictionary) != nil {
viewController = storyBoard.instantiateViewController(withIdentifier: "storyboardIdentifier") // user tap notification
}else{
viewController = storyBoard.instantiateViewController(withIdentifier: "storyboardIdentifier") // User not tap notificaiton
}
self.window?.rootViewController = viewController
self.window?.makeKeyAndVisible()
}
Application in Foreground state Here you can redirect on specific viewcontroller
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
// Print full message.
print(userInfo)
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let presentViewController = storyBoard.instantiateViewController(withIdentifier: "storyboardIdentifier") as! YourViewController
presentViewController.yourDict = userInfo //pass userInfo data to viewController
self.present(presentViewController, animated: true, completion: nil)
completionHandler()
}
}
You have to implement two methods for handling the notification, one for when the app is in the background, and the other for when the app has been shut down and is not running.
Inside your AppDelegate, implement the application(_:didFinishLaunchingWithOptions:) -> Bool method. This is for when the app is not running:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]?) -> Bool {
if let notificationData = launchOptions?[.remoteNotification] {
// Use this data to present a view controller based
// on the type of notification received
}
return true
}
When your app is in the background, you need to implement the userNotificationCenter(_:didReceive:withCompletionHandler:) method:
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
let notificationData = response.notification.request.content.userInfo
// Use this data to present a view controller based
// on the type of notification received
completionHandler()
}
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.
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,
You can create a view identical to push notification,
Display
content of notification in it.
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
I have problem when using FCM for iOS. I can only receive 1 notification per install, after that, iOS stated that my token is unregistered. Have tried to delete the token using InstanceID.instanceID().deleteToken and deleting instanceID using InstanceID.instanceID().deleteID but I still get the same unregistered token. I've also tried to send the notification from FCM console with the same result.
My code in AppDelegate:
let gcmMessageIDKey = "com.ucpmb"
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
Messaging.messaging().delegate = self
Messaging.messaging().shouldEstablishDirectChannel = true
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()
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("delegate", "FCM reg fail")
print("delegate", error.localizedDescription)
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Messaging.messaging().apnsToken = deviceToken
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
print("Message ID: \(userInfo["gcm.message_id"]!)")
print(userInfo)
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
print("Message ID: \(userInfo["gcm.message_id"]!)")
print(userInfo)
if userInfo["module"] as! String == "pmb_voucher" {
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
let centerViewController = storyBoard.instantiateViewController(withIdentifier: "PrePilihJurusanViewController") as! PrePilihJurusanViewController
window?.rootViewController = centerViewController
} else if (userInfo["module"] as! String == "pmb_result") {
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
let centerViewController = storyBoard.instantiateViewController(withIdentifier: "ResultTableViewController") as! ResultTableViewController
window?.rootViewController = centerViewController
}
completionHandler(UIBackgroundFetchResult.newData)
}
func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {
print(notificationSettings.types.rawValue)
}
func application(_ application: UIApplication, didReceive notification: UILocalNotification) {
print("Received Local Notification:")
print(notification.alertBody)
}
And for the AppDelegate extension:
#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 full message.
print(userInfo)
// 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)")
}
// Print full message.
print(userInfo)
completionHandler()
}
}
// [END ios_10_message_handling]
extension AppDelegate : MessagingDelegate {
// [START refresh_token]
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
print("Firebase registration token: \(fcmToken)")
// TODO: If necessary send token to application server.
// Note: This callback is fired at each app startup and whenever a new token is generated.
}
// [END refresh_token]
// [START ios_10_data_message]
// 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)")
}
// [END ios_10_data_message]
}
I'm currently using Swift 4. Thank you for your help!