Push-and-silent remote notification: Cancel alert when app running in background - ios

I want to send a push-and-silent remote notification...meaning... I would
like to update data on the device BEFORE (and not at the same time) an alert message is displayed
to the user.
More Details
1 If the app is not running, I want to show the alert, which is why I added the alert key in the json.
2 If app is running in the background, I want to cancel the alert, and handle the notification silently: by first downloading content, and when ready trigger a local notification.
3 If app is foreground active state, alert is not shown, which is great, and I can handle the logic silently.
I have this
{
"aps" : {
"content-available" : 1,
"alert" : "This is my new notification",
}
}
But it's not working because
When the app is running in the background, the alert is not canceled, and is displayed at the same time as being handled silently.
So
Is there a way to cancel the alert if app is running in the background?

You need to remove alert from payload. Pass only badge and content-available property.
Enable Remote notification under your Application capabilities area. It should be under Background more section.

Related

Recive background notifcation iOS Swift 5 (Without body and title)

I am trying to receive a notification in the background to process information in my App when it is in Foreground, Background or Closed. I don't want to receive the Alert.
I have tried to do it without placing the Title and Body at the time of shipment, only Custom Data.
How could I receive this information without using an alert, regardless of the status of the App?
A silent push notification or some might call it background notification is a notification that does not trigger any alert or sound. It wakes up your app and allows you to perform any non-UI related operations in the background.
Sample payload for a background notification:
{ "aps" : { "content-available" : 1 }, "acme1" : "bar","acme2" : 42 }
You need to add “Background Modes” and “Push Notifications” capabilities in Xcode in order for your app to be able to receive a silent push notification.
Points to note:
You can only test push notifications in a real iOS device. iOS
simulator will not be able to receive any push notifications.
The background operation triggered by a silent push notification
will have roughly 30 seconds of execution time.
Silent push notifications will not work when the device is in Low
Data Mode.
Apple guideline for this topic to refer in more details.

application(_:didReceiveRemoteNotification:fetchCompletionHandler) is not called before user taps on notification

I saw in several places:
https://www.raywenderlich.com/11395893-push-notifications-tutorial-getting-started
If your app was running either in the foreground or the background, the system notifies your app by calling application(_:didReceiveRemoteNotification:fetchCompletionHandler:). When the user opens the app by tapping the push notification, iOS may call this method again, so you can update the UI and display relevant information.
https://medium.com/fenrir-inc/handling-ios-push-notifications-the-not-so-apparent-side-420891ddf10b
Background: When the notification arrives. + If the user taps the
notification, before the app enters foreground.
that if I set "content-available": 1 and add some data payload to notification, the method application(_:didReceiveRemoteNotification:fetchCompletionHandler) will be called twice (unless I set delegate for UNUserNotificationCenter) when my app is in background and then when user taps on notification.
Unfortunately, I didn't notice such behavior, the method above was only called once after user taps on notification.
The notification I'm trying to send is something like:
{
"aps": {
"alert": "Test",
"sound": "default",
"content-available": 1
},
"test": "abc"
}
Has something changed in iOS 13/14 (the Ray Wenderlich tutorial seems to be up-to-date) or am I missing something?
EDIT
Interestingly, after reinstalling the app multiple times, it started working. I set the UNNotificationCenterdelegate and it works like that:
App is in background, the server sends notification with content-available: 1.
System shows alert and application(_:didReceiveRemoteNotification:fetchCompletionHandler:) is called so I can fetch new data.
User taps on alert, userNotificationCenter(_:didReceive:withCompletionHandler:) is called, so I can navigate to particular view.
Is it a proper way of handling push notifications with data payload?

executing code in response to an iOS notification

I need to execute code when my iOS app receives a notification, without involving any user interaction.
if the notification is a silent (i.e. non alert) notification DidReceiveRemoteNotification() does fire in both background and foreground modes.
However, silent notifications are relatively low priority and delivery is not even guaranteed, so this is not a viable option for us; we need to use alert notifications.
If the notification is an alert notification, DidReceiveRemoteNotification() does fire when the app is in foreground mode. However, it does not fire in background mode.
How can I execute code in response to an alert notification, in background mode, without involving user interaction. Is this even possible?
Thanks.
You can combine both silent notification and alert notification on one JSON.
by adding "content-available" : 1 as following :-
{
"aps" : {
"alert" : "Notification Title",
"content-available" : 1
}
}
This will show the alert notification as well as wake the APP to do work on background.

Only Allow One User To Click Push Notification

I want to send all users of my app a Push Notification that will bring them to a certain page in the app.
However, I only want one user to be able to tap it and go to the page, and when one user loads the page that the push brings them into, I want to silently remove the push from all other users.
Is this possible to do? I'm not sure how to grab all sent push notifications, whereas the UNUserNotificationCenter only grabs pushes sent on that device.
Thank you in advance!
I believe that this is possible if you use silent notifications.
Send a silent notification of type A.
All devices receive a type A notification and create local notifications in their UI.
A user press this local notification and load the page from the server.
Application of that use on the click / load event will send some request/event to your server that someone access the link.
Your server will send another silent notification of type B.
All devices receive the type B notification and use the code of the links to discard the type A notification from their own notification center.
Here are relevant posts of clearing notifications:
all the notifications of your application:
iOS application: how to clear notifications?
a specific notification:
https://stackoverflow.com/a/6341476/944070
Possible problems / Issues:
Between the user's click step 3 and step 6 it may take some time if you consider the push delivery times, so someone else may press the link. It's not instant. This can become worse in bad network conditions.
It may be annoying to the users that get a beep on their devices and the notification at last cleared because someone else was faster.
You cannot remove a push notification once it has been sent.
Although you could update the App badging by sending another push to reset the badging to zero. While this won't remove the previous push message, it can hide the red badging on the App icon.
You can simply remove the notification by
Sending the badge count as 0
APNS payload will be :
{
"aps" : {
"alert" : "",
"badge" : 0,
"sound" : "bingbong.aiff"
}
}
If you want to remove or decrease badge count number then you can do it easily with
UIApplication.shared.applicationIconBadgeNumber = max(UIApplication.shared.applicationIconBadgeNumber - 1, 0)
If you want to remove a single notification from notification center then, you can do it by using UNUserNotificationCenter in iOS 10 and above.
UNUserNotificationCenter object manage all notification-related behaviors in app or app extension.
You can removes the specified notification requests from Notification Center by using :
func removeDeliveredNotifications(withIdentifiers: [String])

The purpose of "Content-available" in Push Notification Json?

The purpose is to send push notification with only badge value & nothing else (no banner).
I integrated parse sdk to test push notification & send this push notification
{
"alert" :"",
"badge" :"787",
"Content-available" : "1",
"sound" : ""
}
So the push notification got send when app is in background, foreground & when app is killed.
The purpose to wipe some data on arrival of push notification with badge valve 78 got succeeded.
I send same notification with "Content-available" : "1" removed but everything worked fine as earlier.
My understanding on "Content-available" was that putting it's value to 1 will allow push notification with no alert value.
So I am confused or I am missing something to know the meaning of "Content-available" in this push notification JSon.
Thanks
If you provide this key with a value of 1, (if user opens you app is in background or resumed) the application:didReceiveRemoteNotification:fetchCompletionHandler: will be called.
According to RemoteNotifications Programming content-available definition is
Provide this key with a value of 1 to indicate that new content is
available. Including this key and value means that when your app is
launched in the background or resumed,
application:didReceiveRemoteNotification:fetchCompletionHandler: is
called.
(Newsstand apps are guaranteed to be able to receive at least one push
with this key per 24-hour window.)
TL;DR:
"content-available" : 0: The default; your application won't be notified of the delivery of the notification unless the app is in the foreground.
"content-available" : 1: your application will be notified of the delivery of the notification if it's in the foreground or background (the app will be woken up).
The only time you need to use "content-available" : 1 is for background update notifications:
Background update notifications improve the user experience by giving you a way to wake up your app periodically so that it can refresh its data in the background. When apps do not run for extended periods of time, their data can become outdated. When the user finally launches the app again, the outdated data must be replaced, which can cause a delay in using the app. A background update notification can alert the user or it can occur silently.
However, this does NOT always mean that this notification will be invisible to the user:
If there are user-visible updates that go along with the background update, you can set the alert, sound, or badge keys in the aps dictionary, as appropriate.
By default, "content-available" is set to 0. These "regular" notifications do not immediately notify the app UNLESS the app is in foreground. Instead, these "regular" notifications notify the app when a user taps on them or has selected an option via a "Haptic Touch" on the notification.
Background update notifications are delivered to application(_:didReceiveRemoteNotification:fetchCompletionHandler:):
Unlike the application(_:didReceiveRemoteNotification:) method, which is called only when your app is running in the foreground, the system calls this method when your app is running in the foreground or background.
Note: there's a key distinction between "your application" and "the device:" the device will show the notification if the payload requests it to be shown, but this doesn't always mean that "your application" will be notified on the delivery of this notification (aka "your application" code will run). That's where "content-available": "1" comes in: "your application" will always be notified unless its been terminated.
Short answer: for me I just used "content_available" : "1", or "content_available" : true for resume the background/quit modes in iOS. Notice in my case it's underscore and not hyphen separated.
In my specific scenario my app was made in react-native and I have used https://rnfirebase.io for push notifications
Here a complete explanation of this:
https://rnfirebase.io/messaging/usage#data-only-messages
in IOS
content_available" : "1
equivalent in Android
priority: 'high',
In both cases the background message will invoke the onMessage() method when the app is resumed from background, so the program can run some specific code from there.
Here a sample of sending a push notification using CURL:
#curl -H "Content-type: application/json" -H "Authorization:key=#MyAuthHashCode#" -X POST -d '{ "to": "/topics/#thetopicnumber#","notification": { "title": "msg for topic", "body": "bodytext", "content_available": "true" }}' https://fcm.googleapis.com/fcm/send

Resources