func application(_ application: UIApplication, didReceiveRemoteNotification notification: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
/*
let aps = userInfo["aps"] as! [String: AnyObject]
if let count = aps["badge"] as? Int {
application.applicationIconBadgeNumber = 2
}
*/
let custom = notification["custom"] as! [String: AnyObject]
if let home = custom["a"]!["home"] as? String, home == "1" {
incrementBadgeNumberBy(badgeNumberIncrement: 1)
}
}
In General Application Badge is set from push notification payload.
Payload example:
{
“aps” : {
“badge” : 9
},
}
or
You also can set badge using
UIApplication.shared.applicationIconBadgeNumber = 3
Related
I need some help in getting the inner push data.
in my app delegate file i have the following:
// Push notification received
func application(_ application: UIApplication, didReceiveRemoteNotification data: [AnyHashable : Any]) {
// Print notification payload data
print("Push notification received: \(data)")
}
which results in the following:
Push notification received: [AnyHashable("aps"): {
Link = "http://www.website.com.dll?i.user8=App&id=374941&mobileOnly=true";
alert = "New survey";
}]
How would i go about in getting the value go LINK from data
thanks
You can get push data as like below.
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
let dictPayload = userInfo as NSDictionary
if let data = dictPayload.value(forKey: "aps") as? NSDictionary {
let link = data.value(forKey: "Link") as? String
print(link)
}
print("Push notification received: \(data)")
}
I am downloading my events in background mode, for that I will receive a push and a silent Notification. As I have to download data when my app is in background mode, so I am using silent notification for downloading data through a web service and before that I am updating applicationIconBadgeNumber based on an increment value. When I am updating applicationIconBadgeNumber with my auto increased value all my push notifications are getting cleared in notification center. If I am not setting any applicationIconBadgeNumber they are remaining same. As I have posted my code below, please do let me know if I am missing out something.
var autoIncrementForNotification:Int = 0
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
UIApplication.shared.setMinimumBackgroundFetchInterval(60)
if #available(iOS 10, *) {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) {(accepted, error) in
if !accepted {
print("Notification access denied.")
} else {
application.registerForRemoteNotifications()
}
}
} else {
application.registerForRemoteNotifications(matching: [.badge, .sound, .alert])
}
return true
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let deviceTokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
UserDefaults.standard.removeObject(forKey: "Device_Token")
UserDefaults.standard.setValue(deviceTokenString, forKey: "Device_Token")
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Swift.Void){
let aps = userInfo["aps"] as! [String: AnyObject]
if ((aps["content-available"] as? NSString)?.integerValue == 1)
{
let type = (aps["type"] as? NSString)
if(type == Constants.action_type_Events)
{
if (application.applicationState == .inactive || application.applicationState == .background)
{
autoIncrementForNotification += 1
application.applicationIconBadgeNumber = autoIncrementForNotification
// Firing my Web service
completionHandler(UIBackgroundFetchResult.newData)
}
}
}
}
func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void){
completionHandler(UIBackgroundFetchResult.newData)
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("i am not available in simulator \(error)")
}
func applicationDidBecomeActive(_ application: UIApplication) {
application.applicationIconBadgeNumber = 0
autoIncrementForNotification = 0
}
Please try the following :
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void){
var contentAvailable: Int
let aps = userInfo["aps"] as! [String: AnyObject]
if let content = aps["content-available"] as? String {
contentAvailable = Int(content)!
} else {
contentAvailable = aps["content-available"] as! Int
}
if (contentAvailable == 1)
{
let type = (aps["type"] as? NSString)
if(type == Constants.action_type_Events)
{
if (application.applicationState == .inactive || application.applicationState == .background)
{
autoIncrementForNotification += 1
application.applicationIconBadgeNumber = autoIncrementForNotification
// Firing my Web service
completionHandler(UIBackgroundFetchResult.newData)
}
}
}
}
Reason :
If your Payload file is like this {"aps":{"content-available":1}} below condition is not satisfying, so everytime applicationIconBadgeNumber is becoming 0
if ((aps["content-available"] as? NSString)?.integerValue == 1)
If your Payload file is like this {"aps":{"content-available":"1"}} then your code will work fine.
Running on xcode8 with swift3
Below is my code from AppDelegate.swift
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
print("==== didReceiveRemoteNotification ====")
print(userInfo)
}
When I get a notification and click on it, my debug area will how like below
==== didReceiveRemoteNotification ====
[AnyHashable("type"): order, AnyHashable("aps"): {
alert = "[TestMessage]";
badge = "<null>";
category = alert;
sound = default;
}, AnyHashable("url"): http://www.google.com]
My question is how can I use userInfo to get data from AnyHashable("url") which is "www.google.com" ?
I try
print(userInfo[AnyHashable("url")])
but output in debug area is
Optional(http://www.google.com)
Try print(userInfo[AnyHashable("url")] as? String ?? "") Or you can cast it as URL
if let url = userInfo["url"] as? String {
//do whatever you need with the url
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
if let aps = userInfo["aps"] as? NSDictionary {
print(aps)
let alert = (aps.object(forKey: "alert") as? String)!
}
let url = userInfo?["url"] as? String {
print(url)
}
}
I tried to receive my custom notification from my web through parse website.
Code didReceiveRemoteNotification :
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
PFPush.handlePush(userInfo)
if application.applicationState == UIApplicationState.Inactive {
PFAnalytics.trackAppOpenedWithRemoteNotificationPayload(userInfo)}
Here is the JSON i received from parse website :
[aps: {
alert = "test adirax";
sound = default; }]
It works well for me and the notification shows up. However when i tried to push data from my website, the notification can't shows/ pop up.
Here is my JSON looks like :
{"aps": {"alerts" : "test",
"links": "",
"sounds": "default"}}
I tried to print(userInfo) and the result is i get all the data like above, but there is no notif.
I guess I'm missing some code to convert the data ?
INFORMATION
For the specific information, i tried receive notification from parse.com through subscribe "channels". so it's not a local notification or else.
ADD Code Added (according to my JSON type)
if let launchOptions = launchOptions {
let userInfo = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey] as? [NSObject: AnyObject]
let aps = userInfo!["aps"] as? [NSObject: AnyObject]
let alert1 = aps!["alerts"] as? String
let link1 = aps!["links"] as? String
}
And this :
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
PFPush.handlePush(userInfo)
if application.applicationState == UIApplicationState.Inactive {
PFAnalytics.trackAppOpenedWithRemoteNotificationPayload(userInfo)
}
let aps = userInfo["aps"] as? [NSObject: AnyObject]
let alert1 = aps!["alerts"] as? String
let link1 = aps!["links"] as? String
print(userInfo)
print("success")
}
When i debugged one by one, its success i collect all the data, however i still missing the notification showed up ?
SOLVED PART 1
So far i managed to get the data and push the notification out, but it's only when i open the application. Code :
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
PFPush.handlePush(userInfo)
if application.applicationState == UIApplicationState.Inactive {
PFAnalytics.trackAppOpenedWithRemoteNotificationPayload(userInfo)
}
let notifiAlert = UIAlertView()
let aps = userInfo["aps"] as? [NSObject: AnyObject]
let alert1 = aps!["alerts"] as? String
let link1 = aps!["links"] as? String
notifiAlert.title = alert1!
notifiAlert.message = link1
notifiAlert.addButtonWithTitle("OK")
notifiAlert.show()
print(userInfo)
print("success")
}
I use a local notification trick, but how to pop up the notification when i'm not using the app ?
You have to add custom informations like this:
{"aps": {"alerts" : "test",
"sound": "default"},
"name": "Steven",
"age": "32"
}
And parse it like this:
let aps = userInfo["aps"] as? [NSObject: AnyObject]
let msg = aps!["alert"] as? String
let name = userInfo["name"] as? String
print(name)
EDIT:
You have to check push notification on two functions of UIApplicationDelegate
First.
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// check for push message
if let launchOptions = launchOptions {
let userInfo = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey] as? [NSObject: AnyObject]
let aps = userInfo["aps"] as? [NSObject: AnyObject]
let msg = aps!["alert"] as? String
let name = userInfo["name"] as? String
print(name)
}
}
Second.
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
let aps = userInfo["aps"] as? [NSObject: AnyObject]
let msg = aps!["alert"] as? String
let name = userInfo["name"] as? String
print(name)
}
You should add your custom data to the top-level of your payload, not to the aps object.
Like this, for instance:
{
"aps": {
"alerts" : "test",
"sounds": "default"
},
"links": "",
}
This is my ReceiveRemoteNotification code.
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
PFPush.handlePush(userInfo)
if application.applicationState == UIApplicationState.Inactive {
PFAnalytics.trackAppOpenedWithRemoteNotificationPayload(userInfo)
}
let notifiAlert = UIAlertView()
let aps = userInfo["aps"] as? [NSObject: AnyObject]
let alert1 = aps!["alerts"] as? String
let link1 = aps!["links"] as? String
notifiAlert.title = alert1!
notifiAlert.message = link1
notifiAlert.addButtonWithTitle("OK")
notifiAlert.show()
print(userInfo)
print("success")
}
i tried to receive JSON data from my web, my JSON looks like :
{"aps":{"alerts":"3","links":"","sounds":"default"}}
I did receive the Json data and turn the data to the view. with this code :
let aps = userInfo["aps"] as? [NSObject: AnyObject]
let alert1 = aps!["alerts"] as? String
let link1 = aps!["links"] as? String
notifiAlert.title = alert1!
notifiAlert.message = link1
notifiAlert.addButtonWithTitle("OK")
notifiAlert.show()
print(userInfo)
print("success")
}
However i only receive when i was using the application, but if i'm not using, i can't receive the notification. but my phone was vibrate or make sound, but no message.
Am i missing something right here ? thanks !
Added Here is my full code http://pastebin.com/mkFiq6Cs
EDIT
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
if application.applicationState == UIApplicationState.Inactive {
PFAnalytics.trackAppOpenedWithRemoteNotificationPayload(userInfo)
}
let aps = userInfo["aps"] as? [NSObject: AnyObject]
let alert1 = aps!["alerts"] as? String
let link1 = aps!["links"] as? String
notifiAlert.title = alert1!
notifiAlert.message = link1
notifiAlert.addButtonWithTitle("OK")
notifiAlert.show()
print(userInfo)
print("success")
}
So i have to add this code :
func application(application: UIApplication, didReceiveLocalNotification notification: UILocalNotification) {
if let userInfo = notification.userInfo {
let aps = userInfo["aps"] as? [NSObject: AnyObject]
let alert2 = aps!["alerts"] as? String
let link2 = aps!["links"] as? String
print("didReceiveLocalNotification: \(aps)")
print("didReceiveLocalNotification: \(alert2)")
print("didReceiveLocalNotification: \(link2)")
}
}
And this at didFinishLaunchingOption :
if let options = launchOptions {
if let notification = options[UIApplicationLaunchOptionsLocalNotificationKey] as? UILocalNotification {
if let userInfo = notification.userInfo {
let customField1 = userInfo["CustomField1"] as! String
// do something neat here
}
}
}
SOLVED
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
PFPush.handlePush(userInfo)
if application.applicationState == UIApplicationState.Inactive {
PFAnalytics.trackAppOpenedWithRemoteNotificationPayload(userInfo)
}
let notifiAlert = UIAlertView()
if let aps = userInfo["aps"] as? [NSObject: AnyObject],
let alert1 = aps["alert"] as? String,
let content1 = aps["content-available"] as? String,
let link1 = userInfo["links"] as? String {
notifiAlert.title = alert1
notifiAlert.message = link1
notifiAlert.addButtonWithTitle("OK")
notifiAlert.show()
}
print(userInfo)
print("success")
completionHandler(UIBackgroundFetchResult.NewData)
}
This works perfectly. ! Thanks to #tskulbru
This is because application(_:didReceiveRemoteNotification:) is only called when the application is active. It cant handle app-inactive/background remote notifications.
If the app is not running when a remote notification arrives, the method launches the app and provides the appropriate information in the launch options dictionary. The app does not call this method to handle that remote notification. Instead, your implementation of the application:willFinishLaunchingWithOptions: or application:didFinishLaunchingWithOptions: method needs to get the remote notification payload data and respond appropriately.
Source: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplicationDelegate_Protocol/index.html?hl=ar#//apple_ref/occ/intfm/UIApplicationDelegate/application:didReceiveRemoteNotification:
As said above, application:didReceiveRemoteNotification needs to have additional implementation if it should be able to handle background notifications.
If you instead want just one method to handle all the goodies for you, and don't have a bunch of different methods to implement basically the same thing, Apple has provided a method called application:didReceiveRemoteNotification:fetchCompletionHandler: to handle all this for you.
You need to implement the application:didReceiveRemoteNotification:fetchCompletionHandler: method instead of this one to handle background notifications. This handles background tasks, and you can then call the completionHandler with the appropiate enum when you are finished (.NoData / .NewData / .Failed).
If you want to have a local notification presented when you receive a remote notification while the application is active you will need to create that in the aforementioned method. And if you want to display an alertview if the application is active, you also need to handle the two scenarios in that method. My recommendation is to switch to application:didReceiveRemoteNotification:fetchCompletionHandler: instead and implement everything there.
So in your case, I would do something like this:
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
PFPush.handlePush(userInfo)
if application.applicationState == UIApplicationState.Inactive {
PFAnalytics.trackAppOpenedWithRemoteNotificationPayload(userInfo)
} else {
let notifiAlert = UIAlertView()
if let aps = userInfo["aps"] as? [NSObject: AnyObject],
let alert1 = aps["alerts"] as? String,
let link1 = aps["links"] as? String {
notifiAlert.title = alert1
notifiAlert.message = link1
notifiAlert.addButtonWithTitle("OK")
notifiAlert.show()
}
print(userInfo)
print("success")
}
completionHandler(UIBackgroundFetchResult.NewData)
}
I've not tested the code but it should be something like that without too many changes. I havent used Parse so I don't know exactly what PFPush.handlePush(userInfo) does, you need to check the documentation for that.
Looks like your apns payload is wrong too. See https://developer.apple.com/library/mac/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/TheNotificationPayload.html#//apple_ref/doc/uid/TP40008194-CH107-SW1
In your case:
{"aps":{"alert":"alert content","sound":"default", "content-available": 1}, "links":""}
You had plural form instead of single form. Look at the url I gave for the allowed keys. The links key doesn't exist in aps dictionary, which mean its a custom key and needs to be placed outside the dictionary.
Note that this is the standard push notification way and might not be correct when using Parse.