I have found similar questions on Stack Overflow, but none of them have cleared the point.
I am using Firebase Cloud Messaging for sending push notifications in my app. I am storing the messages received in a local database. When my app is active or in the background, my app is able to receive the notifications (delegate methods called properly) but if the app is being forced quit or not in the memory then also the device is receiving the notifications and sat in notification center but the none of the delegate methods called when the app is being launched by an icon. If a user clicks on Message in the notification center, then the app gets launched, but only the message clicked on is being received and not all of them (in the case of multiple notices have been received).
According to Apple - 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.
But even if the user launched the app still not receive the notifications which were received and sat in the notification center.
Here are the points followed by the app:
My app has no VoIP functionality.
Content-available has been set to 1.
Has enabled to receive background remote notifications.
All notifications sent has been received and displayed in the notification center.
{
aps = {
alert = {
body = "Push Notification Test Message";
title = Push Notification;
};
badge = 1;
"content-available" = 1;
sound = default;
};
"gcm.message_id" = "0:1499340350307980%361a2e5b361a2e5b";
m = "Push Notification Test Message";
tag = m;
}
If the app is being forced quit or not in memory then your app will not receive silent notifications(i.e. Content-available set to 1).
Only push notifications are received in above conditions.
If user clicks on Message in notification center, then app gets launched and only that clicked the message will be received in delegate methods.You cannot access all the messages in the notification tray.
There is no way to get push notifications for the application if app is not running. This is restriction . You are only can get and clear local notifications. So the another way of resolving your problem is saving your notification on the backend when you send it. Then after launching app , you can get notifications list from the server , and match it with id . You can send any parameters that you want in notification playload.
Your app should not rely on the delivery of push notifications. Delivery of push notifications is not guaranteed, as you have found.
Even if your app isn't terminated you may not receive all notifications; For example if the device is in airplane mode and multiple notifications are sent, only the last one is delivered when the device comes back online.
Your app should check with the server for new messages when it is launched or when a notification is received in order to "catch up".
You can also consider including a message payload in your silent notifications. This will be displayed to the user if your app is terminated to prompt them to open your app.
You need to handle method for push notification when the application is open from a tap on any notification. As soon as you tap on notification application will awake and lunch it.
In didFinishLaunchingWithOptions, you need to put below condition:
if (launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]) {
NSMutableDictionary *dic = [[NSMutableDictionary alloc] initWithDictionary:[launchOptions valueForKey:UIApplicationLaunchOptionsRemoteNotificationKey]];
}
It also called below method when notification is tapped:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))handler
{
}
Related
I have implement silent push notification.So "didReceiveRemoteNotification" method called when application is inactive state in ios 9.
There are some case when application is inactive state.
1.When user tab on particular notification.
2.When call or message receive.
3.When notification center and control center open.
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
if(application.applicationState == UIApplicationStateInactive) //Inactive state
{
[self RedirectScreenBasedOnNotification:self.userInfoDic];//Screen Redirection code
}
}
So how can i handle silent notification when app is inactive state?
I have face problem is when notification center open at that time if any notification come then redirection will do,but i want to stop that.
Notification payload:-
aps = {
alert = "Test Dev 5 startd following you ";
"content-available" = 1;
"link_url" = "https://raywenderlich.com";
message = {
friend = {
email = "abc#gmail.com";
name = "Test Dev 5";
photo = "";
"user_id" = 27;
};
id = 3;
"is_business_sent" = 0;
message = "Test Dev 5 startd following you ";
};
sound = default;
}
Thanks in advance
Silent push notifications do not trigger user interactions. When a silent notification payload includes keys for user interaction things go wrong - iOS can't reason about wether the intent is to present something to the user, or to keep the notification silent and handled without user interaction. Sometimes the silent notification may work, other times it may be presented like a normal notification with user interaction. It can be one or the other, not both.
If the silent push key content-available is present in the aps payload the keys alert, sound, or badge should not be.
You can use my Push Notification Payload Validation Tool to check the content of your notification. The payload you posted in your question has several problems - the aps key should only contain Apple keys defined in Generating Push Notifications. All of your custom keys and values should be outside the aps object.
application:didReceiveRemoteNotification:fetchCompletionHandler: will only be called for silent push notifications. If the notification payload contains both content-available and one or more of alert, sound, or badge iOS will not know which method to call and you may see inconsistent behavior.
If you are just trying to show a non-silent notification you do not need to implement application:didReceiveRemoteNotification:fetchCompletionHandler:. Instead implement application:didReceiveRemoteNotification: for iOS 9 and userNotificationCenter:willPresentNotification:withCompletionHandler: for iOS 10 and later.
As far as silent notifications and the inactive application state, there is nothing special to be done here. Silent notifications are intended to 'hint' to the application that it should refresh content. When a silent notification is received the application is required to process the content update within 30 seconds and then call the fetch completion handler. When iOS executes the fetch completion handler it take a new restoration snapshot of the updated UI. This happens even when the application is inactive.
You can add your code in this If condition.
if (UIApplication.sharedApplication.applicationState != UIApplicationStateInactive) {
//Write your code her, this will get executed when your app is not in Inactive state.
}
I have a problem. When my App is Terminated by the user, push notifications are not detected by the application. The push notification is sent with content_available = true.
What should I do?
This is default system behaviour. If you Application is terminated by the user (from the App switcher), Silent Push Notifications (content_available = true) will not wake the Application, i.e. Application:didreceiveremotenotification will not be called.
If you want the user to be notified, do not send a Silent Push Notification. Send a normal push notification which will show up in the user's notification tray.
That is the way how it works on iOS.
If you app is not running at all, your app receive no push notifications at all. Only if the user swipe over one of your push notifications on the lock screen or the notification center your app will be started and you will be notified that your app was started because of the push message.
If you app is in the background, you actually can handle push notifications by enabling "run in background" support.
I'm talking iOS9 and earlier here. Not sure if the behaviour has been changed in iOS10. But if you are coming from Android then you have to accept that push notification handling works completely different on iOS than on Android.
Sending the notification with the content_available as disabled. content_available = 0
The content_available field is used for sending silent push notifications to process in the background and will not display as a notification.
See documentation : https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/TheNotificationPayload.html#//apple_ref/doc/uid/TP40008194-CH107-SW6
Hope this helps,
DT
Make sure that in your push notification payload you are adding priority:"high". It will ensure that your app will receive a Push Notification in background or closed mode.
{
"to" : "/topics/{userId}"
"content_available":true,
"priority":"high"
"notification" : {
"title": "",
"body":""
},
"data" : {
//custom key value pairs
}
}
I have tested the following scenario many times on whats app / FB messenger:
1- Terminate the app by swiping.
2- Go to app settings and turn off both notifications and app refresh.
3- send message from other device.
In each time you will get (vv) which means received by other recipient. i have checked and it's delivered in background.
So how whatsapp is handling this?
Thanks in advance.
WhatsApp App has VoIP functionality and it uses the VoIP facility to push silent notifications and launch app in background even if "Background App Refresh" and "Push Notification" disabled.
You should implement:
- (void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
and then send info to your server when user received notification.
When a push notification message is received didReceiveRemoteNotification can be used to inform that the message has received.
So does disabling push notification from settings stops the delivering message indicator?
No, as WhatsApp is using the silent push notification to wake up the App.
However, silent push notification only works when the App in the foreground or if the App has the VOIP capability.
Which is present in the WhatsApp.
So when you disable the push notification from the settings, the silent push notification wakes up the App and use didReceiveRemoteNotification to inform of message delivery.
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.
I know this is covered in a lot of places, but I cannot figure this out. I use Urban Airship for push notifications. Everything seems to be fine except that when my app is in the background - didReceiveRemoteNotification is not getting called. It works when in the foreground - I am able to properly process messages. And I am able to get to messages from launch options if message is tapped from notifications center. But when in the background, a message it send - iOS displays the alert - didReceiveRemoteNotification is not called. When I tap on my Application icon (not from within notification center) the app comes to the foreground and I have no idea the notification is present. Any ideas?
application:didReceiveRemoteNotification: will call in the background only when you have added content-available key with value 1 into the notification payload.
In case of the Urban Airship, you can send Test Push under the Setting tab.
Sample Payload for Push Notifications:
{
"aps": {
"alert": "aaaa",
"badge": "+1",
"content-available": "1"
},
"device_tokens": [
"86BA71E361B849E8312A7B943BA6B26A74AB436381CF3FEE3CD9EB436A12A292"
]
}
Apple has clearly mentioned in his 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/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html
From the APNS programming guide :
Let’s review the possible scenarios when the operating delivers a
local notification or a remote notification for an application.
The notification is delivered when the application isn’t running in the
foreground. In this case, the system presents the notification,
displaying an alert, badging an icon, perhaps playing a sound.
As a result of the presented notification, the user taps the action button
of the alert or taps (or clicks) the application icon. If the action
button is tapped (on a device running iOS), the system launches the
application and the application calls its delegate’s
application:didFinishLaunchingWithOptions: method (if implemented); it
passes in the notification payload (for remote notifications) or the
local-notification object (for local notifications).
If the application icon is tapped on a device running iOS, the application
calls the same method, but furnishes no information about the
notification.
I believe the last sentence describes your case, and explains why your application gets no information about the notification.
didReceiveRemoteNotification is calling ONLY if app in foreground or if app is just launched or is bought from background to foreground
link in Apple and some question
Method didFinishLaunchingWithOptions:(NSDictionary *)launchOptions parameter launchOptions one of the dictionary keys are UIApplicationLaunchOptionsRemoteNotificationKey which holds the pressed push notification info.
You can push received info after tour main root controller is initialised. I save it to some property and then push it after view is initialised.
if (launchOptions) {
if ([launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]) {
self.notificationToMakeAction = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
}
}