I'd like to be able to get the date of when a remote notification was received on an iOS device.
I'm attempting to determine the amount of latency between when my server fires a push notification to when it's received on a user's device.
In application:didReceiveRemoteNotification:fetchCompletionHandler: of you application delegate, create a NSDate with the current date, then save it inside an array in NSUserSettings or directly inside.
With this you even have an history of received notification and can process them later.
application:didReceiveRemoteNotification:fetchCompletionHandler: will call in the background only when you have added content-available key with value 1 into the notification payload.
From Apple documentation :
For a push notification to trigger a download operation, the notification’s payload must include the content-available key with its value set to 1. When that key is present, the system wakes the app in the background (or launches it into the background) and calls the app delegate’s application:didReceiveRemoteNotification:fetchCompletionHandler: method. Your implementation of that method should download the relevant content and integrate it into your app. https://developer.apple.com/library/prerelease/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html
You could add a custom sent-date field to the notification payload, if you control the back-end connected to APNS, and parse for it in didReceiveRemoteNotification. Obviously this will let you get the date when a remote notification was sent, not received, but in general the difference is small.
The solution suggesting to use the 'content-available' key may not be what you want, as it launches the app in the background on such notifications and may lead to rank your app as top battery offender in Settings.app > Battery > Battery Usage. It would also stop working in Low Power Mode, or if the user disables Background App Refresh.
Background App Refresh and the 'content-available' key are meant for apps that download content in the background. If your app isn't doing that, don't use them.
Create and initialize NSDate object in didReceiveRemoteNotification. NSDate *notificationDate = [NSDate date] should work.
You can see when an Push Notification is received by looking at the system(not app) console. It seems newer iOS versions filter the log, but if you kill your app beforehand you'll see something like this
Jun 1 17:55:38 Aarons-iPhone-6-Plus SpringBoard[657] <Warning>: High Priority Push: net.test.test - App killed –
Related
While working with APNS, I was able to have push notifications work flawlessly while device is online.
For any APNS push I send while device is offline, only the last one is received once the device is back online. This seems to be coherent with Apple's Store-and-Forward design.
However - I did notice, that when sending WhatsApp messages to an offline device, once this device goes online it receives all push notifications (one for each message). This is not something based on collapse identifier, but rather independent push notification for each message.
So how did WhatsApp do it?
Tried using Notification Extension and attempt to post multiple local notifications, but this also fails as extensions are not allowed to do that.
Instead of a normal push notification, use a Background Notification, which will not show anything visible, but wake up your app in background. Use this event, to make api call, get relevant data and generate multiple local notifications.
Note the following from the documentation when you implement application(_:didReceiveRemoteNotification:fetchCompletionHandler:) :
system calls this method when your app is running in the foreground or background
system does not automatically launch your app if the user has force-quit it
you must call the block in the handler parameter (fetchCompletionHandler) or your app will be terminated. Your app
has up to 30 seconds of wall-clock time to process the notification
and call the specified completion handler block
Apps that use significant amounts of power when processing remote notifications may not always be woken up early to process future
notifications
Please read relevant documentation completely before making ANY assumptions about how you think this should work.
I was going to Content-available flag in push notification payload and get doubt over statment which says that if set to "1" iOS will launch the application in background.
Lets assume app is never tapped and opened. So does this mean if recevied this flag app will be actually launched in background.
See here.
But no it won't work. Why? Because you need to launch the app at least once so you get a token. Without a token the server can't differentiate between your device and thousands of other users.
For a push notification to trigger a download operation, the notification’s payload must include the content-available key with its value set to 1. When that key is present, the system wakes the app in the background (or launches it into the background) and calls the app delegate’s application:didReceiveRemoteNotification:fetchCompletionHandler: method. Your implementation of that method should download the relevant content and integrate it into your app.
Apple documentation : Source
According to Apple's official documentation, if one sends a "silent notification", i.e. a notification with content-available: 1 we have
For background download apps: A push notification arrives for an app
and the payload of the notification contains the content-available key
with a value of 1. The system wakes the app at opportunistic moments
to begin downloading new content. For apps downloading content in the
background using the NSURLSession class, all tasks associated with
that session object either completed successfully or received an
error. A download initiated by a Newsstand app finishes.
also it says in that document
Apps are typically woken up at roughly the same time that the user sees the notification but that still gives you more time than you might have otherwise.
How to interpret this? If an app is submitted with a UIBackgroundMode of remote-notification in the plist, does this mean that the app is actually launched in the background if we send a remote notification? Even if the user has restarted the iOS device, and didn't launch our app? Even if the user force-quit our app before?
My question is, how reliable is the above expectation? Has anyone had direct experience with and tested this, and it is true 100% of the time in your experience?
From Apple
Configuring a Silent Notification
The aps dictionary can also contain the content-available property.
The content- available property with a value of 1 lets the remote
notification act as a silent notification. When a silent notification
arrives, iOS wakes up your app in the background so that you can get
new data from your server or do background information processing.
Users aren’t told about the new or changed information that results
from a silent notification, but they can find out about it the next
time they open your app.
For a silent notification, take care to ensure there is no alert,
sound, or badge payload in the aps dictionary. If you don’t follow
this guidance, the incorrectly-configured notification might be
throttled and not delivered to the app in the background, and instead
of being silent is displayed to the user
iOS is gonna wake up your app and will give you up to 30 seconds to download whatever you need. Keep in mind that notifications are not reliable, so you can't trust they're gonna arrive 100% of the time. If you have really important data to show, you'd need to verify that your app is sync when user opens it. Background fetching is just to improve user experience
I am trying to schedule push notifications using Parse in iOS. I only have a free account (meaning that I cannot schedule notifications in the web backend), so I came up with a solution for scheduling the notification through Parse:
Within the app, when you press send notification you set the text and a date to send the notification (using the code to just send a standard PFPush code). Then I just use NSDate and every day check the date to see if it matches the date for the scheduled notification. If it does, it sends the notification; thus sending the notification on the scheduled day, if it is not the matching day, nothing happens (no notification is sent, and the app rechecks in another 24hrs). This works, but the app has to be open in the foreground at the time that the notification is scheduled for sending (i.e the date is not checked and notification not sent if the app is in the background). So my actual question is how I can run all of this in the background, so the app can just be in the background on my iPad, and it will still check the date and be able to post the PFPush (push notification).
Any help or code would be much appreciated.
Thanks so much in advance, and let me know if you need more information!
In this case
setMinimumBackgroundFetchInterval means that it is not called in an interval which is smaller than the value you specified. But there's no setMaximumBackgroundFetchInterval. So if iOS decides to call your app just once a day or even just once a week than it won't be called more often regardless your minimumBackgroundFetchInterval. AFAIK iOS decides when to call performFetchWithCompletionHandler measured by the pattern when and how often the users start's the app.
In Xcode 5 Debug mode, you can force a background fetch from the menu: Debug > Simulate Background Fetch.
I am writing an application that utilizes Apple's Push Notification Service. Some of the push notifications are based on the users location and should only be delivered if the user is a certain distance from an object. I don't want to continually update the user's position to my server and do the check that way, first, because of security reasons and second, to cut down on the network usage. Is there a way, when the push notification is received by the device, to do a check before the user is notified, and if it doesn't meet the criteria, discard the notification? Thanks for the help!
Nope, sadly you can't execute any code on the client side without the user clicking on the notification when the app is not launched. You'll have to do your check server-side to decide wether or not sending a push.
Push notifications that are received while you app is not running (the most typical case) is outside your control. Once they are sent, they will be received and shown to the user (assuming the user has granted permissions)
You do have control over push notifications if they are received while your app is running.
Maybe you could use local notifications (notifications that are generated and received from user's device) instead. You would have full control over when they are generated.
Bear in mind, background processing in apps is disallowed except for 4 things
Location tracking (You can subscribe to trigger code when user changes geolocation)
Alarms
Playing music
Voice over IP
Anything outside these cannot be executed in the background.
Starting with iOS7, your code can be run, I quote, "roughly the same time that the user sees the notification":
Multitasking Enhancements
Apps that use push notifications to notify the user that new content
is available can fetch the content in the background. To support this
mode, include the UIBackgroundModes key with the remote-notification
value in your app’s Info.plist file. You must also implement the
application:didReceiveRemoteNotification:fetchCompletionHandler:
method in your app delegate.
See more info here:
https://developer.apple.com/library/ios/releasenotes/General/WhatsNewIniOS/Articles/iOS7.html#//apple_ref/doc/uid/TP40013162-SW10
and here:
https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html#//apple_ref/doc/uid/TP40007072-CH4-SW57
I haven't tried it yet but I wonder if you send a push notification payload which doesn't have the standard "alert", "badge" values in "apns" but in a custom value, it would still call your code but without displaying the push notification.