Problem:
Cannot receive push notification for my from firebase given the fact that I was able to receive the device token and firebase token.
Here are my main calls in my AppDelegate.swift
UIApplication.shared.registerForRemoteNotifications()
This call is successful and I am able to establish connection to APNS because I was able to get my token with this call:
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)
Also, I know I am connecting to firebase because I am able to get my firebase token with this call:
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String)
So I am pretty confident that my code in AppDelegate.swift is fine.
Here are my steps to configure firebase push notification:
Downloaded my google-service.plist file and dragged it into my project
Logged into my apple developers account (paid) and created my Key with push notification (copied down the KeyID and along with my teamID or App prefix).
Went into my firebase account and uploaded my Key along with my KeyID and TeamID
I made sure my app capabilities got the push notification switch to ON
Tried sending a test message and app never receives one
My AppDelegate.swift:
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate, MessagingDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
UIApplication.shared.applicationIconBadgeNumber = 0
// Override point for customization after application launch.
loggingWithSwitftyBeaverConfiguration()
UNUserNotificationCenter.current().delegate = self
// requesting user's permission to accpet push notification
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in
if granted == true {
log.debug("User granted push notification")
UNUserNotificationCenter.current().delegate = self
Messaging.messaging().delegate = self
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
} else {
log.debug("User did not grant pn")
}
}
return true
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
log.debug("Device token receiving failed because: \(error.localizedDescription)")
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let token = deviceToken.map {String(format: "%02.2hhx", $0)}.joined()
log.debug("Token: \(token)")
}
func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingRemoteMessage) {
log.debug("\(remoteMessage.description)")
}
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
log.debug("Firebase cloud messaging token: \(fcmToken)")
}
func applicationDidBecomeActive(_ application: UIApplication) {
Messaging.messaging().shouldEstablishDirectChannel = true
}
func applicationDidEnterBackground(_ application: UIApplication) {
Messaging.messaging().shouldEstablishDirectChannel = false
}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
UIApplication.shared.applicationIconBadgeNumber += 1
print("push notification received")
}
}
Extra information: I was able to receive test notifications by using pusher, just wanted to throw it out there,
Thank you
UPDATE: - working code:
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var compositionRoot: CompositionRoot?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
window = UIWindow()
configureCompositionRoot()
configureFirebase()
configurePushNotification()
configureApplicationEntryPoint()
configureLogging()
return true
}
func configureCompositionRoot() {
guard let window = window else { return }
compositionRoot = CompositionRoot(window: window)
}
func configureApplicationEntryPoint() {
guard let compositionRoot = compositionRoot else { return }
compositionRoot.getCoordinator().onStart()
}
func configureLogging() {
let console = ConsoleDestination()
log.addDestination(console)
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let token = deviceToken.map {String(format: "%02.2hhx", $0)}.joined()
print("Token: \(token)")
Messaging.messaging().apnsToken = deviceToken
//Messaging.messaging().setAPNSToken(deviceToken, type: MessagingAPNSTokenType.prod)
}
}
extension AppDelegate: UNUserNotificationCenterDelegate {
func configureFirebase() {
FirebaseApp.configure()
}
func configurePushNotification() {
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(options: authOptions) { (granted, error) in
if granted == true {
print("User granted push notification")
UNUserNotificationCenter.current().delegate = self
Messaging.messaging().delegate = self
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
} else {
print("User did not grant pn")
}
}
}
}
extension AppDelegate: MessagingDelegate {
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
}
}
Please check your payload. It might be the reason that you are not receiving notifications.
Your payload should like:
{
"to": "APA91bHun4MxP5egoKMwt2KZFBaFUH-1RYqx...",
"notification": {
"body": "great match!",
"title": "Portugal vs. Denmark",
"icon": "myicon"
},
"data": {
"Nick": "Mario",
"Room": "PortugalVSDenmark"
}
}
Having all data under data does not trigger any notification in iOS even though Firebase returns a successful request because the forwarded APNS payload is not correct. Besides the proper way should be to follow the GCM or FCM payload recommendations, which is to use both notification for the notification message and data for custom key/value pairs.
When FCM Send data to APNS it convert it into APNs payload. It set values of notification in aps tag i.e.
{
"aps" : {
"alert" : {
"title" : "Portugal vs. Denmark",
"body" : "Portugal vs. Denmark",
}
},
"Nick" : "Mario",
"Room" : "PortugalVSDenmark"
}
[Follow the step by step process define here..]
https://firebase.google.com/docs/cloud-messaging/ios/client
Another possible lead is to disable Firebase Swizzling as explained here :
https://firebase.google.com/docs/cloud-messaging/ios/client
Related
How can I go to another view controller after successfully signing with google? I've tried "self.inputViewController?.performSegue(withIdentifier: "goToMain", sender: self)" in my App Delegate but not getting any respond. Am I supposed to add the method in App Delegate or the view controller with the sign-in button?
App Delegate
import UIKit
import Firebase
import GoogleSignIn
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, GIDSignInDelegate{
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
GIDSignIn.sharedInstance()?.clientID = "my_client_id"
GIDSignIn.sharedInstance()?.delegate = self
return true
}
func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {
if let error = error {
print(error)
return
}
guard
let authentication = user?.authentication,
let idToken = authentication.idToken
else {
return
}
let credential = GoogleAuthProvider.credential(withIDToken: idToken,
accessToken: authentication.accessToken)
Auth.auth().signIn(with: credential) { authResult, error in
if let error = error {
let authError = error as NSError
print(authError.localizedDescription)
return
}
self.inputViewController?.performSegue(withIdentifier: "goToMain", sender: self)
}
}
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
return GIDSignIn.sharedInstance().handle(url)
}
// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}
}
Are you sure about the inputViewController is not nil? This may a reason for not working.
You can add a function to test this, or you can use the print function to check, or, you can use debug point to check inputViewController is nil or not.
I'd like to add comment but I don't have enough reputation point :).
Good luck.
I am getting FCM messages pushed to my iOS device fine when in the background but not in the foreground. I have found a number of articles where others had the same issue and solved it by adding the willPresentNotification function. However this isn't solving the issue for me. My FCM code is as follows:
class FCMManager: NSObject, MessagingDelegate, UNUserNotificationCenterDelegate {
static let shared = FCMManager()
let database = Database.database().reference()
public func registerForPushNotifications() {
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .sound, .announcement, .badge, .carPlay, .providesAppNotificationSettings]
UNUserNotificationCenter.current()
.requestAuthorization( options: authOptions,
completionHandler: { granted, _ in
guard granted else {
print("Apple push notifications are not registered")
return
}
print("Apple push notifications are registered")
})
Messaging.messaging().delegate = self
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
updatePushTokenIfNeeded()
}
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
updatePushTokenIfNeeded()
}
}
My notification payloads are set up as:
["to" : "fcm_token",
"notification" : ["title" : "Message Title",
"body" : "Message Body",
"sound" : "default",
"badge" : 1]
]
Then my app delegate is as follows:
class AppDelegate: UIResponder, UIApplicationDelegate, MessagingDelegate, UNUserNotificationCenterDelegate {
var window: UIWindow?
let notificationCenter = UNUserNotificationCenter.current()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
let fcmManager = FCMManager()
fcmManager.registerForPushNotifications()
return true
}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
if #available(iOS 14, *) {
completionHandler([.banner])
} else {
completionHandler([.alert])
}
}
}
Am trying to fetch FCM key for push notification from Firebase cloud messaging but am getting nil & error which i mention below
**
Error :- APNS device token not set before retrieving FCM Token for Sender ID '836092823410'. Notifications to this FCM Token will not be delivered over APNS.Be sure to re-retrieve the FCM token once the APNS device token is set.
**
Google Plist File
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CLIENT_ID</key>
<string>836092823410-d76r5bkjrusfmgo6rskqo81l4mk7vmp4.apps.googleusercontent.com</string>
<key>REVERSED_CLIENT_ID</key>
<string>com.googleusercontent.apps.836092823410-d76r5bkjrusfmgo6rskqo81l4mk7vmp4</string>
<key>API_KEY</key>
<string>AIzaSyDpP1n_NRqj9c_Mq-pA2PlRez7AnVM5buw</string>
<key>GCM_SENDER_ID</key>
<string>836092823410</string>
<key>PLIST_VERSION</key>
<string>1</string>
<key>BUNDLE_ID</key>
<string>com.iai.tracker</string>
<key>PROJECT_ID</key>
<string>crucial-audio-334611</string>
<key>STORAGE_BUCKET</key>
<string>crucial-audio-334611.appspot.com</string>
<key>IS_ADS_ENABLED</key>
<false/>
<key>IS_ANALYTICS_ENABLED</key>
<false/>
<key>IS_APPINVITE_ENABLED</key>
<true/>
<key>IS_GCM_ENABLED</key>
<true/>
<key>IS_SIGNIN_ENABLED</key>
<true/>
<key>GOOGLE_APP_ID</key>
<string>1:836092823410:ios:0312dc35c45b23b9e37feb</string>
</dict>
</plist>
Delegate File
import UIKit
import GoogleMaps
import Firebase
import GooglePlaces
import Highcharts
enum BuildTypes: String {
case jsd = "JSD"
case fleetPolice = "FleetPolice"
case veyron = "Veyron"
case jbd = "JBD"
case gpsTracker = "GPSTracker"
case roadLookUp = "RoadLookUp"
case iaitrack = "IAITrack"
}
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, MessagingDelegate {
var window: UIWindow?
let gcmMessageIDKey = "gcm.message_id";
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
//Going through different build type
let buildType: String = Bundle.main.infoDictionary?["BUILD_TYPE"] as? String ?? "Debug"
print("Build type: - ",buildType)
NotificationCenter.default.addObserver(self, selector: #selector(self.notAuthorized), name: HTTPUtil.NotAuthorizedNotification, object: nil);
switch buildType {
case BuildTypes.jsd.rawValue, BuildTypes.fleetPolice.rawValue:
print("JSD")
GMSServices.provideAPIKey("AIzaSyBKsjff4VNWTyu8X3UTYXOBazO0jt_Cnpw");
GMSPlacesClient.provideAPIKey("AIzaSyBKsjff4VNWTyu8X3UTYXOBazO0jt_Cnpw");
case BuildTypes.veyron.rawValue, BuildTypes.jbd.rawValue, BuildTypes.gpsTracker.rawValue:
GMSServices.provideAPIKey("AIzaSyCRWtSQIUsoNhFwMMdeFRX0A74rooHskBg");
GMSPlacesClient.provideAPIKey("AIzaSyCRWtSQIUsoNhFwMMdeFRX0A74rooHskBg");
case BuildTypes.iaitrack.rawValue:
GMSServices.provideAPIKey("AIzaSyC2qDNCajLm1Kq_AuZTS5tE0xJ73R1RTkA");
GMSPlacesClient.provideAPIKey("AIzaSyC2qDNCajLm1Kq_AuZTS5tE0xJ73R1RTkA");
default:
print("REst")
GMSServices.provideAPIKey("AIzaSyAgaZm9nk4RcfgZ0O0R9UgxJ7PRLZt0RB4");
GMSPlacesClient.provideAPIKey("AIzaSyAgaZm9nk4RcfgZ0O0R9UgxJ7PRLZt0RB4");
}
FirebaseApp.configure()
Messaging.messaging().delegate = self
let t = Messaging.messaging().token { token, error in
if (token != nil) {
print(token)
} else {
print(error)
}
}
let token = Messaging.messaging().fcmToken
print("FCM token: \(token ?? "")")
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()
HIChartView.preload()
let u = UserService.getActiveUserLocalCache();
Configuration.setBaseUrl(baseUrl: u?.baseUrl ?? "https://api.fleethunt.in/");
return true
}
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
debugPrint(fcmToken);
}
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)
}
#objc func notAuthorized(){
if let window = self.window{
let mainTabController = window.rootViewController as! MainTabBarController;
mainTabController.selectedIndex = 0;
let home = (mainTabController.viewControllers?[0] as! UINavigationController).viewControllers[0] as! HomeViewController;
home.showLoginVC();
window.makeToast("Not Authorized. You have been logged out");
}
}
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) {
// 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) {
// 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.
self.updateFcmToken();
let u = UserService.getActiveUserLocalCache();
Configuration.setBaseUrl(baseUrl: u?.baseUrl ?? "https://api.fleethunt.in/");
}
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.
}
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
// 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, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
self.updateFcmToken();
// With swizzling disabled you must set the APNs token here.
// Messaging.messaging().apnsToken = deviceToken
}
func updateFcmToken() -> Void{
let mute = UserDefaults.standard.bool(forKey: "mute") ?? false
print(mute);
FCMService.updateFCM(mute: mute) { (resp) in
}
}
var orientationLock = UIInterfaceOrientationMask.portrait
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
return self.orientationLock
}
struct AppUtility {
static func lockOrientation(_ orientation: UIInterfaceOrientationMask) {
if let delegate = UIApplication.shared.delegate as? AppDelegate {
delegate.orientationLock = orientation
}
}
static func lockOrientation(_ orientation: UIInterfaceOrientationMask, andRotateTo rotateOrientation:UIInterfaceOrientation) {
self.lockOrientation(orientation)
UIDevice.current.setValue(rotateOrientation.rawValue, forKey: "orientation")
}
}
}
#available(iOS 10, *)
extension AppDelegate : UNUserNotificationCenterDelegate {
// [START refresh_token]
func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String) {
print("Firebase registration token: \(fcmToken)")
self.updateFcmToken();
}
// [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: MessagingDelegate) {
print("Received data message: \(remoteMessage.description)")
}
// [END ios_10_data_message]
// 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()
}
}
I can't get any push Notidication.
I tried to send a notification from Firebase console, to all the users of the app.
The Console says that the notification been sent to one device (my device), but I do not get anything on my iPhone.
I'm running this code at AppDelegate.swift:
//
// AppDelegate.swift
// mt
//
// Created by ES on 15.6.2018.
// Copyright © 2018 ES. All rights reserved.
//
import UIKit
import Firebase
import FirebaseMessaging
import UserNotifications
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
UIApplication.shared.applicationIconBadgeNumber = 0
registerForPushNotifications()
FirebaseApp.configure()
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) {
// 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) {
// 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) {
// 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:.
}
func application(_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable : Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
let dict = userInfo["aps"] as! NSDictionary
let title = dict["alert"]
print ("#", title!)
}
func registerForPushNotifications() {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) {
(granted, error) in
print("Permission granted: \(granted)")
guard granted else { return }
let viewAction = UNNotificationAction(identifier: "addToCal",
title: "New date available!",
options: [.foreground])
let newsCategory = UNNotificationCategory(identifier: "NEW_SESSION",
actions: [viewAction],
intentIdentifiers: [],
options: [])
UNUserNotificationCenter.current().setNotificationCategories([newsCategory])
self.getNotificationSettings()
}
}
func getNotificationSettings() {
UNUserNotificationCenter.current().getNotificationSettings { (settings) in
print("Notification settings: \(settings)")
guard settings.authorizationStatus == .authorized else { return }
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
}
}
func application(_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let tokenParts = deviceToken.map { data -> String in
return String(format: "%02.2hhx", data)
}
let token = tokenParts.joined()
print("Device Token: \(token)")
}
func application(_ application: UIApplication,
didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("Failed to register: \(error)")
}
}
(I got the Token, so I think that my app have the permission to get notifications)
I want to show fcm message any time if my app is open or not open.I want to catch message and save core data.when my app is opened I will get my message but notification alert doesn't show. But when I close my app it shows my message but I did not get my message in background.. here is my appDelegate
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate , UNUserNotificationCenterDelegate,MessagingDelegate{
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
if #available(iOS 10.0, *) {
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: {_, _ in })
// For iOS 10 data message (sent via FCM
Messaging.messaging().remoteMessageDelegate = self
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
FirebaseApp.configure()
return true
}
//MARK: FCM Token Refreshed
func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String) {
// FCM token updated, update it on Backend Server
}
func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingRemoteMessage) {
print("Messaging",messaging)
print("remoteMessage*******************",remoteMessage)
}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (_ options: UNNotificationPresentationOptions) -> Void) {
print("Handle push from foreground")
// custom code to handle push while app is in the foreground
print("\(notification.request.content.userInfo)")
if UIApplication.shared.applicationState == .active { // In iOS 10 if app is in foreground do nothing.
print("active****")
completionHandler([])
} else { // If app is not active you can show banner, sound and badge.
print("Not active****")
completionHandler([.alert, .badge, .sound])
}
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
print("Handle push from background or closed")
print("\(response.notification.request.content.userInfo)")
}
func tokenRefreshNotification(notification: NSNotification) {
let refreshedToken = InstanceID.instanceID().token()
// print("fcm**************************","Dhruw: Connected to FCM. Token : \(String(describing: refreshedToken))")
var fcm_token = String(describing: refreshedToken!)
print("fcm toker********",fcm_token);
connectToFCM()
}
func connectToFCM() {
Messaging.messaging().shouldEstablishDirectChannel = true
}
func applicationWillResignActive(_ application: UIApplication) {
}
func applicationDidEnterBackground(_ application: UIApplication) {
}
func applicationWillEnterForeground(_ application: UIApplication) {
}
func applicationDidBecomeActive(_ application: UIApplication) {
}
func applicationWillTerminate(_ application: UIApplication) {
self.saveContext()
}
// MARK: - Core Data stack
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "Finjo_Expense_Management")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
guard let messageId = userInfo["gcm.message_id"]
else {
return
}
print(messageId)
print("did*****",userInfo);
let aps = userInfo[AnyHashable("aps")] as? NSDictionary
var message = aps?["alert"] as! String;
print("message",message)
}
// Called when APNs has assigned the device a unique token
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
// Convert token to string
let deviceTokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
// Print it to console
print("APNs device token: \(deviceTokenString)")
//09256B251D3BBEAA50949067DF40AB75E5D2668170AB0C3B0D310205F2876C32
// Persist it in your backend in case it's new
}
// Called when APNs failed to register the device for push notifications
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
// Print the error to console (you should alert the user that registration failed)
print("APNs registration failed: \(error)")
}
func saveContext () {
let context = persistentContainer.viewContext
if context.hasChanges {
do {
try context.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
}
}
With Advance thanks...Please help me
When app is open you need to set localnotification for showing notifications.. otherwise you need to show custom view.