I have already written a lot of code in which I set notifications and try to send a notification from a user to another but now here is my problem, there isn't any notification that appears on the other user's device. The app doesn't crash and I have don't have build failed so I really don't know where I am wrong. Thanks in advance for your answers, here's my code...
// Parts about push notifications in AppDelegate.swift
static let NOTIFICATION_URL = "https://gcm-http.googleapis.com/gcm/send"
static var DEVICEID = String()
static let SERVERKEY = "AAAAuIcRiYI:APA91bHA8Q4IJBG9dG4RY9YOZ3v4MlcVZjmYs3XhiMY3xpQm3bTSjrINUiImaE0t17Y6mghR2vN1ezJTMSVFmHlgOUBX8KQZEckgwCkc1tlMdpm_UjxobmrHf3GbvwrKtHVZsJR-v1GG"
#available(iOS 10.0, *){
UNUserNotificationCenter.current().delegate = self
// Request Autorization.
let option : UNAuthorizationOptions = [.alert,.badge,.sound]
UNUserNotificationCenter.current().requestAuthorization(options: option) { (bool, err) in
}
}
else{
let settings : UIUserNotificationSettings = UIUserNotificationSettings(types: [.alert,.badge,.sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
UIApplication.shared.applicationIconBadgeNumber = 0
func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String) {
guard let newToken = InstanceID.instanceID().token() else {return}
AppDelegate.DEVICEID = newToken
connectToFCM()
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
let notification = response.notification.request.content.body
print(notification)
completionHandler()
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
guard let token = InstanceID.instanceID().token() else {return}
AppDelegate.DEVICEID = token
print(token)
connectToFCM()
}
func connectToFCM()
{
Messaging.messaging().shouldEstablishDirectChannel = true
}
// Parts about notifications in messages.swift, I call this function after the user sends a message in way that the person who receives the message receives at the same time a notification.
fileprivate func setupPushNotification(fromDevice:String)
{
Database.database().reference().child("users").child(userID).observeSingleEvent(of: .value, with: { (snapshot) in
let value = snapshot.value as? NSDictionary
let device = value?["device"] as? String ?? ""
guard let message = self.authorText else {return}
let title = "You received a new message !"
let body = "from \(message)"
let toDeviceID = device
var headers:HTTPHeaders = HTTPHeaders()
headers = ["Content-Type":"application/json","Authorization":"key=\(AppDelegate.SERVERKEY)"
]
let notification = ["to":"\(toDeviceID)","notification":["body":body,"title":title,"badge":1,"sound":"default"]] as [String:Any]
Alamofire.request(AppDelegate.NOTIFICATION_URL as URLConvertible, method: .post as HTTPMethod, parameters: notification, encoding: JSONEncoding.default, headers: headers).responseJSON { (response) in
print(response)
}
})
}
Related
So I have a single Xcode project for two iOS app targets that share a common codebase.
The first app was already working and live on the App Store. The second app is just a modified paid version of our earlier app.
Both the apps use Firebase and OneSignal (for push notifications ) and I have downloaded two GoogleServiceInfo.plist files and linked them to their respective targets.
This is my AppDelegate.swift file where I configured Firebase.
import Firebase
import FirebaseMessaging
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var wakeTime : Date = Date() // when did our application wake up most recently?
// To access AppDelegate values
class var shared: AppDelegate {
return (UIApplication.shared.delegate as? AppDelegate) ?? AppDelegate()
}
// To get token for login
var pushRefreshedToken : String {
print(Messaging.messaging().fcmToken)
return Messaging.messaging().fcmToken ?? "token_new_reg"
}
let gcmMessageIDKey = "gcm.message_id"
var notification: Any?
var window: UIWindow?
//this variable is declared so that the app can run on ios 12 or lower running devices, without this it will show black screen.
func applicationWillEnterForeground(_ application: UIApplication) {
// time stamp the entering of foreground so we can tell how we got here
wakeTime = Date()
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
// OneSignal
let notificationOpenedBlock: OSNotificationOpenedBlock = { result in
// This block gets called when the user reacts to a notification received
let notification: OSNotification = result.notification
print("Message: ", notification.body ?? "empty body")
print("badge number: ", notification.badge)
print("notification sound: ", notification.sound ?? "No sound")
if let additionalData = notification.additionalData {
print("additionalData: ", additionalData)
// Handle additional data
switch UIApplication.shared.applicationState {
case .background, .inactive:
// background, opened from notif
if let tag = additionalData["t"] as? String {
if tag == NotificationRedirectionTags.appstore {
CentralLoadingViewController.redirectionTag = tag
} else {
MiddleViewController.notifTag = tag
}
}
case .active:
// foreground
if let topVC = UIApplication.getTopViewController() {
if let tag = additionalData["t"] as? String {
if tag == NotificationRedirectionTags.vehicleHealth {
print("Going to VH")
let storyboard = UIStoryboard(name: StoryBoards.CarHealthStoryboard, bundle: nil)
let nv = storyboard.instantiateViewController(withIdentifier: Identifiers.MainCarHealthViewController) as! MainCarHealthViewController
topVC.navigationController?.pushViewController(nv, animated: true)
}
if tag == NotificationRedirectionTags.appstore {
if let url = URL(string: "https://apps.apple.com/in/app/scouto/id1495648508") {
UIApplication.shared.open(url)
}
}
}
}
default:
break
}
// Handle action buttons
if let actionSelected = notification.actionButtons {
print("actionSelected: ", actionSelected)
}
if let actionID = result.action.actionId {
//handle the action
if actionID == NotificationRedirectionTags.vehicleHealth {
MiddleViewController.notifTag = actionID
} else if actionID == NotificationRedirectionTags.appstore {
CentralLoadingViewController.redirectionTag = actionID
}
}
}
}
OneSignal.setNotificationOpenedHandler(notificationOpenedBlock)
// Remove this method to stop OneSignal Debugging
OneSignal.setLogLevel(.LL_VERBOSE, visualLevel: .LL_NONE)
// OneSignal initialization
OneSignal.initWithLaunchOptions(launchOptions)
#if MAHINDRA_CW_PRODUCTION
OneSignal.setAppId(appIDOne)
#elseif SCOUTO_PRODUCTION
OneSignal.setAppId(appIDTwo)
#endif
// promptForPushNotifications will show the native iOS notification permission prompt.
// We recommend removing the following code and instead using an In-App Message to prompt for notification permission (See step 8)
OneSignal.promptForPushNotifications(userResponse: { accepted in
print("User accepted notifications: \(accepted)")
})
let str = [NotificationRedirectionTags.appstore, "AppStore"]
if str.contains(UserDefaults.standard.value(forKey: NotificationActionTags.inputText) as? String ?? ""){
if let url = URL(string: "https://apps.apple.com/in/app/scouto/id1495648508") {
UIApplication.shared.open(url)
}
}
LocationService.shared.updatingLocation(completion: { location in
if location != nil{
LocationService.shared.stopUpdatingLocation()
} else {
LocationService.shared.showLocationPermissionsAlert(true)
}
})
// FireBase Setup
FirebaseApp.configure()
// notification
if #available(iOS 10.0, *) {
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions) { (granted, error) in
guard granted else { return }
print("UNNotificationCenter Auth Granted")
let replyAction = UNTextInputNotificationAction(identifier: "ReplyAction", title: "Reply", options: [])
let openAppAction = UNNotificationAction(identifier: "OpenAppAction", title: "Open app", options: [.foreground])
let quickReplyCategory = UNNotificationCategory(identifier: "QuickReply", actions: [replyAction, openAppAction], intentIdentifiers: [], options: [])
UNUserNotificationCenter.current().setNotificationCategories([quickReplyCategory])
print("UNNotificationCategory Set")
UNUserNotificationCenter.current().getNotificationSettings { (settings) in
guard settings.authorizationStatus == .authorized else { return }
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
}
}
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
Messaging.messaging().delegate = self
Messaging.messaging().token { token, error in
if let error = error {
print("Error fetching FCM registration token: \(error)")
} else if let token = token {
print("FCM registration token: \(token)")
//self.fcmRegTokenMessage.text = "Remote FCM registration token: \(token)"
}
}
application.registerForRemoteNotifications()
}
//MARK:- Push Notifications
extension AppDelegate {
// DEPRECATED
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("Remote notification: User info 1")
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("User info 2")
print(userInfo)
//completionHandler(UIBackgroundFetchResult.newData)
}
}
// MARK:- Push Notification Handler - UNUserNotificationCenterDelegate
#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("User info 3")
print(userInfo)
// Change this to your preferred presentation option
completionHandler([[.alert, .badge , .sound]])
}
// Notification handler
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)")
}
// With swizzling disabled you must let Messaging know about the message, for Analytics
// Messaging.messaging().appDidReceiveMessage(userInfo)
// Print full message.
print("User info 4")
print( )
// Handle text input notification
if response.actionIdentifier == "ReplyAction" {
print("Entered ReplyAction block")
if let textResponse = response as? UNTextInputNotificationResponse {
// Do whatever you like with user text response...
print("----RECEIVING USER NOTIFICATION INPUT ------")
print(textResponse.userText)
if textResponse.userText == NotificationRedirectionTags.appstore || textResponse.userText == "AppStore" {
if let url = URL(string: "https://apps.apple.com/in/app/scouto/id1495648508") {
UIApplication.shared.open(url)
}
}
UserDefaults.standard.setValue(textResponse.userText, forKey: NotificationActionTags.inputText)
return
}
}
// Handle userInfo data
switch UIApplication.shared.applicationState {
case .background, .inactive:
// background, opened from notif
if let tag = userInfo["t"] as? String {
if tag == NotificationRedirectionTags.appstore {
UserDefaults.standard.setValue(tag, forKey: NotificationActionTags.inputText)
}
MiddleViewController.notifTag = tag
}
case .active:
// foreground
if let topVC = UIApplication.getTopViewController() {
if let tag = userInfo["t"] as? String {
// Go to Vehicle Health
if tag == NotificationRedirectionTags.vehicleHealth {
print("Going to VH")
let storyboard = UIStoryboard(name: StoryBoards.CarHealthStoryboard, bundle: nil)
let nv = storyboard.instantiateViewController(withIdentifier: Identifiers.MainCarHealthViewController) as! MainCarHealthViewController
topVC.navigationController?.pushViewController(nv, animated: true)
}
// Go to Live Track
if tag == "os" {
print("Going to Live Track")
let storyboard = UIStoryboard(name: StoryBoards.DashboardStoryboard, bundle: nil)
let nv = storyboard.instantiateViewController(withIdentifier: Identifiers.LiveTrackingViewController) as! LiveTrackingViewController
topVC.navigationController?.pushViewController(nv, animated: true)
}
}
}
default:
break
}
completionHandler()
}
}
//MARK: MessagingDelegate FCM -> Recieve message from FCM
extension AppDelegate : MessagingDelegate {
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
print("Firebase registration token: \(fcmToken)")
let lokenFCM : String = fcmToken ?? "token_new_reg"
let dataDict:[String: String] = ["token": lokenFCM]
NotificationCenter.default.post(name: Notification.Name("FCMToken"), object: nil, userInfo: dataDict)
// TODO: If necessary send token to application server.
// Note: This callback is fired at each app startup and whenever a new token is generated.
}
// func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingRemoteMessage) {
// print("Message message data", remoteMessage.appData)
// }
}
I have uploaded the same APNS key to Firebase for both the apps in Project settings.
However, the issue is that I am able to receive notifications only on one app and I am not able to receive notifications in the second app.
I have checked the code multiple times but cannot seem to figure out what is going wrong at all.
Please kindly have a look at the code and provide me with some suggestions on what I may be doing wrong. Your help is highly appreciated & thank you!
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 not working at all. I have tried all the possible measures so far:
This is the code that i have tried:
In didFinishLaunchingWithOptions
FirebaseApp.configure()
if #available(iOS 10.0, *) {
let center = UNUserNotificationCenter.current()
center.delegate = self
center.requestAuthorization(options: [.badge, .alert, .sound]) {
(granted, error) in
if granted {
DispatchQueue.main.async {
application.registerForRemoteNotifications()
//UIApplication.shared.registerForRemoteNotifications()
}
} else {
//print("APNS Registration failed")
//print("Error: \(String(describing: error?.localizedDescription))")
}
}
} else {
let type: UIUserNotificationType = [UIUserNotificationType.badge, UIUserNotificationType.alert, UIUserNotificationType.sound]
let setting = UIUserNotificationSettings(types: type, categories: nil)
application.registerUserNotificationSettings(setting)
application.registerForRemoteNotifications()
//UIApplication.shared.registerForRemoteNotifications()
}
Then the register and fail method:
private func application(application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
Messaging.messaging().apnsToken = deviceToken as Data
print("Registered Notification")
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print(error.localizedDescription)
print("Not registered notification")
}
#available(iOS 10, *)
extension AppDelegate : UNUserNotificationCenterDelegate {
// Receive displayed notifications for iOS 10 devices.
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
let userInfo = notification.request.content.userInfo
// With swizzling disabled you must let Messaging know about the message, for Analytics
// Messaging.messaging().appDidReceiveMessage(userInfo)
// Print message ID.
if let messageID = userInfo["gcm.message_id"] {
print("Message ID: \(messageID)")
}
// Print full message.
print(userInfo)
// Change this to your preferred presentation option
completionHandler([])
}
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
// Print message ID.
if let messageID = userInfo["gcm.message_id"] {
print("Message ID: \(messageID)")
}
// Print full message.
print(userInfo)
completionHandler()
}
}
Note:
I have tried it on real device no push notifications so far.
I have double checked the certificates and regenerated the provisioning file after turning on the push notifications in
capabilities.
I have also added background modes -> remote notifications on.
I have tried with legacy build also no luck.
I have tried reinstalling apps many times not working.
FirebaseAppDelegateProxyEnabled is set to NO in plist still no luck.
Also updated the pods still no luck.
.p12 certificate is at the firebase console, still not working.
Trying from last 1 week with different projects with different authentication methods with Apple key i have also tried still no luck.
here is the code i have used to generate push notification hope this helps you out.
put the whole following code in ur appdelegate.
Imported Libraries
import Firebase
import FirebaseMessaging
import UserNotifications
import FirebaseInstanceID
import UserNotifications
add MessagingDelegate to ur appdelegate.
then
In didFinishLaunchingWithOptions
if #available(iOS 10.0, *) {
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(options: authOptions,
completionHandler: { (bool, err) in
})
} else {
let settings: UIUserNotificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
UIApplication.shared.applicationIconBadgeNumber = 0
FirebaseApp.configure()
// [START set_messaging_delegate]
Messaging.messaging().delegate = self
let token = Messaging.messaging().fcmToken
print("FCM token: \(token ?? "")")
Then Add these Two function
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
// If you are receiving a notification message while your app is in the background,
// this callback will not be fired till the user taps on the notification launching the application.
// TODO: Handle data of notification
// With swizzling disabled you must let Messaging know about the message, for Analytics
// Messaging.messaging().appDidReceiveMessage(userInfo)
// Print message ID.
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
// Print full message.
print(userInfo)
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
// If you are receiving a notification message while your app is in the background,
// this callback will not be fired till the user taps on the notification launching the application.
// TODO: Handle data of notification
// With swizzling disabled you must let Messaging know about the message, for Analytics
// Messaging.messaging().appDidReceiveMessage(userInfo)
// put your json parameters here Print message ID.
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
if let msg = userInfo["desc"] as? String
{
let title = userInfo["noti_title"] as? String
createNotification(message: msg, title: title ?? "" )
}
// Print full message.
print(userInfo)
completionHandler(UIBackgroundFetchResult.newData)
}
func createNotification(message: String, title: String) {
let content = UNMutableNotificationContent()
content.title = title
content.body = message
let triger = UNTimeIntervalNotificationTrigger(timeInterval: 2, repeats: false )
let request = UNNotificationRequest(identifier: "TextMessage", content: content, trigger: triger)
UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
}
Then add these functions to get FCMToken
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
print("APNs token retrieved: \(deviceToken)")
// With swizzling disabled you must set the APNs token here.
if let refreshedToken = InstanceID.instanceID().token() {
print("InstanceID token: \(refreshedToken)")
}
let tokenT = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
print(tokenT)
guard let token = InstanceID.instanceID().token() else {return}
AppDelegate.DEVICEID = token
print(token)
UserDefaults.standard.set(token, forKey: "token")
connectToFCM()
}
func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String) {
guard let newToken = InstanceID.instanceID().token() else {return}
AppDelegate.DEVICEID = newToken
UserDefaults.standard.set(newToken, forKey: "token")
connectToFCM()
}
func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingRemoteMessage) {
print("Received data message: \(remoteMessage.appData)")
print(remoteMessage.appData["notification"]!)
// let info = response.notification.request.content.userInfo
// if let message = info["messages"] {
// print(message)
// }
}
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
print("Firebase registration token: \(fcmToken)")
UserDefaults.standard.set(fcmToken, forKey: "token")
}
then add the following extention in your app delegate
extension AppDelegate : UNUserNotificationCenterDelegate {
// Receive displayed notifications for iOS 10 devices.
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
let userInfo = notification.request.content.userInfo
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
print(userInfo)
// Change this to your preferred presentation option
completionHandler([.alert,.badge,.sound])
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
let application = UIApplication.shared
if(application.applicationState == .active){
print("user tapped the notification bar when the app is in foreground")
window = UIWindow(frame: UIScreen.main.bounds)
window?.makeKeyAndVisible()
// let layout = UICollectionViewFlowLayout()
window?.rootViewController = UINavigationController(rootViewController: NotificationViewController())
}
if(application.applicationState == .inactive)
{
print("user tapped the notification bar when the app is in background")
window = UIWindow(frame: UIScreen.main.bounds)
window?.makeKeyAndVisible()
// let layout = UICollectionViewFlowLayout()
window?.rootViewController = UINavigationController(rootViewController: NotificationViewController())
}
/* Change root view controller to a specific viewcontroller */
// let storyboard = UIStoryboard(name: "Main", bundle: nil)
// let vc = storyboard.instantiateViewController(withIdentifier: "ViewControllerStoryboardID") as? ViewController
// self.window?.rootViewController = vc
completionHandler()
}
func connectToFCM()
{
Messaging.messaging().shouldEstablishDirectChannel = true
}
func initializeNotificationServices() -> Void {
let settings = UIUserNotificationSettings(types: [.sound, .alert, .badge], categories: nil)
UIApplication.shared.registerUserNotificationSettings(settings)
// This is an asynchronous method to retrieve a Device Token
// Callbacks are in AppDelegate.swift
// Success = didRegisterForRemoteNotificationsWithDeviceToken
// Fail = didFailToRegisterForRemoteNotificationsWithError
UIApplication.shared.registerForRemoteNotifications()
}
}
hoping this will help you out.
Receive notifications in the background and in the foreground.
but I can't get notifications if the application is killed.
open Background fetch and Remote notification from capabilities
installed on certificates via firebase
json file into "content-available" = true, 'priority'=>'high', I added
I want to be able to receive notifications after the application is completely closed
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate, MessagingDelegate {
var window: UIWindow?
let gcmMessageIDKey = "message_id"
static var DEVICE_ID = String()
var msg_body = ""
var msg_title = ""
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
UIApplication.shared.statusBarStyle = .lightContent
FirebaseApp.configure()
Messaging.messaging().delegate = self
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()
return true
}
func connectToFcm() {
Messaging.messaging().shouldEstablishDirectChannel = true
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
if let refreshedToken = InstanceID.instanceID().token() {
AppDelegate.DEVICE_ID = refreshedToken
print("*********")
print("InstanceID token: \(refreshedToken)")
print("*********")
}else{
print("Can't get token device")
}
connectToFcm()
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("Failed to register for remote notifications with error: \(error)")
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
print(userInfo)
guard let data: [String: Any] = userInfo as? [String: Any] else {
return
}
let listData = data["notification"] as! String
let jsonData = listData.data(using: .utf8)
do {
let decoder = JSONDecoder()
let dataJson = try decoder.decode(DataNotif.self, from: jsonData!)
msg_body = dataJson.body!
msg_title = dataJson.title!
createNotification(title: msg_title, body: msg_body)
}catch{
print("error")
}
completionHandler(UIBackgroundFetchResult.newData)
}
// messaging
func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String) {
if let token = InstanceID.instanceID().token() {
AppDelegate.DEVICE_ID = token
print("*********")
print("Token Instance: \(token)")
print("*********")
}
connectToFcm()
}
func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingRemoteMessage) {
print("Received data message: \(remoteMessage.appData)")
guard let data: [String: Any] = remoteMessage.appData as? [String: Any] else {
return
}
let listData = data as! NSDictionary
let jsonData = listData.data(using: .utf8)
do {
let decoder = JSONDecoder()
let dataJson = try decoder.decode(DataNotif.self, from: jsonData!)
msg_body = dataJson.body!
msg_title = dataJson.title!
createNotification(title: msg_title, body: msg_body)
}catch{
print("error")
}
}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.alert, .badge, .sound])
}
func applicationDidBecomeActive(_ application: UIApplication) {
UIApplication.shared.applicationIconBadgeNumber = 0
connectToFcm()
}
func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
completionHandler(.newData)
}
func applicationDidEnterBackground(_ application: UIApplication) {
Messaging.messaging().shouldEstablishDirectChannel = false
print("Disconnect FCM")
}
func createNotification(title: String, body: String) {
let content = UNMutableNotificationContent()
content.title = NSString.localizedUserNotificationString(forKey: title, arguments: nil)
content.body = NSString.localizedUserNotificationString(forKey: body, arguments: nil)
content.sound = UNNotificationSound.default
content.badge = NSNumber(integerLiteral: UIApplication.shared.applicationIconBadgeNumber + 1)
let request = UNNotificationRequest.init(identifier: "pushNotif", content: content, trigger: nil)
let center = UNUserNotificationCenter.current()
center.add(request)
}
}
You must enable the following :)
Hi I just want to show push Notification with Image. Im using the below code and im not sure where im doing mistake it took me more than 3 weeks, I gone through many Links but still it couldn't be fixed. the below is my App delegate code
AppDelegate.Swift
import UIKit
import UserNotifications
var deviceTokenString:String = ""
var badgeCount = 0
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Push Notification
if #available(iOS 10.0, *)
{
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in
// actions based on whether notifications were authorised or not
guard error == nil else {
//Display Error.. Handle Error.. etc..
return
}
if granted
{
//Do stuff here..
}
else {
//Handle user denying permissions..
}
}
application.registerForRemoteNotifications()
} else {
// Fallback on earlier versions
}
registerForRemoteNotification()
// iOS 10 support
if #available(iOS 10, *) {
UNUserNotificationCenter.current().requestAuthorization(options:[.alert, .sound]){ (granted, error) in }
application.registerForRemoteNotifications()
}
// iOS 9 support
else if #available(iOS 9, *) {
UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.sound, .alert], categories: nil))
UIApplication.shared.registerForRemoteNotifications()
}
// iOS 8 support
else if #available(iOS 8, *) {
UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.sound, .alert], categories: nil))
UIApplication.shared.registerForRemoteNotifications()
}
// iOS 7 support
else {
application.registerForRemoteNotifications(matching: [.sound, .alert])
}
return true
}
func registerForRemoteNotification() {
if #available(iOS 10.0, *) {
let center = UNUserNotificationCenter.current()
center.delegate = self
center.requestAuthorization(options: [.sound, .alert]) { (granted, error) in
if error == nil{
UIApplication.shared.registerForRemoteNotifications()
// UIApplication.shared.applicationIconBadgeNumber = 5
}
}
}
else {
UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.sound, .alert], categories: nil))
UIApplication.shared.registerForRemoteNotifications()
// UIApplication.shared.applicationIconBadgeNumber = 5
}
}
func incrementBadgeNumberBy(badgeNumberIncrement: Int)
{
let currentBadgeNumber = UIApplication.shared.applicationIconBadgeNumber
let updatedBadgeNumber = currentBadgeNumber + badgeNumberIncrement
if (updatedBadgeNumber > 0)
{
UIApplication.shared.applicationIconBadgeNumber = updatedBadgeNumber
}
else
{
UIApplication.shared.applicationIconBadgeNumber = 0
}
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("Couldn't register: \(error)")
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
deviceTokenString = deviceToken.hexString()
// deviceTokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
print("device token: \(deviceTokenString)")
}
// Push notification received
func application(_ application: UIApplication, didReceiveRemoteNotification data: [AnyHashable : Any]) {
// Print notification payload data
badgeCount = badgeCount + 1
self.incrementBadgeNumberBy(badgeNumberIncrement: badgeCount)
print("Push notification received: \(data)")
}
// Notification will present call back
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.alert, .sound, .badge])
print("UserInfo: \(notification.request.content.userInfo)")
var userinfo = NSDictionary()
userinfo = notification.request.content.userInfo as NSDictionary
let imgData = userinfo.value(forKey: "data")! as! NSDictionary
let url = imgData.value(forKey: "attachment-url")
let imgUrl = URL(string: url as! String)!
// 1. Create Notification Content
let content = UNMutableNotificationContent()
// 2. Create Notification Attachment
URLSession.shared.downloadTask(with: imgUrl)
{(location, response, error) in
print("location: \(location!)")
if error == nil
{
if let location = location
{
// Move temporary file to remove .tmp extension
let tmpDirectory = NSTemporaryDirectory()
let tmpFile = "file://".appending(tmpDirectory).appending(imgUrl.lastPathComponent)
print("tmpFile: \(tmpFile)")
let tmpUrl = URL(string: tmpFile)!
print("tmpUrl: \(tmpUrl)")
try! FileManager.default.moveItem(at: location, to: tmpUrl)
// Add the attachment to the notification content
if let attachment = try? UNNotificationAttachment(identifier: "attachment", url: tmpUrl) {
content.attachments = [attachment]
print("attachment: \(content.attachments)")
// 3. Create Notification Request
let request = UNNotificationRequest.init(identifier: String.UNNotificationRequest.NormalLocalPush.rawValue,
content: content, trigger: nil)
content.title = "\(userinfo.value(forKeyPath: "aps.alert.title")!)"
content.body = "\(userinfo.value(forKeyPath: "aps.alert.body")!)"
content.sound = UNNotificationSound.default()
content.badge = (UIApplication.shared.applicationIconBadgeNumber + 1) as NSNumber;
content.categoryIdentifier = String.UNNotificationCategory.Normal.rawValue
// 4. Add to NotificationCenter
let center = UNUserNotificationCenter.current()
center.add(request)
}
}
}
else
{
print("Error: \(error!)")
}
}.resume()
}
#available(iOS 10.0, *)
// Notification interaction response call back
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void) {
print("\(response.notification.request.content.userInfo)")
var userinfo = NSDictionary()
userinfo = response.notification.request.content.userInfo as NSDictionary
let imgData = userinfo.value(forKey: "data")! as! NSDictionary
let url = imgData.value(forKey: "attachment-url")
let imgUrl = URL(string: url as! String)!
// 1. Create Notification Content
let content = UNMutableNotificationContent()
content.title = "\(userinfo.value(forKeyPath: "aps.alert.title")!)"
content.body = "\(userinfo.value(forKeyPath: "aps.alert.body")!)"
content.sound = UNNotificationSound.default()
content.badge = (UIApplication.shared.applicationIconBadgeNumber + 1) as NSNumber;
content.categoryIdentifier = String.UNNotificationCategory.Normal.rawValue // 设置通知类型标示
// 2. Create Notification Attachment
URLSession.shared.downloadTask(with: imgUrl) { (location, response, error) in
if let location = location {
// Move temporary file to remove .tmp extension
let tmpDirectory = NSTemporaryDirectory()
let tmpFile = "file://".appending(tmpDirectory).appending(imgUrl.lastPathComponent)
let tmpUrl = URL(string: tmpFile)!
try! FileManager.default.moveItem(at: location, to: tmpUrl)
// Add the attachment to the notification content
if let attachment = try? UNNotificationAttachment(identifier: "", url: tmpUrl) {
content.attachments = [attachment]
}
}
// Serve the notification content
// self.contentHandler!(content)
}.resume()
// if let attachement = try? UNNotificationAttachment(identifier: "attachment", url: imgUrl, options: nil)
// {
// content.attachments = [attachement]
// }
// 3. Create Notification Request
let request = UNNotificationRequest.init(identifier: String.UNNotificationRequest.NormalLocalPush.rawValue,
content: content, trigger: nil)
// 4. Add to NotificationCenter
let center = UNUserNotificationCenter.current()
center.add(request)
let responseNotificationRequestIdentifier = response.notification.request.identifier
if responseNotificationRequestIdentifier == String.UNNotificationRequest.NormalLocalPush.rawValue ||
responseNotificationRequestIdentifier == String.UNNotificationRequest.LocalPushWithTrigger.rawValue ||
responseNotificationRequestIdentifier == String.UNNotificationRequest.LocalPushWithCustomUI1.rawValue ||
responseNotificationRequestIdentifier == String.UNNotificationRequest.LocalPushWithCustomUI2.rawValue {
let actionIdentifier = response.actionIdentifier
switch actionIdentifier {
case String.UNNotificationAction.Accept.rawValue:
break
case String.UNNotificationAction.Reject.rawValue:
break
case String.UNNotificationAction.Input.rawValue:
break
case UNNotificationDismissActionIdentifier:
break
case UNNotificationDefaultActionIdentifier:
break
default:
break
}
}
completionHandler();
}
}
extension Data
{
func hexString() -> String
{
return self.reduce("") { string, byte in
string + String(format: "%02X", byte)
}
}
}
And below is my Extension Code which im using for custom Push notification,
Extension.swift
import Foundation
extension String {
enum UNNotificationAction : String {
case Accept
case Reject
case Input
}
enum UNNotificationCategory : String {
case Normal
case Cheer
case CheerText
}
enum UNNotificationRequest : String {
case NormalLocalPush
case LocalPushWithTrigger
case LocalPushWithCustomUI1
case LocalPushWithCustomUI2
}
}
extension URL {
enum ResourceType : String {
case Local
case Local1
case Remote
case AttachmentRemote
}
static func resource(type :ResourceType) -> URL
{
switch type {
case .Local:
return Bundle.main.url(forResource: "cheer", withExtension: "png")!
case .Local1:
return Bundle.main.url(forResource: "hahaha", withExtension: "gif")!
case .Remote:
return URL(string: "http://ww1.sinaimg.cn/large/65312d9agw1f59leskkcij20cs0csmym.jpg")!
case .AttachmentRemote:
return URL(string: "https://assets-cdn.github.com/images/modules/open_graph/github-mark.png")!
}
}
}
extension URLSession {
class func downloadImage(atURL url: URL, withCompletionHandler completionHandler: #escaping (Data?, NSError?) -> Void) {
let dataTask = URLSession.shared.dataTask(with: url) { (data: Data?, response: URLResponse?, error: Error?) in
completionHandler(data, error as NSError?)
}
dataTask.resume()
}
}
and My Api response is,
[AnyHashable("aps"):
{
alert = {
body = test;
title = "N-Gal";
};
"mutable-content" = 1;
sound = default;
},
AnyHashable("data"):
{
"attachment-url" = "https://www.n-gal.com/image/cache/catalog/HomeBanner/Banners/1172X450-N-Gal-Footwear-Banner-100x100.jpg";
}]
This code is based on the tutorial https://github.com/maquannene/UserNotifications. Please give me a solution to fix this... Thanks in Advance...!
From your code snippet I conclude you are talking about remote notifications. That's an important distinction. If you want to 'enrich' a remote notification (e.g. add an image), you need a UNNotificationServiceExtension:
For local notifications, the app adds attachments when creating the
rest of the notification’s content. To add attachments to a remote
notification, use a notification service extension to modify the
notification content before it is delivered. For more information
about implementing a notification service extension, see
UNNotificationServiceExtension
Source: Apple documentation. (emphasis mine)
That extension lives outside of your app and is called before the user gets to see the remote notification. That way you have the chance to load all of your remote resources before the notification is scheduled for delivery. For more info on the lifecycle of extensions and how they communicate with their host app, take a look at the App Extension Programming Guide.
To add the extension in Xcode, go to File > New > Target and select a Notification Service Extension:
This will create new extension target and embed it in the host target:
In the NotificationService.swift file you will find the entry point where you can start customising the notification content.
class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: #escaping (UNNotificationContent) -> Void) {
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
if let bestAttemptContent = bestAttemptContent {
// Modify the notification content here...
bestAttemptContent.title = "\(bestAttemptContent.title) [modified]"
contentHandler(bestAttemptContent)
}
}
override func serviceExtensionTimeWillExpire() {
// Called just before the extension will be terminated by the system.
// Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
contentHandler(bestAttemptContent)
}
}
}
Be sure to take look at the UNNotificationServiceExtension class overview for more details.