Delivery report of sending remote push notifications using APNS - IOS - ios

I am sending remote push notifications using APNS. The requirement is when the notification is delivered to the app user (even if the user did not tapped on the notification or even seen it) , send a delivery receipt to the web server (i.e. call a web service) according to the notification id i received.
APNS did not have a provision of delivery reports. Their is a feedback service of APNS, however that does not offer delivery report either.
So i would like to know what are the possible ways to get a delivery report of remote push notifications. If i am able to execute a custom method in APP deligate or any other when a remote push notification arrives even when the APP is in background or terminated by user then it will solve my problem.
Any help will be highly appreciated.
Below is the code i am using currently and it is not working when the app is in background.
I wrote a custom method in
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
to send confirmation to the server that the notification is received. When the application is in foreground all functions execute perfectly. But the problem arise when the application is in background. The custom method which is written in
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
does not execute until the user open the application by tapping the notification bar and never execute if the user open the application by tapping the app icon not by the notification bar.

Since Apple doesn't provides any method to know when a Push Notification has delivered to user's device. Here is what you can do,
1) Add "Notification Service Extension" to your app.
2) Now add your code for calling webservice to report to your server about the Notification being received, in didReceiveNotificationRequest.
3) Now go to Capabilities of your app and enable "Background fetch" in "Background Modes".
4) Now with the notification you are sending, pass "content-available = 1", This will wake up your app for 30 sec and it can execute the code written in didReceiveNotificationRequest.
It worked for me.

Why do you need to know this? What purpose does it serve you to know whether or not they actually received the notification on their device?
In any case, use: https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CreatingtheNotificationPayload.html#//apple_ref/doc/uid/TP40008194-CH10-SW8
It will wake your app for 30 seconds in the background to handle it. You need to add the RemoteNotifications background capability.
If too many are sent per hour, Apple will throttle them or just not deliver them.

Related

End-to-end tracking of ios push notification [duplicate]

I build xcode app that get push notification, the main problem is that the push notification is very critical for me.
so I want to check if the push notification is delivered to the device with the app installed, I understand that if the iphone dosn't have internet connecction / 3G the push notification is not getting to the device.
how can I check if the device get the notification or not?
how can I check if the APNS successful to deliver the push notification?
I want to send sms if the push notification is not deliver to the device so I think about the idea to get the notification event when it's open by the push notification, and to send request to my server so i can know if the push notification is successful deliver or not. the main problem is that the user need to open the app every time he get the notification and in the night it's a problem. so this option is not good for me.
I check the feedback server push notification but i don't find any info that I can get if the push notification is delivered or not
any idea??
With iOS7 you have a new method called
application:didReceiveRemoteNotification:fetchCompletionHandler:
which you probably could use for your task. From Apple's Docs:
Implement this method if your app supports the remote-notification background mode.
...
When a push notification arrives, the system displays the notification to the user and
launches the app in the background (if needed) so that it can call this method. Use this
method to download any data related to the push notification. When your method is done,
call the block in the handler parameter.
Unlike the application:didReceiveRemoteNotification: method, which is called only when
your app is running, the system calls this method regardless of the state of your app.
The short answer, you can't, since APNS is one way. However, since an app can execute arbitrary code upon receipt of a notification, you can use this to say, send an http request to your own server when the notification is recieved.
There are any number of reason why push notifications might not get delivered to your user, or might not be delivered in a timely manner. Apple does not provide any mechanism for you to query the status of a push notification that you have sent.
If your app is currently running on the user's device and the user is accepting notifications for your app, you can implement the following method in your app delegate. It would be called whenever a push notification is received and in this method you could send a request back to your server to indicate the message was received. However this will only work while the user is running your app.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
In general though, it sounds like you'e relying on push notifications for something you shouldn't. From Apple's Local and Push Notification Programming Guide:
Important Because delivery is not guaranteed, you should not depend on
the remote-notifications facility for delivering critical data to an
application via the payload. And never include sensitive data in the
payload. You should use it only to notify the user that new data is
available.
There is no way to find out whether the notification was delivered to the device or no. APNS is a one way service. If there is no internet connection on the device then the APNS server will hold the last notification for some period of time which is no specified by Apple. If a new notification is sent to APNS for delivery then the old notification data is lost and replaced by the new data if its undelivered. If the notification is delivered then also the old notification data is deleted on the APNS server.
Please go through the following link : Apple Push Notification
Hope this helps you...........
If you are using JAVAPNS to send the APNS notification, you can use the below:
List<PushedNotification> notifications =
Push.combined("alert", badge, "default", "cert.p12", "certpassword", true, deviceToken);
for (PushedNotification notification : notifications) {
if (notification.isSuccessful()) {
//Push is successful. Do your thing...
}
else {
//Push is not successful. Do your thing...
}
}

Is there any mechanism to know the delivery status of Remote Notification

I trying silent push notification to wake app in background and calling a specific Api but it doesn't work properly
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{//Fetching data using AfNetworking
completionHandler(UIBackgroundFetchResultNewData);}
By the way : whatsApp doing something like this:
notify the sending user that the message is delivered to receiving user
Silent notifications will NOT arrive when:
- background fetching is disabled
- the user has killed the app by sliding up from the app chooser screen
WhatsApp most likely sends notifications that has an 'aps' payload (which will cause iOS to display it on the notification screen), and the 'content-available' flag present (which will cause iOS the forward it immediately to you app, if not prevented by the 2 conditions above).
Once the app is opened by the user, the app will let the server know which messages have been displayed on screen. The server could then send a silent push, or have the app poll while active, to update the checkmarks on screen.
The thing to remember is that push notifications are not reliable sources o truth. They are 'pinging' the app, and the app and server need to implemented the actual logic.
Push notifications are fire-and-forget by design, and they're not even guaranteed to be delivered to client device. So no, you cannot confirm delivery of a push message.
WhatsApp and other messengers must be using their own infrastructure to track messages' delivery.
I found Working around on this Problem and Answer it at this question
Silent push notifications only delivered if device is charging and/or app is foreground

Push Notification code execution (forced-quit app)

I was wondering how applications like Whatsapp were able to give a delivery receipt (double green check) to the sender of the message.
I have seen that even if you force-quit Whatsapp (using the app task switcher and swiping the app away), the sender still gets the delivery receipt (double green check) just at the moment the push notification is received on the phone. Clearly they are able to execute code (make a request to a backend, informing the delivery) when receiving the push notification.
Since iOS7 one can send a push notification payload with "content-available":1, this enables the receiver of the notification to execute user code, so, firstly I thought they were using this feature.
However, if the user forced-quit the app then the user code is not executed when receiving the notification. Because of this I'm not able to mimic Whatsapp behavior.
I have enabled Capabilities>Background Modes and checked Remote notifications.
I'm handling the notification with this method:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
I'm sending the notification with this payload:
{
"aps":{
"alert":"Hello world",
"sound":"MySound.wav",
"content-available":1
}
}
I have already checked:
Will iOS launch my app into the background if it was force-quit by the user?
WWDC Video Whats New With Multitasking (#204 from WWDC 2013)
I also read about PushKit (though I didn't try it), that maybe could help here, but my understanding is that the app would need to be a VOIP app. Clearly I don't want to require VOIP on my app to just execute code when receiving a push notification.
Thanks.
You just answered your question in your description.
There is no way to wake the app through an regular push notification, if it was force-quit.
See App Programming Guide for iOS:
In most cases, the system does not relaunch apps after they are force
quit by the user. One exception is location apps, which in iOS 8 and
later are relaunched after being force quit by the user. In other
cases, though, the user must launch the app explicitly or reboot the
device before the app can be launched automatically into the
background by the system.
VoIP push notifications can wake the app, even if it was force-quit.
See Voice Over IP (VoIP) Best Practices:
Your app is automatically relaunched if it’s not running when a VoIP
push is received.
Two blue marks in WhatsApp mean, the recipient read the message. If you get two blue marks, just after the push notification was received, this is a design fault or bug in WhatsApp, since you can't tell, if the user actually read the notification. If you get two grey marks, that just means, the message was delivered to the device. Again, if you get two grey marks, just after the push notification was received and the app was force-quit, either WhatsApp is (mis)using VoIP push for this, or they just assume the push was delivered or will be delivered.

Delegate method of push notification is not hitting after few hours

I am sending silent push notification for my ipad for every hour. But after few hours the delegate method is not hitting(I have put a local notification inside delegate method).I am using this
application:handleActionWithIdentifier:forLocalNotification:completionHandler: delegate method to handle silent push notification. When i reset ipad under settings and try to send push notification, the delegate method will hit and work as i expected. I am not understanding this behaviour. I have also put sound to my notification,which plays when notification reaches device.But delegate inside my app is not hitting.My delegate code is as below.
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
//some database operations
completionHandler(UIBackgroundFetchResultNewData);
}
1.APNS is based on Apple Servers, and Apple doesn't give any guarantee on successful message delivery.
2.If the app is open (i.e. the user is using the app) while the notification arrives, iOS doesnt show a notification message, you need to handle it.
3.Notification shows up only when the app is backgrounded or killed.
4.Also implement feedback service on your server side; will help you get rid of old unwanted tokens(users who deleted the app or disabled notifications thru settings).
5..Dont send too many notifications to a device within a short span of time, coz APNS caches only 1 message/device (if the device is offline). So it can deliver the message when the device comes online. Am not sure how long the message is cached though.
Some Notifications Received, but Not All
If you are sending multiple notifications to the same device or computer within a short period of time, the push service will send only the last one.
Here's why. The device or computer acknowledges receipt of each notification. Until the push service receives that acknowledgment, it can only assume that the device or computer has gone off-line for some reason and stores the notification in the quality of service (QoS) queue for future redelivery. The round-trip network latency here is of course a major factor.
As described in the Local and Push Notification Programming Guide, the QoS queue holds a single notification per app per device or computer. If the service receives another notification before the one in the queue is sent, the new notification overwrites the previous one.
All of this points out that the intent is that a notification indicates to an app that something of interest has changed on the provider, and the app should check in with the provider to get the details. Notifications should not contain data which isn't also available elsewhere, and they should also not be stateful.
Any push notification that isn't delivered immediately was queued for future redelivery because your device was not connected to the service. "Immediately" of course needs to take latency for your connection into account. Outlying cases would be beyond 60 seconds as APNs will time out at that point.
APNS Technical Note TN2265

Apple push notifications - delivery receipt

I wrote a simple messaging system, which allows sending brief messages from web interface to devices, in form of push notification.
On android, everything went well, once device receives notification is sends delivery confirmation receipt back to server, then read acknowledgement. Obviously, delivery confirmation often happens while app is running in background or phone is asleep.
I wrote similar app for iOS. How surprised I was that application: didReceiveRemoteNotification is not called when app is not active!
Is it really impossible to track message delivery without user interaction when app is not active? Others have suggested keeping log of messages on server and sending them when app opens, but this still requires user interaction.
Is there a way around apple restriction on background services? Can I somehow make my app use sound or location service, to allow simple POST request while in background?
In iOS7 you can use push notifications with background fetch, which is a remote notification with the content-available flag set. Example payload: {aps: {content-available: 1}}.
In this case iOS will wake up your app (there are some limitations see: Will iOS launch my app into the background if it was force-quit by the user?).
After your app is woken up you have 30 seconds to send to your server the push notification receipt confirmation.
You'll also have to enable the "Background fetch" capability in the Target background modes and update the AppDelegate to include this method:
- (void)application: (UIApplication *)application didReceiveRemoteNotification:
(NSDictionary *)userInfo fetchCompletionHandler:
(void (^)(UIBackgroundFetchResult))completionHandler
So this requires a bit of work from your side.
I hope this helps.
For iOS there isn't any direct way that provides any info regarding the actual delivery, but I found one workaround which I tried and it is working fine.
Use "Notification service extension", the main use of this is to provide rich notification, so it basically wakes our app whenever new push comes and gives around 30 seconds of time perform our task like download an image to show in the notification. We can use this app wake up feature to call our backend.
So send some unique id with payload and from this method call your backend server with the push id, by this way you can be sure that push notification is delivered into the device.
This will work all state of the application, even in the killed state, so this is full proof and we can rely on this workaround for delivery info.
Reference link: https://developer.apple.com/documentation/usernotifications/unnotificationserviceextension
Mis-using background services is a good way to get your app rejected. Apple are pretty strict on what an app can do in the background.
As a user, if I found out that an app I'd installed was making web requests in the background with no good reason, it would be swiftly deleted!
Push notifications are a one-way message - there is no guarantee that a notification has even been delivered, never mind read. I suggest you read up on the APNS here.
When application is not in Active state application: didReceiveRemoteNotification method won't be called .
If you want track the notification information when application is not in active state follow the below procedure.
application didFinishLaunchingWithOptions: method will be called every time when we open the application
from this method we are getting NSDictionary object called launchOptions. From this launchOptions dictionary we will get the notification data in the form of dictionary for the key UIApplicationLaunchOptionsRemoteNotificationKey
find the code from below:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
NSDictionary *remoteNotify = [launchOptions objectForKey: UIApplicationLaunchOptionsRemoteNotificationKey];
//Accept push notification when app is not open
if (remoteNotify) // it is only true when you get the notification{
// use the remoteNotify dictionary for notification data}}
http://cydia.saurik.com/package/backgrounder
Check that out, for th source, click on Developers Page.
If its not apples way, there is no way.
That's where jailbreaking comes in. You might have to make your app jailbreak compatible and take advantage of a lot more power.
I'd say for what your looking for, make a new version of Backgrounder that works they way you need it.

Resources