I am using swift3. I want to show FCM message to tableview in a UIViewController when My app receive FCM message data.I have got my fcm data using bellow code in appDelegate..But I don't know how to get data in UIViewController.
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (_ options: UNNotificationPresentationOptions) -> Void) {
let message : UNNotificationPresentationOptions = .alert
//GlobalVariables.notification_message = getAlert(notification: .alert)
if UIApplication.shared.applicationState == .active { // In iOS 10 if app is in foreground do nothing.
print("active****")
print("\(notification.request.content.userInfo)")
completionHandler([message, .sound])
} else {
print("Not active****")
completionHandler([message, .badge, .sound])
}
}
Please help me
Thanks advance
Set a variable on your AppDelegate, then use it from either:
AppDelegate's didFinishLaunchingWithOptions on window?.rootViewController
Your view controller by calling (UIApplication.shared.delegate as? AppDelegate)?.yourVariable
I recommend setting variable in AppDelegate to nil after using it, to prevent using same notification data twice.
In app delegate change your code like this
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
// FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenType.sandbox)
// FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenType.prod)
}
func applicationWillTerminate(_ application: UIApplication) {
UserDefaults.standard.removeObject(forKey: "check")
UserDefaults.standard.removeObject(forKey: "userid")
UserDefaults.standard.removeObject(forKey: "patient_no")
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
let state: UIApplicationState = UIApplication.shared.applicationState
if state == .active{
UIApplication.shared.applicationIconBadgeNumber = 0
if let notification = userInfo["aps"] as? [AnyHashable: Any],
let alert = notification["alert"] as? String {
print(alert)
message = alert
let localNotification = UILocalNotification()
localNotification.alertBody = alert
localNotification.soundName = UILocalNotificationDefaultSoundName
UIApplication.shared.scheduleLocalNotification(localNotification)
print("Active----")
}
}else if state == .inactive{
if let notification = userInfo["aps"] as? [AnyHashable: Any],let alert = notification["alert"] as? String {
print(alert)
message = alert
let localNotification = UILocalNotification()
localNotification.alertBody = alert
localNotification.soundName = UILocalNotificationDefaultSoundName
UIApplication.shared.scheduleLocalNotification(localNotification)
print("Inactive----")
}
}else if state == .background{
if let notification = userInfo["aps"] as? [AnyHashable: Any],let alert = notification["alert"] as? String,let sound = notification["sound"] as? String{
print(alert)
message = alert
var localNotification = UILocalNotification()
localNotification.alertBody = alert
localNotification.soundName = sound
UIApplication.shared.applicationIconBadgeNumber = number!+1
print(number!+1)
UIApplication.shared.scheduleLocalNotification(localNotification)
print("Background----")
}
}
}
then add this where you want the message back
let delegate = UIApplication.shared.delegate as! AppDelegate
let message = delegate.message
This is a sample only you want to add some condition
Related
I am trying to schedule notifications in my project. I don't get any errors or runtime crashes, however for some reason I don't get any notifications on the simulator when scheduling. I am not sure where exactly I am going wrong, as I have been successful in doing so in a previous project.
Does anyone have any suggestions ?
import UserNotifications
func addNotification(title: String, category: String, UI: String, date: Date) {
// Remove Notification
removeNotifcation(UI: UI)
// Create Notification
// iOS 10 Notification
if #available(iOS 10.0, *) {
let notif = UNMutableNotificationContent()
notif.title = title
notif.subtitle = "Reminder for \(title)"
notif.body = "Your Reminder for \(title) set for \(date)"
notif.sound = UNNotificationSound.default()
notif.categoryIdentifier = UI
let today = Date()
let interval = date.timeIntervalSince(today as Date)
let notifTrigger = UNTimeIntervalNotificationTrigger(timeInterval: interval, repeats: false)
let request = UNNotificationRequest(identifier: title, content: notif, trigger: notifTrigger)
UNUserNotificationCenter.current().add(request, withCompletionHandler: { error in
if error != nil {
print(error as Any)
// completion(Success: false)
} else {
//completion(Sucess: true)
}
})
} else {
let newNotification:UILocalNotification = UILocalNotification()
newNotification.category = category
newNotification.userInfo = [ "UUID" : UI]
newNotification.alertBody = "Your reminder for \(title)"
newNotification.fireDate = date
//notification.repeatInterval = nil
newNotification.soundName = UILocalNotificationDefaultSoundName
UIApplication.shared.scheduleLocalNotification(newNotification)
}
}
func removeNotifcation(UI: String) {
//Remove Notif
//iOS 10 Notification
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: [UI])
} else {
//Remove Notif
let app:UIApplication = UIApplication.shared
for oneEvent in app.scheduledLocalNotifications! {
let notification = oneEvent as UILocalNotification
let userInfoCurrent = notification.userInfo!
let uuid = userInfoCurrent["UUID"] as! String
if uuid == UI {
//Cancelling local notification
app.cancelLocalNotification(notification)
break;
}
}
}
}
This is how I am calling the methods
dataManager.addNotification(title: "String", category: "001", UI: uuid, date: datePicker.date)
Notifications don't appear when app is in foreground only if you implement willPresent delegate method and because of
let today = Date()
this date makes it triggers when you run it , so add a time interval and send app to background and you'll see it , plus make sure you request a permission for it in AppDelegate
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in
print("granted: (\(granted)")
}
return true
}
Also you can have a look to this tutorial
//
Edit : to verify it triggers anyway implement this
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
print("handling notifications with the TestIdentifier Identifier")
completionHandler()
}
and set the delegate to the VC
UNUserNotificationCenter.current().delegate = self
I have integrated Push notification on to my project and for some reason the banner appears on when I'm in the background mood and not when I'm in the foreground. I'm sure I've missed something, my code as bellow. Any help would much appreciate.
import UserNotifications
class AppDelegate: UIResponder, UIApplicationDelegate,UNUserNotificationCenterDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
let center = UNUserNotificationCenter.current()
center.delegate = self //not sure this is appropriate
registerForPushNotifications()
}
func registerForPushNotifications() {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) {
(granted, error) in
guard granted else { return }
self.getNotificationSettings()
}
}
func getNotificationSettings() {
UNUserNotificationCenter.current().getNotificationSettings { (settings) in
print("Notification settings: \(settings)")
guard settings.authorizationStatus == .authorized else { return }
DispatchQueue.main.async(execute: {
UIApplication.shared.registerForRemoteNotifications()
})
}
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let tokenParts = deviceToken.map { data -> String in
return String(format: "%02.2hhx", data)
}
let token = tokenParts.joined()
if let valueInDB = UserDefaults.standard.value(forKey: "Permission_Granted") {
UserDefaults.standard.setValue(token, forKey: "PUSH_TOKEN")
UserDefaults.standard.synchronize()
print("Device Push Token: \(token)")
}
This gets called every time I gets a notification despite if its running on foreground or background. Thus the batch icon gets updated.
func application(_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable : Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void)
{
print("Recived: \(userInfo)")
completionHandler(.newData)
self.onPushRecieved = MP3ViewController().catchPushNotifications
let notification = JSON(userInfo)
print(notification)
let mediaId = (notification["media_id"]).stringValue
print(mediaId)
var badgeCount = 0
var pushAvailable = false
if let pushCount = UserDefaults.standard.value(forKey: "PUSH_COUNT"){
badgeCount = pushCount as! Int
print(badgeCount)
badgeCount = badgeCount + 1
UIApplication.shared.applicationIconBadgeNumber = badgeCount
}
print(badgeCount)
UserDefaults.standard.setValue(badgeCount, forKey: "PUSH_COUNT")
UserDefaults.standard.synchronize()
let storyboard = UIStoryboard(name: "Main", bundle: nil)
print(isOnBackGround)
if isOnBackGround {
if mediaId != nil{
DispatchQueue.main.async {
let mP3ViewController = storyboard.instantiateViewController(withIdentifier:"MP3ViewController") as! MP3ViewController
mP3ViewController.media_ID = mediaId
self.navigationController?.pushViewController(mP3ViewController, animated:true)
self.isOnBackGround = false
}
}
}else{
print("Running on foreground")
}
}
}
You may want to implement the following function, eg:
public func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Swift.Void) {
completionHandler([.badge, .alert, .sound])
}
of this delegate: UNUserNotificationCenterDelegate
Ok so my push notification work like a charm when the app is running in the foreground. But when ever I enter into the background, the app never receives the push notification. Its like the notification falls on deaf ears.
So this is what happening. When the app is first started, I can received notification. When I close and reopen the app I can receive notification. But when the app is closed in the background I cannot receive notification. I print off when the app goes into the background and when the app becomes active so I know that its not closing I think. Because its printing that its going into the background, so it should be running.
So this is what I have for the app deligate class:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
//OTHER THINGS
//Open the Push note page
if launchOptions != nil
{
print(launchOptions)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier(myPage)
self.window?.rootViewController = vc
}
//handel push note if app is closed
//Sends it to the regular handler for push notifcaiton
//didrecivepushnotificaiton
if let remoteNotification = launchOptions?[UIApplicationLaunchOptionsRemoteNotificationKey] as? NSDictionary
{
print("Got A Push Note when I was closed")
self.application(application, didReceiveRemoteNotification: remoteNotification as [NSObject : AnyObject])
}
}
func application( application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken
deviceToken: NSData ) {
print("DEVICE TOKEN = \(deviceToken)")
//convert the device token into a string
let tokenChars = UnsafePointer<CChar>(deviceToken.bytes)
var token = ""
for i in 0..<deviceToken.length {
token += String(format: "%02.2hhx", arguments: [tokenChars[i]])
}
print("token: " + token)
//store the user device token for apns push notification
loginInformation.setObject(token, forKey: "token")
self.loginInformation.synchronize()
}
// [START ack_message_reception]
func application( application: UIApplication,
didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
print("Recived Push Notificaion")
var myMess :String = ""
var url : String = ""
var myTitle : String = ""
if var alertDict = userInfo["aps"] as? Dictionary<String, String> {
print("Alert Dict")
print(alertDict)
url = alertDict["url"]!
myMess = alertDict["alert"]!
myTitle = alertDict["mytitle"]!
//store the url for the push control view
loginInformation.setObject(url, forKey: "URL")
loginInformation.setObject(myMess, forKey: "Message")
loginInformation.setObject(myTitle, forKey: "Title")
self.loginInformation.synchronize()
}else{print("No go")}
application.applicationIconBadgeNumber = 0
//post notification.
NSNotificationCenter.defaultCenter().postNotificationName("PushReceived", object: nil, userInfo: userInfo)
if myTitle == ""
{
myTitle = “New Title“
}
if myMess == ""
{
myMess = “All Hail Gus“
}
let alert = UIAlertController(title: myTitle, message: myMess, preferredStyle: UIAlertControllerStyle.Alert)
//Close Button
alert.addAction(UIAlertAction(title: "次回", style: UIAlertActionStyle.Default, handler: nil))
self.window?.rootViewController?.presentViewController(alert, animated: true, completion: nil)
}
func registrationHandler(registrationToken: String!, error: NSError!) {
}
// [START receive_apns_token_error]
func application( application: UIApplication, didFailToRegisterForRemoteNotificationsWithError
error: NSError ) {
print(error)
}
I think I have all the right setting on this too. But I am not too sure now. The push notifications did work but I made a lot of changes and haven't tested them in a while.
And this is an example of the payload
{"aps":{"alert":"Gus Message.","badge":"1", "url":"https://www.gus.com","mytitle":"Gus Title"}}
To fully implement APNS servie, u have to handle three cases:
inactive
foreground
background
the inactive mode should be handled in didFinishLaunchingWithOptions method
//receive apns when app in inactive mode, remaining message hint display task could be sum up by the code in applicationwillenterforeground
if let options = launchOptions {
if options[UIApplicationLaunchOptionsRemoteNotificationKey] != nil {
let userInfo: NSDictionary = options[UIApplicationLaunchOptionsRemoteNotificationKey] as! NSDictionary
let apsInfo: NSDictionary = userInfo["aps"] as! NSDictionary
//parse notification body message ...
NSNotificationCenter.defaultCenter().postNotificationName(APP_NOTIF_RECEIVE_REMOTE_NOTIF, object: userInfo)
APService.handleRemoteNotification(userInfo as! [NSObject : AnyObject])
//Update badge number
let badgeIndex = apsInfo["badge"] as! Int
UIApplication.sharedApplication().applicationIconBadgeNumber = badgeIndex
}
}
} else if options[UIApplicationLaunchOptionsURLKey] != nil {
if let url = launchOptions?[UIApplicationLaunchOptionsURLKey] as? NSURL {
print(url)
}
}
}
the remaining two cases should be handle in didReceiveRemoteNotification method
//receive apns when app in background mode
let apsInfo: NSDictionary = userInfo["aps"] as! NSDictionary
if UIApplication.sharedApplication().applicationState != UIApplicationState.Active{
//TODO: temporary method, need further update
//judge notification type
if let _ = userInfo["inviterName"] as? String {
//notification for group invite
}else{
//Update badge number
if let badgeInt = apsInfo["badge"] as? Int {
UIApplication.sharedApplication().applicationIconBadgeNumber = badgeInt > 0 ? badgeInt: 1
}else{
UIApplication.sharedApplication().applicationIconBadgeNumber = 1
}
//turn on trigger to enable message hint btn on recorder vc when it appear
NSUserDefaults.standardUserDefaults().setBool(true, forKey: REMOTE_NOTIF_REMAINING)
}
}
//receive apns when app in forground mode
else{
//TODO: temporary method, need further update
//judge notification type
if let _ = userInfo["inviterName"] as? String {
//notification for group invite
NSNotificationCenter.defaultCenter().postNotificationName(APP_NOTIF_RECEIVE_GROUP_NOTIF, object:nil)
}else{
//notificate recorder vc to display message hint directly
NSNotificationCenter.defaultCenter().postNotificationName(APP_NOTIF_RECEIVE_REMOTE_NOTIF, object: userInfo)
}
}
APService.handleRemoteNotification(userInfo)
completionHandler(UIBackgroundFetchResult.NewData)
I am creating local notification when app receiving Push notification. these local notification generating when app in foreground and when i am creating local notification at the same time didReceiveLocalNotification method is calling and getting difficulties to manage local notification and clicking/tap on location same event calling twice.I need to avoids duplicate Local notifications also.
Please help me for solve this issue.
//MARK: - Delegate Method For APNS Notification
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
print("Notification Message \(userInfo)")
let aps = userInfo["aps"] as! [String: AnyObject]
// 1
if userInfo["postData"] != nil {
// Refresh Promotions
print("Got it...")
// Clear Previous Value Data
postData.removeAll()
//Adding New Post Data here
if (userInfo["postData"] != nil){
self.postData = userInfo["postData"]! as! [String : AnyObject]
print(self.postData)
}
//Condition here for Notification
if appInForeground == false {
//Goto Promo List
//Set Boolean for View
notiDetails = true
//Navigation
gotoPromoListView()
}else{
let systemSoundID: SystemSoundID = 1016
// to play sound
AudioServicesPlaySystemSound (systemSoundID)
AudioServicesPlayAlertSound(SystemSoundID(kSystemSoundID_Vibrate))
let notification = UILocalNotification()
notification.alertBody = (aps["alert"] as? String)!
notification.soundName = UILocalNotificationDefaultSoundName
notification.userInfo = userInfo["postData"]! as! [String : AnyObject]
UIApplication.sharedApplication().scheduleLocalNotification(notification)
}
How to manage this method for local notification
func application(application: UIApplication, didReceiveLocalNotification notification: UILocalNotification) {
// Do something serious in a real app.
print("Received Local Notification:")
print(notification.userInfo)
self.postData = notification.userInfo as! [String : AnyObject]
didTapNotification()
}
Could you please show your code, where you register your remote notifications?
If you want to show alert and badge, when receive push notifications, you can make like this:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let notificationTypes: UIUserNotificationType = [.Alert, .Badge, .Sound]
let notificationSettings: UIUserNotificationSettings = UIUserNotificationSettings(forTypes: notificationTypes, categories: nil)
UIApplication.sharedApplication().registerUserNotificationSettings(notificationSettings)
return true
}
func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {
UIApplication.sharedApplication().registerForRemoteNotifications()
}
After that you can add custom actions to method:
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject :
}
If you need local notifications, you should set fire property, when you schedule notification:
let localNotification = UILocalNotification()
localNotification.fireDate = NSDate()
localNotification.timeZone = NSTimeZone.defaultTimeZone()
localNotification.alertBody = text
localNotification.soundName = UILocalNotificationDefaultSoundName
UIApplication.sharedApplication().scheduleLocalNotification(localNotification)
I'm trying to create a subscription using CloudKit to fires every time a record is created. I have successfully created the subscription, I can see it in dashboard, but I've noticed that the print I have in didReceiveRemoteNotification was never printed!
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
print("oioioioioi")
let viewController: CurrentEventController = self.window?.rootViewController as! CurrentEventController
if let userInfo = userInfo as? [String: NSObject] {
let notification: CKNotification = CKNotification(fromRemoteNotificationDictionary: userInfo)
if (notification.notificationType == CKNotificationType.Query) {
let queryNotification = notification as! CKQueryNotification
let recordID = queryNotification.recordID
viewController.fetchRecord(recordID!)
}
}
}
Thanks for any help!