Push Notification doesn't call didReceiveRemoteNotification swift - ios

I have implemented Push Notification using FCM.
When my app is in the foreground and a notification arrive then didReceiveRemoteNotification method is called but when the app is not active it doesn't call this method
I am checking this by setting a bool value to true when app is in background but doesn't change the bool it means it doesn't execute this line..
Here is my method.
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
self.application(application, didReceiveRemoteNotification: userInfo) { (UIBackgroundFetchResult) in
if UIApplication.sharedApplication().applicationState != .Active{
NSUserDefaults.standardUserDefaults().setBool(true, forKey: "AriveNotification")
NSUserDefaults.standardUserDefaults().synchronize()
}else{
NSUserDefaults.standardUserDefaults().setBool(false, forKey: "AriveNotification")
NSUserDefaults.standardUserDefaults().synchronize()
}
}
}
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
if UIApplication.sharedApplication().applicationState != .Active{
NSUserDefaults.standardUserDefaults().setBool(true, forKey: "AriveNotification")
NSUserDefaults.standardUserDefaults().synchronize()
}else{
NSUserDefaults.standardUserDefaults().setBool(false, forKey: "AriveNotification")
NSUserDefaults.standardUserDefaults().synchronize()
}
}
completionHandler(.NewData)
}
For Registering GCM Push Notification i use these method when user sign in successfully.
func userDidLoggedIn() -> Void {
tabBarController = storyboard.instantiateViewControllerWithIdentifier("TabBarController") as! VaboTabBarController
self.window?.rootViewController = self.tabBarController
self.window?.makeKeyAndVisible()
self.registerDeviceForPushNotification(UIApplication.sharedApplication())
}
func connectToFcm() {
FIRMessaging.messaging().connectWithCompletion({error in
if (error != nil) {
print("Unable to connect with FCM. \(error)")
} else {
print("Connected to FCM.")
}
})
}
func application(application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenType.Sandbox)
}
func registerDeviceForPushNotification(application:UIApplication) -> Void {
let settings: UIUserNotificationSettings = UIUserNotificationSettings.init(forTypes: [.Alert,.Badge,.Sound], categories: nil)
self.pushNotificationToken = FIRInstanceID.instanceID().token()!
let userID = self.userData["id"] as! NSNumber
print("InstanceID token: \(self.pushNotificationToken)")
self.registerDeviceOnServerWith(self.pushNotificationToken, userID: userID)
application.registerUserNotificationSettings(settings)
application.registerForRemoteNotifications()
}
func tokenRefreshNotification(notification: NSNotification) {
if let refreshedToken = FIRInstanceID.instanceID().token() {
let userID = self.userData["id"] as! NSNumber
self.registerDeviceOnServerWith(refreshedToken, userID: userID)
print("InstanceID token: \(refreshedToken)")
}
// Connect to FCM since connection may have failed when attempted before having a token.
connectToFcm()
}
PS. I have set Remote-Notification check from capabilities as well as in info.plist. Plus i also have tried by adding "content-available":1 from the notification payload.

You have to write the correct spelling and character placement in Notification Payload.
As per your statement you might have placed incorrect character in content available place.
Please send your payload in this format..
{
"aps":{
"alert":{
"title":"Notification Title Text",
"Body" :"Notification Body",
"content_available":1
}
}
}
You have written content-available it should be content_availble. Now this will wake your app to run your logic in the background as well

Related

Push notifications in iOS suddenly not delivering via Firebase

Recently I stopped receiving Firebase Cloud Messaging APNs notifications. I decided to update to latest version of Firebase pods and my AppDelegate.swift had a few functions deprecated so it currently looks like this now:
import UIKit
import SwiftyJSON
import IQKeyboardManagerSwift
import Firebase
import FirebaseInstanceID
import FirebaseMessaging
import UserNotifications
import AVFoundation
import Crittercism
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, MessagingDelegate, UNUserNotificationCenterDelegate {
var window: UIWindow?
var isPulltoRefreshInProgress: Bool = Bool(false)
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
Crittercism.enable(withAppID: Config.sharedInstance.apteligentAppID())
//To find Home Directory
print("Home Directory - \(NSHomeDirectory())")
IQKeyboardManager.shared.enable = true
IQKeyboardManager.shared.enableAutoToolbar = false
IQKeyboardManager.shared.shouldShowToolbarPlaceholder = false
// IQKeyboardManager.shared.shouldResignOnTouchOutside = true
// UIApplication.shared.statusBarStyle = .lightContent
configureForPushNotification()
registrationForNotification(application: application )
self.startOver()
return true
}
func registrationForNotification(application: UIApplication) {
// iOS 10 support
if #available(iOS 10, *) {
DLog("registrationForNotification")
UNUserNotificationCenter.current().delegate = self
UNUserNotificationCenter.current().requestAuthorization(options:[.badge, .alert, .sound]){ (granted, error) in }
application.registerForRemoteNotifications()
}
else {
application.registerForRemoteNotifications(matching: [.badge, .sound, .alert])
}
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
Tokens.sharedInstance.isNotificationCame = true
NotificationCenter.default.post(name: NSNotification.Name(NotificationCenterIDs.kPushNotificationReceivedNotification), object:self)
if application.applicationState == UIApplication.State.active {
DLog("App is in foreground when notification received")
// app was already in the foreground
} else {
DLog("App was just brought from background to foreground via PUSH")
// app was just brought from background to foreground via PUSH
self.startOver()
}
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
// let application = UIApplication.shared
// if(application.applicationState == .active){
// DLog("user tapped the notification bar when the app is in foreground")
if let window = self.window {
if let viewController = UIStoryboard(name: StoryboardControllerIDs.kStoryboardId, bundle: nil).instantiateViewController(withIdentifier: StoryboardController.kNotificationsViewController) as? NotificationsViewController{
if let rootViewController = window.rootViewController as? UINavigationController{
// DLog("Root: " + String(describing: type(of: rootViewController)))
Tokens.sharedInstance.isNotificationCame = true
rootViewController.pushViewController(viewController, animated: true)
}
}
}
// }
// if(application.applicationState == .inactive)
// {
// DLog("user tapped the notification bar when the app is in background")
// }
/* 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 configureForPushNotification() {
var fileName : String = "GoogleServiceQA-Info"
let currentConfiguration = Bundle.main.object(forInfoDictionaryKey: "Config")! as! String
if currentConfiguration.lowercased() == "production" {
fileName = "GoogleServiceProd-Info"
}
let filePath = Bundle.main.path(forResource: fileName, ofType: "plist")!
let options = FirebaseOptions(contentsOfFile: filePath)
FirebaseApp.configure(options: options!)
Messaging.messaging().delegate = self
// if let refreshedToken = InstanceID.instanceID().token() {
// print("InstanceID token: \(refreshedToken)")
// DeviceTokenConstants.deviceToken = refreshedToken
// }
InstanceID.instanceID().instanceID { (result, error) in
if let error = error {
DLog("Error fetching remote instange ID: \(error)")
} else if let result = result {
DLog("configureForPushNotification - Remote instance ID token: \(result.token)")
DeviceTokenConstants.deviceToken = result.token
}
}
NotificationCenter.default.addObserver(self, selector:
#selector(tokenRefreshNotification), name:
NSNotification.Name.InstanceIDTokenRefresh, object: nil)
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
//Getting errors in Xcode10 for iOS12
let hexString = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
DLog("===DEVICE-TOKEN: \(hexString)")
// In debug mode
Messaging.messaging().apnsToken = deviceToken
Messaging.messaging().setAPNSToken(deviceToken, type: .sandbox)
Messaging.messaging().setAPNSToken(deviceToken, type: .prod)
// In release mode
// InstanceID.instanceID().setAPNSToken(deviceToken, type: InstanceIDAPNSTokenType.prod)
}
// This method will be called when app received push notifications in foreground
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void)
{
completionHandler([.alert, .badge, .sound])
}
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
print("Firebase registration token: \(fcmToken)")
DeviceTokenConstants.deviceToken = fcmToken
FireBaseToken.didReceived = true
}
#objc func tokenRefreshNotification(_ notification: Notification) {
InstanceID.instanceID().instanceID { (result, error) in
if let error = error {
print("Error fetching remote instange ID: \(error)")
} else if let result = result {
print("tokenRefreshNotification - Remote instance ID token: \(result.token)")
DeviceTokenConstants.deviceToken = result.token
let dataDict:[String: String] = ["token": result.token]
NotificationCenter.default.post(name: Notification.Name("FCMToken"), object: nil, userInfo: dataDict)
}
}
// Deprecated code
// if let refreshedToken = InstanceID.instanceID().token() {
// print("InstanceID token: \(refreshedToken)")
// DeviceTokenConstants.deviceToken = refreshedToken
// }
// Connect to FCM since connection may have failed when attempted before having a token.
// connectToFcm()
}
Is there something in this code that may prevent the notification from being delivered or is this an external issue outside of the iOS app? I am able to see tokens being printed in my console for the device token and fcm token, so I feel that the setup in the iOS app is not the issue. I ensured that the app notifications were not disabled in my iPhone.
If you are using keyid instead of certification, you can try to change ur debug mode to release mode then you can try to see if you receive push or u can upload to TestFlight and check if you receive the push.
However it’s better to use certification instead keyid that you can use in debug and in release mode.
I don't understand from your code why it doesn't work, have you tried to follow firebase's guide to the letter? It never gave me problems.

Push notifications being sent but not received iOS - Cloud functions

I'm trying to send push notifications to the iPhone 6s I am using for testing. I've followed through the Firebase documentation and I can't seem to get a notification arrive to the phone. When I try to send a test notification with the FCM token I get after registering, it is classed as "sent" on the firebase console but not "received".
The minimum software version for the app is iOS 13 so I haven't added the deprecated functions for the notification service.
I've tried:
Disabling and reenabling the push notification and background task capabilities in xcode
Created new certificates and provisioning profiles using the capabilities
Uninstalling the app from the phone and reinstalling it
Setting FirebaseAppDelegateProxyEnabled to NO and YES in the Info.plist file
Writing and running the cloud function that will be used to send the notification which runs as "ok" according to the firebase console
Cleaning the build folder
Using all of the tokens that are returned on registering
Any help would be greatly appreciated,
Thanks in advance :)
App Delegate:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
FirebaseApp.configure()
db = Firestore.firestore()
UNUserNotificationCenter.current().delegate = self
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in
print("granted: (\(granted)")
}
application.registerForRemoteNotifications()
Messaging.messaging().delegate = self
InstanceID.instanceID().instanceID { (result, error) in
if let error = error {
print("Error fetching remote instance ID: \(error)")
} else if let result = result {
print("Remote instance ID token: \(result.token)")
}
}
GIDSignIn.sharedInstance().clientID = FirebaseApp.app()?.options.clientID
GIDSignIn.sharedInstance().delegate = self
GADMobileAds.sharedInstance().start(completionHandler: nil)
self.window = UIWindow(frame: UIScreen.main.bounds)
let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
UserDefaults.standard.setValue(false, forKey: "backing_up")
let user = Auth.auth().currentUser
let email = user?.email
let password = UserDefaults.standard.string(forKey: "password")
let setup = UserDefaults.standard.bool(forKey: "accountSetup")
let credential = EmailAuthProvider.credential(withEmail: email ?? "", password: password ?? "")
user?.reauthenticate(with: credential)
if (user?.isEmailVerified ?? false) && setup {
let homeVC = mainStoryboard.instantiateViewController(withIdentifier: "MainViewController")
self.window?.rootViewController = homeVC
self.window?.makeKeyAndVisible()
} else {
do {
try Auth.auth().signOut()
} catch let signOutError as NSError {
print ("Error signing out: %#", signOutError)
}
let loginVC = mainStoryboard.instantiateViewController(withIdentifier: "LoginViewController")
self.window?.rootViewController = loginVC
self.window?.makeKeyAndVisible()
}
return true
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
Messaging.messaging().apnsToken = deviceToken
Messaging.messaging().setAPNSToken(deviceToken, type: .prod)
Messaging.messaging().setAPNSToken(deviceToken, type: .sandbox)
UserDefaults.standard.synchronize()
print("token: \(token)")
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("failed to register for remote notifications with with error: \(error)")
}
// If in foreground
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
let userInfo = notification.request.content.userInfo
// Print message ID.
print("Message ID: \(userInfo["gcm.message_id"]!)")
// Print full message.
print("%#", userInfo)
completionHandler([.alert, .sound])
}
// If in background
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
print("handling notification")
if let notification = response.notification.request.content.userInfo as? [String:AnyObject] {
let message = parseRemoteNotification(notification: notification)
print(message as Any)
}
completionHandler()
}
private func parseRemoteNotification(notification:[String:AnyObject]) -> String? {
if let identifier = notification["identifier"] as? String {
return identifier
}
return nil
}
func messaging(_ messaging: Messaging, didReceiveRegistrationToken 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.
}
FINALLY! I tried to fix the issue by just starting from scratch and began creating another app. Halfway through the process, I found that I hadn't uploaded a .p8 file to Firebase for the app I was trying to get notifications to work for (I thought I had but apparently not).
If you have the same problem, check if your app is properly registered with Firebase on the console for cloud messaging!

Push notification is not receiving in iOS swift?

I am using FCM for push notification. FCM is connected, device is registered successfully and I am able to print device token but the device is not receiving notification.
In general -> capabilities tab -> enabled push notification and remote notification in back ground mode.
Here registering device for remote notification.
func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
let trimEnds:String! = {
deviceToken.description.trimmingCharacters(
in: CharacterSet(charactersIn: "<>"))
}()
let cleanToken:String! = {
trimEnds.replacingOccurrences(of: " ", with: "")
}()
let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
print(token)
UserDefaults.standard.set(token, forKey: "deviceToken")
UserDefaults.standard.synchronize()
#if DEBUG
//For Firebase
FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenType.sandbox)
#else
FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenType.prod)
#endif
print("Device Token:", token)
}
Here I called didReceiveRemoteNotification method to receive notification on the registered device:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
print("-=-=-=-=-\nDid receive notification\n-=-=-=-",userInfo)
print("-=-=-=-=-\n")
NotificationCenter.default.post(name: Notification.Name(rawValue: "notification_recieved"), object: nil)
if userInfo.index(forKey: "chat_id") != nil {
print("messag push")
if (AppUtility?.hasValidText(User.userID))! {
//let friendImage = userInfo["path"] as! String
let chatID = userInfo["chat_id"] as! String
let friendId = userInfo["to"] as! String
let unRead = userInfo["unread"] as! String
print(unRead)
UnReadMsgs = unRead
let dictAPS = userInfo["aps"] as! NSDictionary
let dict = dictAPS["alert"] as! NSDictionary
let friendName = dict["title"] as! String
let friendMsg = dict["body"] as! String
if(UIApplication.shared.applicationState == UIApplicationState.active){
print("app is Active")
if let wd = self.window {
var VC = wd.rootViewController
if(VC is UINavigationController){
VC = (VC as! UINavigationController).visibleViewController
if(VC is ChatViewController!){
print("Chat Screen")
let chatVC : ChatViewController = VC as! ChatViewController
if chatVC.chatId == chatID{
print("Same Chat")
self.clearChatWithChatID(chatID)
}else{
CustomNotificationView.showNotificationPopUp(self.window!, name: friendName, msg: friendMsg, image: "", chat: chatID, friendID: friendId)
playSound()
print("Other Chat")
}
}else{
let nc = NotificationCenter.default
nc.post(name: Notification.Name(rawValue: "MessageGet"),
object: nil,
userInfo: ["unRead":unRead,
"date":Date()])
CustomNotificationView.showNotificationPopUp(self.window!, name: friendName, msg: friendMsg, image: "", chat: chatID, friendID: friendId)
playSound()
print("Other Screen")
}
}
}
}else{
print("app is in BG")
var vc:ChatViewController!
vc = ChatViewController(nibName: "ChatViewController", bundle: nil)
vc.chatId = chatID
vc.otherUserId = friendId
vc.otherUserName = friendName
vc.channelRef = self.channelRef.child("\(chatID)")
vc.friendImageLink = "\(resourceUrl)\("")"
let nav = UINavigationController(rootViewController: vc)
nav.isNavigationBarHidden = false
if let wd = self.window {
var VC = wd.rootViewController
if(VC is UINavigationController){
VC = (VC as! UINavigationController).visibleViewController
}
VC!.present(nav, animated: false, completion: {
})
}
}
}
}else{
let val = userInfo["aps"] as! [String:AnyObject];
let alert = NSString(string: val["alert"] as! String)
if(UIApplication.shared.applicationState == UIApplicationState.inactive || UIApplication.shared.applicationState == UIApplicationState.background)
{
showUserInfo(application, didReceiveRemoteNotification: userInfo)
}
else
{
print("top most vc \(String(describing: UIApplication.shared.keyWindow!.rootViewController!.topMostViewController().presentingViewController)) and presentedvc \(String(describing: UIApplication.shared.keyWindow!.rootViewController!.topMostViewController().presentedViewController))")
if UIApplication.shared.keyWindow!.rootViewController!.topMostViewController() is NYAlertViewController{
let newAlert = AppUtility?.getDisplayAlertController(title: "FitFlow", messageText: alert as String)
let nvVc = UIApplication.shared.keyWindow!.rootViewController!.topMostViewController().presentedViewController
nvVc?.present(newAlert!, animated: true, completion: nil)
return
}
AppUtility?.displayAlert(title:"FitFlow", messageText: alert as String,UIApplication.shared.keyWindow!.rootViewController!.topMostViewController())
}
}
}
I have tested by keeping breakpoints, it does not called didReceiveRemoteNotification method at all. How to receive push notification using above method?
I was also stuck with this earlier.
This requires FCM token, and not the APNS token.
To do so,
Your AppDelegate class needs to have these -
import Firebase
import UserNotifications
import FirebaseMessaging
class AppDelegate: UIResponder,
UIApplicationDelegate,
UNUserNotificationCenterDelegate,
FIRMessagingDelegate {
}
Then subscribe the messaging delegate in didFinishLaunchingWithOptions
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
GIDSignIn.sharedInstance().clientID =
"Your client id"
DispatchQueue.main.async {
FIRApp.configure()
}
FIRMessaging.messaging().remoteMessageDelegate = self
if #available(iOS 10, *) {
UNUserNotificationCenter.current().requestAuthorization(options:[.badge, .alert, .sound]){ (granted, error) in }
application.registerForRemoteNotifications()
}
// iOS 9 support
else if #available(iOS 9, *) {
UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.badge, .sound, .alert], categories: nil))
UIApplication.shared.registerForRemoteNotifications()
}
// iOS 8 support
else if #available(iOS 8, *) {
UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.badge, .sound, .alert], categories: nil))
UIApplication.shared.registerForRemoteNotifications()
}
// iOS 7 support
else {
application.registerForRemoteNotifications(matching: [.badge, .sound, .alert])
}
return true
}
// You dont need didRegisterForRemoteNotificationsWithDeviceToken method anymore
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { }
the token you received from the delegate didRegisterForRemoteNotificationsWithDeviceToken is not useful,
You need to use the FIRInstanceID.instanceID().token()
Add below code in your applicationDidBecomeActive, this will check for FCM token refreshes, and handle that elegantly.
func applicationDidBecomeActive(_ application: UIApplication) {
NotificationCenter.default.addObserver(self, selector:
#selector(tokenRefreshNotification), name:
NSNotification.Name.firInstanceIDTokenRefresh, object: nil)
}
#objc func tokenRefreshNotification(notification: NSNotification) {
if let refreshedToken = FIRInstanceID.instanceID().token() {
print("InstanceID token: \(refreshedToken)")
UserDefaults.standard.set(refreshedToken, forKey: "deviceToken")
self.sendFCMTokenToServer(token: refreshedToken)
}
/*
Connect to FCM since connection may
have failed when attempted before having a token.
*/
else {
connectToFcm()
}
}
func updatePushNotificationWebservice() {
/*
if you want to save that token on your server
Do that here.
else use the token any other way you want.
*/
}
func connectToFcm() {
FIRMessaging.messaging().connect { (error) in
if (error != nil) {
print("Unable to connect with FCM. \(String(describing: error))")
}
else {
print("Connected to FCM.")
/*
**this is the token that you have to use**
print(FIRInstanceID.instanceID().token()!)
if there was no connection established earlier,
you can try sending the token again to server.
*/
let token = FIRInstanceID.instanceID().token()!
self.sendFCMTokenToServer(token: token)
}
}
}
For debugging use the token obtained from FIRInstanceID.instanceID().token()!, and use the push notification firebase console with same token in the >project>Cloud messaging tab.
https://console.firebase.google.com/u/0/
Setting priority to high from backend solves my problem.
Please check from firebase console->cloud messaging(down left item) to send push notification.

PushNotifications not working properly(reliably) in iOS

I am facing some issues with push notifications. We are using Firebase for Push Notificaions. The thing is I am able to receive PushNotifications properly on one iPhone but can’t get them on another iPhone. And I am getting Notifications properly on Android.
What I am doing is Signing-In from a same account and trying push notifications. What is happening is am getting on all android phones, on my iPhone 5S most of all but very few on my iPhone 6.
Here is the code which is used in AppDelegate for setting up the connection.
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
InstanceID.instanceID().setAPNSToken(deviceToken, type: InstanceIDAPNSTokenType.sandbox)
}
#objc func tokenRefreshNotification(notification: Notification){
print("entered tokenRefreshNotification")
let refreshedToken = InstanceID.instanceID().token()
if refreshedToken != nil{
UserDefaults.standard.setValue(refreshedToken, forKey: "token")
}
//UserDefaults.standard.setValue(refreshedToken, forKey: "token")
print("Instance ID token: \(String(describing: refreshedToken))")
connectToFCM()
}
func connectToFCM(){
Messaging.messaging().connect { (error) in
if error != nil{
self.print("Unable to connect to FCM \(String(describing: error))")
return
}
self.print("connected to FCM")
}
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
print("application did receive remote notification")
print(userInfo)
let notification = UILocalNotification()
notification.fireDate = Date()
let notificationType = (userInfo["type"] as! String).lowercased()
switch notificationType {
case "alert" :
print("Show notifications and save in the notifications list.")
notification.alertBody = userInfo["message"] as? String
//code for saving to user defaults
if var notifications = userDefaults.value(forKey: keys.notificationsList) as? [String] {
if let notificationString = notification.alertBody{
notifications.append(notificationString)
userDefaults.setValue(notifications, forKey: keys.notificationsList)
}
} else{
//in case of empty notificationList
if let notificationString = notification.alertBody{
let notifications = [notificationString]
userDefaults.setValue(notifications, forKey: keys.notificationsList)
}
}
//notifications.append(notification.alertBody)
UIApplication.shared.scheduleLocalNotification(notification)
case "advertisement" :
print("Just show the notification and do nothing else.")
notification.alertBody = userInfo["message"] as? String
UIApplication.shared.scheduleLocalNotification(notification)
case "cleardb":
print("Clear everything from Database, but not logout user.")
notification.alertBody = "All data from database had been wiped"
UIApplication.shared.scheduleLocalNotification(notification)
case "update_device":
print("device_data has been updated so download devices info again")
case "logout":
print("logout the user")
Functions.functions.wipeUserDefaults()
notification.alertBody = "Logged out of Ryoking"
UIApplication.shared.scheduleLocalNotification(notification)
default:
print("lol")
}
}
func application(received remoteMessage: MessagingRemoteMessage) {
print("application received remote message")
print(remoteMessage.appData)
}
I have followed this steps from firebase console literally and it works for me like a charm, try it out:
https://firebase.google.com/docs/cloud-messaging/ios/first-message?authuser=0

iOS Push Notifications with Firebase

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.

Resources