I have an issue, and can't figure out what is the problem. I have integrated Firebase in my app. Everything was OK until I updated to xCode 8.3 and Swift3.1.
I receive the notification in Foreground in the console from the FCM but when I enter in Background or even in Foreground
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void)
is never executed and I'm not able to handle the notification
This is what I am receiving from the FCM
[AnyHashable("from"): 1234456, AnyHashable("sender_name"): Driver, AnyHashable("type"): NEW_MESSAGE, AnyHashable("text"): text ;)]
In AppDelegate I have the following:
import UIKit
import CoreData
import FBSDKCoreKit
import FBSDKLoginKit
import UserNotifications
import Firebase
import FirebaseInstanceID
import FirebaseMessaging
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate {
var window: UIWindow?
let gcmMessageIDKey = "gcm.message_id"
var apiManagerFunc = ApiManager()
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 })
// For iOS 10 data message (sent via FCM)
FIRMessaging.messaging().remoteMessageDelegate = self
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
application.registerForRemoteNotifications()
}
application.registerForRemoteNotifications()
if let options: NSDictionary = launchOptions as NSDictionary? {
let remoteNotification = options[UIApplicationLaunchOptionsKey.remoteNotification]
if let notification = remoteNotification {
self.application(application, didReceiveRemoteNotification: notification as! [AnyHashable: Any], fetchCompletionHandler: { (result) in
})
}
}
// [START add_token_refresh_observer]
// Add observer for InstanceID token refresh callback.
NotificationCenter.default.addObserver(self,
selector: #selector(self.tokenRefreshNotification),
name: .firInstanceIDTokenRefresh,
object: nil)
// [END add_token_refresh_observer]
if let refreshedToken = FIRInstanceID.instanceID().token() {
print("InstanceID token: \(refreshedToken)")
connectToFcm()
}
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
// Print message ID.
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
// Print full message.
print(userInfo)
}
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
// Let FCM know about the message for analytics etc.
FIRMessaging.messaging().appDidReceiveMessage(userInfo)
// handle your message
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
if application.applicationState == .active {
let userInfoCheck = userInfo["type"] as! String
if userInfoCheck == "LOCATION_REQUEST" {
let valueCheck = UserDefaults.standard.value(forKey: "myLocationSwitchState") as! String
if valueCheck == "on" {
self.showAlertAppDelegate(title: "", message: userInfo["text"] as! String, buttonTitle: "Ok", window: self.window!)
self.updateLocationToServer()
print("Shown")
} else {
print(valueCheck)
}
} else {
self.showAlertAppDelegate(title: "New Message", message: userInfo["text"] as! String, buttonTitle: "Ok", window: self.window!)
}
} else {
let userInfoCheck = userInfo["type"] as! String
if userInfoCheck == "LOCATION_REQUEST" {
let valueCheck = UserDefaults.standard.value(forKey: "myLocationSwitchState") as! String
if valueCheck == "on" {
scheduleLocalNotification(message: userInfo["text"] as! String)
print("Shown")
self.updateLocationToServer()
} else {
print(valueCheck)
}
} else {
scheduleLocalNotification(message: userInfo["text"] as! String)
}
}
// Print full message.
print(userInfo)
completionHandler(UIBackgroundFetchResult.newData)
}
func showAlertAppDelegate(title : String,message : String,buttonTitle : String,window: UIWindow){
let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: buttonTitle, style: UIAlertActionStyle.default, handler: nil))
window.rootViewController?.present(alert, animated: true, completion: nil)
}
func scheduleLocalNotification(message: String) {
// create a corresponding local notification
let notification = UILocalNotification()
notification.alertBody = message
// play default sound
notification.soundName = UILocalNotificationDefaultSoundName
// assign a unique identifier to the notification so that we can retrieve it later
notification.userInfo = ["UUID": UUID().uuidString]
notification.category = "XXXXXXXXXXXXXXX"
UIApplication.shared.scheduleLocalNotification(notification)
}
func application(_ application: UIApplication, didReceive notification: UILocalNotification) {
print(notification)
}
// [START connect_to_fcm]
func connectToFcm() {
// Won't connect since there is no token
guard FIRInstanceID.instanceID().token() != nil else {
return
}
// Disconnect previous FCM connection if it exists.
FIRMessaging.messaging().disconnect()
FIRMessaging.messaging().connect { (error) in
if error != nil {
print("Unable to connect with FCM. \(String(describing: error))")
} else {
print("Connected to FCM.")
}
}
}
// [END connect_to_fcm]
// Successful registration and you have a token. Send the token to your provider, in this case the console for cut and paste.
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenType.sandbox)
print("Successful registration. Token is:")
print(tokenString(deviceToken))
}
// Failed registration. Explain why.
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("Failed to register for remote notifications: \(error.localizedDescription)")
}
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
return FBSDKApplicationDelegate.sharedInstance().application(application, open: url, sourceApplication: sourceApplication, annotation: annotation)
}
func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
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()
FBSDKAppEvents.activateApp()
FIRMessaging.messaging().connect { error in
print(error as Any)
}
}
#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)
// Change this to your preferred presentation option
completionHandler(.badge)
}
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]
// [START ios_10_data_message_handling]
extension AppDelegate : FIRMessagingDelegate {
// Receive data message on iOS 10 devices while app is in the foreground.
func applicationReceivedRemoteMessage(_ remoteMessage: FIRMessagingRemoteMessage) {
print(remoteMessage.appData)
}
}
// [END ios_10_data_message_handling]
There is no error behind this. Its just that this method will not get called unless you tap on the notification.
Related
This is my appdelegate where is my notification implementations goes on. Sometimes I register with token and token is received. But not receiving notifications. But some time there is no registration with token at all. This is my code below.
import UIKit
import UserNotifications
import RxSwift
//import Firebase
//import Messages
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
let gcmMessageIDKey = "gcm.message.shopflow.key"
var window: UIWindow?
let userdefaults = Foundation.UserDefaults.standard
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
// FirebaseApp.configure()
// [START set_messaging_delegate]
// Messaging.messaging().delegate = self
// [END set_messaging_delegate]
UNUserNotificationCenter.current().delegate = self
registerForPushNotifications()
checkReachability()
checkRegisterdUser()
// Check whether the app has opened from a notification or a normal launch
//crashing code
// let remoteNotif = launchOptions?[UIApplicationLaunchOptionsKey.remoteNotification] as? NSDictionary
// if remoteNotif != nil {
// let notifName = remoteNotif?["aps"] as! String
// print("Notification: \(notifName )")
// }else{
// print("Not remote")
// }
return true
}
func applicationWillResignActive(_ application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
func applicationDidEnterBackground(_ application: UIApplication) {
checkReachability()
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(_ application: UIApplication) {
checkReachability()
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(_ application: UIApplication) {
checkReachability()
// 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.
}
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
// check connectivity
func checkReachability(){
if ReachabilityHelper.shared.checkNetworkReachability(){
}else{
showNetworkAlert()
}
}
// show network alert
func showNetworkAlert(){
let alertController = UIAlertController(title: "Connection Error", message:"An active internet connection is needed to use this app.Please make sure you are connected and try again.", preferredStyle: .alert)
let okAction = UIAlertAction(title: NSLocalizedString("Retry", comment: ""), style: UIAlertActionStyle.default) {
UIAlertAction in
if ReachabilityHelper.shared.checkNetworkReachability(){
//print("Connected")
}else{
// print("Not connected")
self.showNetworkAlert()
}
}
alertController.addAction(okAction)
window!.rootViewController?.present(alertController, animated: true, completion: nil)
}
func checkRegisterdUser(){
// let storyBoard = UIStoryboard(name: storyboardIdentifier., bundle: <#T##Bundle?#>)
if UserDefaults.standard.bool(forKey: Key.loginStatus){
let vc = UIStoryboard(name: storyboardIdentifier.home.rawValue, bundle: nil).instantiateViewController(withIdentifier: viewControllerIdentifiers.tabBar.rawValue) as! UITabBarController
Constants.AppObjects.appDelegate.window?.rootViewController = vc
// self.present(vc, animated: true, completion: nil)
}
}
func registerForPushNotifications() {
// 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)
// UIApplication.shared.registerUserNotificationSettings(settings)
// }
//
// UIApplication.shared.registerForRemoteNotifications()
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) {
(granted, error) in
print("Permission granted: \(granted)")
guard granted else { return }
self.getNotificationSettings()
}
}
func getNotificationSettings() {
UNUserNotificationCenter.current().getNotificationSettings { (settings) in
print("Notification settings: \(settings)")
guard settings.authorizationStatus == .authorized else { return }
DispatchQueue.main.async(execute: {
UIApplication.shared.registerForRemoteNotifications()
})
}
}
// private func application(_ application: UIApplication, didRegister notificationSettings: UNNotificationSettings) {
//// if notificationSettings. != UIUserNotificationType() {
// application.registerForRemoteNotifications()
//// }
// }
// 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 to
// the FCM registration token.
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {
userdefaults.set("NA", forKey: "DEVICE_TOKEN")
userdefaults.synchronize()
print("Registration failed!")
}
func application(_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
// With swizzling disabled you must set the APNs token here.
// Messaging.messaging().apnsToken = deviceToken
let tokenParts = deviceToken.map { data -> String in
return String(format: "%02.2hhx", data)
}
let token = tokenParts.joined()
print("Device Token: \(token)")
userdefaults.set(token, forKey:"DEVICE_TOKEN")
userdefaults.synchronize()
_ = HomeViewModel().deviceToken().subscribe(onNext:{ message in
if message == response.success.rawValue{
//print("Signup done")
print("new Device Token device registation")
}else if message != ""{
print("shopErrors:fail Device Token device registation")
//print(alertMessage)
}
}).disposed(by: DisposeBag())
}
// func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
//
// if let remoteNotification = launchOptions?[UIApplicationLaunchOptionsKey.remoteNotification] as! [NSObject : AnyObject]? {
//
// }
// }
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)
}
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
// Let FCM know about the message for analytics etc.
// Messaging.messaging().appDidReceiveMessage(userInfo)
// handle your message
}
}
#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, .sound, .badge])
}
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()
}
func registerForPushNitfication(){
registerForPushNotifications()
}
}
//extension AppDelegate: MessagingDelegate{
// func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
// let dataDic: [String: String] = ["token": fcmToken]
// NotificationCenter.default.post(name: Notification.Name("FCMToken"), object: nil, userInfo: dataDic)
//
// userdefaults.set(dataDic["token"], forKey:"DEVICE_TOKEN")
// userdefaults.synchronize()
//
// _ = HomeViewModel().deviceToken().subscribe(onNext:{ message in
//
// if message == response.success.rawValue{
// //print("Signup done")
// print("shopErrors:new Device Token device registation")
// }else if message != ""{
// print("shopErrors:fail Device Token device registation")
// //print(alertMessage)
// }
//
// }).disposed(by: DisposeBag())
// }
//
//}
I register for APNs and enable push notifications and also background notification fetch capability. But I couldn't resolve this. Anyone can find an answer?
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 successfully added firebase and notification in my project. Using this Notifications are coming and I can access them by tapping on that notification. But the issue is if my app is closed, I got a notification, now without tapping on that I cleared that. Now no data inserted in my Db. How to keep all notifications on queue to access directly when app is opened next time. Thanks in advance.
class AppDelegate: UIResponder, UIApplicationDelegate , CLLocationManagerDelegate , FIRMessagingDelegate , UNUserNotificationCenterDelegate {
var window: UIWindow?
var locationManager = CLLocationManager()
var utill = FencingUtil()
var wrap = WrapperApi()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
if launchOptions != nil{
let userInfo = launchOptions?[UIApplicationLaunchOptionsKey.remoteNotification]
if userInfo != nil {
self.handleUserInfo(userinfo: userInfo as! [AnyHashable : Any])
// Perform action here
}
}
self.locationManager.delegate = self
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.distanceFilter = 50.0; // Will notify the LocationManager every 100 meters
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
GMSServices.provideAPIKey("AIzaSyDNoFY_sbP9j-ObZx06B_rmjcCVrCM_ZP0")
GMSPlacesClient.provideAPIKey("AIzaSyDNoFY_sbP9j-ObZx06B_rmjcCVrCM_ZP0")
FIRApp.configure()
// var db: SQLiteDatabase
let dataStore = SQLiteDataStore.sharedInstance
do {
try dataStore.createTables()
}
catch _{}
if #available(iOS 10.0, *) {
let center = UNUserNotificationCenter.current()
center.delegate = self
center.requestAuthorization(options: [.badge, .sound, .alert], completionHandler: {(grant, error) in
if error == nil {
if grant {
application.registerForRemoteNotifications()
} else {
//User didn't grant permission
}
} else {
print("error: ",error)
}
})
// For iOS 10 display notification (sent via APNS)
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
return true
}
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
print("Handle push from foreground")
// custom code to handle push while app is in the foreground
//print("\(notification.request.content.userInfo)")
self.handleUserInfo(userinfo: notification.request.content.userInfo)
}
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
print("Handle push from background or closed")
// if you set a member variable in didReceiveRemoteNotification, you will know if this is from closed or background
self.handleUserInfo(userinfo: response.notification.request.content.userInfo)
}
func applicationReceivedRemoteMessage(_ remoteMessage: FIRMessagingRemoteMessage)
{
print("%#", remoteMessage.appData)
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any])
{ self.application(application, didReceiveRemoteNotification: userInfo) { (UIBackgroundFetchResult) in }
print ("dasdasd")
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
self.handleUserInfo(userinfo: userInfo)
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenType.sandbox)
FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenType.prod)
}
func tokenRefreshNotificaiton(_ notification: Foundation.Notification) {
guard let refreshedToken = FIRInstanceID.instanceID().token()
else {
return
}
//refreshedToken = FIRInstanceID.instanceID().token()!
print("InstanceID token: \(refreshedToken)")
utill.tokenDefault.setValue(refreshedToken, forKey: "tokenId")
// Connect to FCM since connection may have failed when attempted before having a token.
connectToFcm()
}
// [START connect_to_fcm]
func connectToFcm() {
FIRMessaging.messaging().connect { (error) in
if (error != nil) {
print("Unable to connect with FCM. \(String(describing: error))")
} else {
//print("Connected to FCM.")
}
}
}}
if you are launching your application then you can get you notification object in didFinishLaunchingWithOptions method try this. if you have
not cleared notification from notification center.
if (launchOptions != nil) {
if let remoteNotification = launchOptions?
[UIApplicationLaunchOptionsKey.remoteNotification] {
let objNotification = remoteNotification as! [AnyHashable :
Any]
}
}
I am currently working on setting up Firebase push notifications with the console and with Firebase functions. I went through the documentation that was available on github to get everything setup, but for some reason nothing appears on my actual phone that I am testing it on, not the simulator. When I send a push notification from my Firebase console to my phone the message appears in my console, but there's no sound or banner that comes down wether i'm in my phone or not. This is the code I have in my app delegate.
import UIKit
import Firebase
import FirebaseMessaging
import UserNotifications
import FBSDKCoreKit
import Stripe
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
let gcmMessageIDKey = "gcm.message_id"
func application(_ application: UIApplication, didFinishLaunchingWithOptions
launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
FIRApp.configure()
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)
FIRMessaging.messaging().remoteMessageDelegate = self
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
NotificationCenter.default.addObserver(self,
selector: #selector(self.tokenRefreshNotification),
name: .firInstanceIDTokenRefresh,
object: nil)
FIRDatabase.database().persistenceEnabled = true
let ref = FIRDatabase.database().reference()
ref.keepSynced(true)
FBSDKApplicationDelegate.sharedInstance().application(application,didFinishLaunchingWithOptions: launchOptions)
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
return true
}
return true
}
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
let handled = FBSDKApplicationDelegate.sharedInstance().application(app, open: url, sourceApplication: options[UIApplicationOpenURLOptionsKey.sourceApplication] as! String!, annotation: options[UIApplicationOpenURLOptionsKey.annotation])
return handled
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
print("APNS token retrieved \(deviceToken)")
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("This is the error that appeared when trying to prompt user for remotenotifications\(error)")
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
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) {
// TODO: Handle data of notification
// Print message ID.
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
// Print full message.
print(userInfo)
completionHandler(UIBackgroundFetchResult.newData)
}
// [END receive_message]
// [START refresh_token]
func tokenRefreshNotification(_ notification: Notification) {
if let refreshedToken = FIRInstanceID.instanceID().token() {
print("InstanceID token: \(refreshedToken)")
}
// Connect to FCM since connection may have failed when attempted before having a token.
connectToFcm()
}
// [END refresh_token]
// [START connect_to_fcm]
func connectToFcm() {
// Won't connect since there is no token
guard FIRInstanceID.instanceID().token() != nil else {
return
}
// Disconnect previous FCM connection if it exists.
FIRMessaging.messaging().disconnect()
FIRMessaging.messaging().connect { (error) in
if error != nil {
print("Unable to connect with FCM. \(error?.localizedDescription ?? "")")
} else {
print("Connected to FCM.")
}
}
}
func applicationWillResignActive(_ application: UIApplication) {
}
func applicationDidEnterBackground(_ application: UIApplication) {
print("entered background")
}
func applicationWillEnterForeground(_ application: UIApplication) {
}
func applicationDidBecomeActive(_ application: UIApplication) {
connectToFcm()
}
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
}
#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)
// 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]
// [START ios_10_data_message_handling]
extension AppDelegate : FIRMessagingDelegate {
// Receive data message on iOS 10 devices while app is in the foreground.
func applicationReceivedRemoteMessage(_ remoteMessage: FIRMessagingRemoteMessage) {
print(remoteMessage.appData)
}
}
You need to pass 'UNNotificationPresentationOptions' in completion handler like this in 'willPresent notification' delegate method
completionHandler([.alert, .badge, .sound])
Thanks
Probably the app is running foregrounded, try to put the app in the background and try again. Check the settings of iPhone to see if banners are disabled for your app. Or if you are sending a silent push. Good luck.
I have a problem similar to:
iOS not receiving notifications from Firebase Cloud Messaging
In my Firebase console I added from my KeyChain my Apple iOS Development Push Service .p12 key also, I added the GoogleService-Info.plist and the identifiers are ok.
Also, in my Capabilities the Push Notifications, Background Modes > Background fetch and Remote notifications and Keychain Sharing are active.
And my AppDelegate.swift looks:
import UIKit
import GoogleMaps
//import FacebookCore
import FBSDKCoreKit
import UserNotifications
import Firebase
import FirebaseCore
import FirebaseInstanceID
import FirebaseMessaging
#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.
FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
GMSServices.provideAPIKey("xxxx-xxx")
if #available(iOS 10.0, *) {
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: {_, _ in })
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self
// For iOS 10 data message (sent via FCM)
FIRMessaging.messaging().remoteMessageDelegate = self
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
// [END register_for_notifications]
FIRApp.configure()
// [START add_token_refresh_observer]
// Add observer for InstanceID token refresh callback.
//NotificationCenter.default.addObserver(self, selector: #selector(self.tokenRefreshNotification), name: .firInstanceIDTokenRefresh, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.tokenRefreshNotification), name: NSNotification.Name.firInstanceIDTokenRefresh, object: nil)
return true
}
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
//return FBSDKApplicationDelegate.sharedInstance().application(app, open: url, options: options)
let appId = FBSDKSettings.appID()
if url.scheme != nil && url.scheme!.hasPrefix("fb\(appId)") && url.host == "authorize" { // facebook
//return SDKApplicationDelegate.shared.application(app, open: url, options: options)
return FBSDKApplicationDelegate.sharedInstance().application(app, open: url, options: options)
}
return false;
}
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.
FBSDKAppEvents.activateApp()
}
func applicationWillResignActive(_ application: UIApplication) {
}
func applicationWillEnterForeground(_ application: UIApplication) {
}
func applicationWillTerminate(_ application: UIApplication) {
}
func connectToFcm() {
FIRMessaging.messaging().connect { (error) in
if (error != nil) {
print("Unable to connect with FCM. \(error)")
} else {
print("Connected to FCM.")
}
}
}
/*func connectToFcm() {
// Won't connect since there is no token
guard FIRInstanceID.instanceID().token() != nil else {
return;
}
// Disconnect previous FCM connection if it exists.
FIRMessaging.messaging().disconnect()
FIRMessaging.messaging().connect { (error) in
if error != nil {
print("Unable to connect with FCM. \(error)")
} else {
print("Connected to FCM.")
}
}
}*/
func applicationDidEnterBackground(_ application: UIApplication) {
FIRMessaging.messaging().disconnect()
print("Disconnected from FCM.")
}
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
// 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
// Print message ID.
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
// Print full message.
print(userInfo)
completionHandler(UIBackgroundFetchResult.newData)
}
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
// Let FCM know about the message for analytics etc.
FIRMessaging.messaging().appDidReceiveMessage(userInfo)
// handle your message
}
func tokenRefreshNotification(_ notification: Notification) {
if let refreshedToken = FIRInstanceID.instanceID().token() {
print("InstanceID token: \(refreshedToken)")
}
// Connect to FCM since connection may have failed when attempted before having a token.
connectToFcm()
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
var token = ""
for i in 0..<deviceToken.count {
token = token + String(format: "%02.2hhx", arguments: [deviceToken[i]])
}
//Tricky line
FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenType.sandbox)
print("Device Token:", token)
print("Token:", deviceToken)
// With swizzling disabled you must set the APNs token here.
// FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenType.sandbox)
}
}
// [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
// 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]
// [START ios_10_data_message_handling]
extension AppDelegate : FIRMessagingDelegate {
// Receive data message on iOS 10 devices while app is in the foreground.
func applicationReceivedRemoteMessage(_ remoteMessage: FIRMessagingRemoteMessage) {
print(remoteMessage.appData)
}
}
// [END ios_10_data_message_handling]
When I sent a message from the Firebase console I get a message like:
Message ID: 0:1xxxx5994%84df84xxxxx
[AnyHashable("google.c.a.e"): 1, AnyHashable("google.c.a.ts"): 14871xxx, AnyHashable("google.c.a.udt"): 0, AnyHashable("gcm.n.e"): 1, AnyHashable("aps"): {
alert = "This is a test";
}, AnyHashable("google.c.a.c_id"): 5884120750xxxxxx, AnyHashable("gcm.message_id"): 0:1xxxx5994%84df84xxxxx]
But for some reason the push notification never appears on my device.
What I'm doing wrong?