Apple push notifications - delivery receipt - ios

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.

Related

Delivery report of sending remote push notifications using APNS - 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.

iOS Background Task/Push Notification

I am building an app that needs to speak data while the app is in the background (or screen is off). The speaking part is done via AVSpeechSynthesizer.
My Android app launches a service that listens for the data and whenever it needs to say something, I say it and its done. Now iOS doesn't allow these kind background tasks from what I read. The closet thing is called 'Executing Finite-Length Tasks' which looks like has a time limit of 10 mins max. So this will not work for me. Instead it looks like I need to use Push Notifications.
Looking at the documentation for Push Notifications, if I understand it correctly, if my app is in the Foreground, then my app receives the Push Notification instantly. While if my app is in the Background, a notification is set (notification center), and once the user hits the notification, my app launches with the payload.
The question here is, is there anyway to make a push notification wake my app immediately so I can speak some info?
Or what are some of the other alternative approaches that should be used in this case?
My other idea would be to implement some sort of mp3 stream per user, that would stream audio which I could play in the background. But this seems excessive for what I am trying to accomplish?
I'm not sure if you'll be able to invoke speech synthesis from the background, but you can have you app notified when the push arrives. The trick is to implement the
- (void) application: (RMApp *) application didReceiveRemoteNotification: (NSDictionary *) userInfo fetchCompletionHandler: (void (^)(UIBackgroundFetchResult result)) completionHandler
UIApplicationDelegate method (note the completionHandler parameter).
You must also set the Remote Notifications Background Mode capability.
And you must set content-available in your push notification payload.
A decent writeup on these steps found here:
http://samwize.com/2015/08/07/how-to-handle-remote-notification-with-background-mode-enabled/

Trigger background sync using notification when app not runnning

I already implemented this:
enable remote notifications in background modes
silent notification {"aps": {"content-available": 1}}
In Apple docs on Push Notification, they are saying:
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.
#
(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
After receive silent notification. In this method, I am downloading some data from the server then data synchronization.
EXPECTED:
The goal is when user open/using the app, it should reflect the latest position for the user.
ACTUAL:
Receive silent notification, download data from server, then data synchronization are works fine when app is running in foreground and background.
But can't wakes up the app in background and to do that when my app is not in running state (app is not launched or killed from app switcher).
QUESTION:
I silent notification doesn't work when app not running? (can't wake up app in background)
Is there missing code in my code which need implemented?
If this way doesn't work when app not running. Is there any way to keep my app local data always same/synced with the database server (when I'm using or not the app)? how other app do it?
Silent notifications are able to bring your app into the background to do any tasks that you may require, as per the Apple documentation:
the system wakes the app in the background (or launches it into the background)
The method you are using, userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:,
is called to let your app know which action was selected by the user for a given notification.
The correct method you should be implementing (even in iOS10) is:
application:didReceiveRemoteNotification:fetchCompletionHandler:. This tells the app that a remote notification arrived that indicates there is data to be fetched.
The way you are doing it is the correct (and probably most popular way) of syncing data between a server and application instance when the user is not actively engaging with the app. Your issue seems to be that you are using the wrong app delegate instance method for your callback.
Update 1:
As per your updated question, I have updated my answer.
That the notifications are not being delivered to your app after it has been terminated by the user is by design. According to the documentation:
The system does not automatically launch your app if the user has force-quit it. In that situation, the user must relaunch your app or restart the device before the system attempts to launch your app automatically again.
To combat this, you can look into Apple PushKit. Originally intended for VoIP apps, it would also work for your application. However unlike regular silent notifications, these do wake up your app even if it has been terminated by the user.
However, keep in mind that once a user terminates an application he expects to have terminated it for good (or until he manually restarts it). To override this would be poor design. Maybe it is fine with the user if the app spends some time downloading the latest data upon launch if the user had terminated the app previously? Depending on the exact reason why you need your app to have the latest information before launch, maybe you don't need to account for this scenario.

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

Does iOS cache remote notifications for apps that are running in background?

Official document from apple developer network mentions that the payload of a push notification is provided to an application when it’s running in foreground, or when it’s activated because of a push notification. I cannot find the statement about what happens when the app is running in background.
I did a test with an instant message application, and found something that I do not understand. Procedure of the test is:
Enable push notification for the app
Switch the app to background
Send two IMs to the client. Two push notification arrives at the client and the badge on the app's icon becomes 2
Shut down cellular network to prevent the app from communicating with its server
Click the app icon to switch it to foreground
After these steps, I can see the 2 messages in the chat window. Because the app is not able to retrieve the messages directly from server, the only explanation is that the push notifications are processed by the app when it’s in background, or they are cached somewhere and can be accessed by the app when it's switched to foreground. But does iOS really allows an app to execute codes when it’s in background, or cache notifications for apps?
The application caches the notifications for 2-5 minutes(i don't know exact) time..
If you receive a notification and you open the app in 2-5 minutes
then in your app delegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
}
You will have the notification object then .. you can get it using launchOPtions object for key UIApplicationLaunchOptionsRemoteNotificationKey
If you don't open it within 2-5 minutes.. there will be no notification object,
This is based on my experience..cant totally support this answer

Resources