how can I handle a remote notification without opening the app (when the banner appear on the screen)
I tried a lot of methods and they are called only when I tap on the notification
If your app needs to analyze push notification without, user tapping on it, you need to set content-available=1 in your push notification,you get the push data in 'didReceiveRemoteNotification' function in your AppDelegate. but you need to consider something, even with this method, there is no guarantee that your application get the push notification data, Your application get the push's data only when your application is in foreground or your app is in background but IOS system is not idling your application otherwise your app is not going to get the push notification from IOS.
Related
When app is not running (terminated NOT in background) and a remote push notifications is received, is there any way to inform the app about it so that the app can update something locally such as simple int counter?
I want to store something so that when the app is launched the next time, app knows that notification was received when app wasn't running and something needs to be done.
If user launches an app by tapping on a notification, obviously the app is notified about it through AppDelegate methods but these methods are never called if user launches an app by tapping on the app's icon.
To be aware of notification when user launches app by tapping on icon, i need some way to let app know that notification was received when app was in background.
There is no way you can achieve this with simple push notifications.
According to apple docs if the user has manually killed your application by swiping it out of memory, your app will never be started in the background to process data until after the user chooses to launch it again.
One solution to this problem is using VOIP push.
According to apple docs -
Your app is automatically relaunched if it’s not running when a VoIP
push is received.
But you need a strong reason for using it and apple may ask that before approving your app on the app store.
To read more about VOIP push please go through this doc - https://developer.apple.com/library/content/documentation/Performance/Conceptual/EnergyGuide-iOS/OptimizeVoIP.html
You can also be used the "Silent Push Notifications".Which are confirming that their is something available on the server, which you need to download to your app,The payload format of the Silent push notification is like
{ content-available:1 }
The Best part of the silent notification is that they do not notify the iPhone user
Here 1 is for their is something available to download from the server.
here below i have attached the apple's silent notification slide.
Your App is getting Refresh in the Background.
I have implemented the UIApplicationDelegate method -(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler to handle push notifications, it works fine. In some situations, I need to retrieve the payload of the push notification. But sometimes this delegation method is not called.
I have a question about retrieving the payload (userInfo) in this scenario:
The app running either in background or not launched. The app received a push notification, a banner is shown, sound is played, and message is displayed, app icon badge increased, and the push notification can be seen in the iOS notification centers. If the user taps the notification when it's shown or in the notification center, the app launches, and the didReceiveRemoteNotification: method is called.
However, if the user just tap the app icon and launch the app in normal ways, the method is not called, and I can't retrieve the userInfo.
From Apple's documentation on handling push notifications:
The notification is delivered when the app isn’t running in the foreground. In this case, the system presents the notification, displaying an alert, badging an icon, perhaps playing a sound, and perhaps displaying one or more action buttons for the user to tap.
The user taps a custom action button in an iOS 8 notification. In this case, iOS calls either application:handleActionWithIdentifier:forRemoteNotification:completionHandler: or application:handleActionWithIdentifier:forLocalNotification:completionHandler:. In both methods, you get the identifier of the action so that you can determine which button the user tapped. You also get either the remote or local notification object, so that you can retrieve any information you need to handle the action.
The user taps the default button in the alert or taps (or clicks) the app icon. If the default action button is tapped (on a device running iOS), the system launches the app and the app calls its delegate’s application:didFinishLaunchingWithOptions: method, passing in the notification payload (for remote notifications) or the local-notification object (for local notifications). Although application:didFinishLaunchingWithOptions: isn’t the best place to handle the notification, getting the payload at this point gives you the opportunity to start the update process before your handler method is called.
If the notification is remote, the system also calls application:didReceiveRemoteNotification:fetchCompletionHandler:.
If the app icon is clicked on a computer running OS X, the app calls the delegate’s applicationDidFinishLaunching: method in which the delegate can obtain the remote-notification payload. If the app icon is tapped on a device running iOS, the app calls the same method, but furnishes no information about the notification.
The highlighted part kinda saying there is no obvious way to access the payload of the push notification in this way. So is there a way to work around this issue?
Thank you!
It is the default behavior of iOS. You will never know the payload unless user opens your app via tapping on the notification.
You can use silent push notifications if you want to send custom data (max 2048 bytes) or commands to your mobile app.
In the push notification set 'content-available' to 1 so you app gets some time to process data and also add your custom content to the notification.
I also use silent push notifications to trigger my apps to update by REST HTTP calls, since my data can be bigger than the max size... The only downside is that Apple might block your background activities if you are battery or processor intensive. Visual push notifications are always delivered.
Things I hate most are visual push notifications like 'you've got a new message' , on which I click sometimes when no data connection is available and the app will not show me the message... You can solve this by sending a silent push notification with data and only if the data could be fetched from the server, or
stored correctly in case you can send it all in the notification, you set a local notification.
Choose between visual and silent push notifications wisely is my only advise.
Check the following link for more official Apple info: https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CreatingtheNotificationPayload.html
I might by fighting the windmills but I need to put some clearance into my knowledge of remote notifications. I want to handle notification while my app is turned off (killed from the app switcher) but user decides to turn it on not by tapping on notification but by tapping on app icon.
As far is I know, when app is killed and a remote notification arrives user has to tap on notification to pass it in launchOptions from didFinishLaunchingWithOptions: but... I want to handle this notification when user taps on app icon and nothing is passed to lauchOptions. In that scenario, at the moment I have no notification at all...
Is it possible to handle notification in background and perform action on it no matter how the app has been launched? Maybe didReceiveRemoteNotification: fetchCompletionHandler:?
Yeah, you are fighting the windmills :)
I recommend you to read Local and Push Notifications in depth. It's a bit long but the doc is clarifying.
In a fragment of this doc you can read:
If the application icon is tapped on a device running iOS, the
application calls the same method
(application:didFinishLaunchingWithOptions:), but furnishes no
information about the notification.
And later on:
When handling remote notifications in
application:didFinishLaunchingWithOptions: or
applicationDidFinishLaunching:, the application delegate might perform
a major additional task. Just after the application launches, the
delegate should connect with its provider and fetch the waiting data.
Listing 2-5 gives a schematic illustration of this procedure.
So having said this you could have a list of sent notifications for each device in your server and each time your app launches check if the device has any pending notification.
From the Local and Push Notification Programming Guide
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
So, if your application is launched from the icon then you won't receive the notification data. You need your app to query the service/data store that is responsible for sending the notification to see if there is outstanding data/transactions/whatever.
Is there an opportunity to stop showing push notifications via an app?
I have an app connected to a database. When someone sends me something like a message I will get a push on my devices (lock-)screen. But if the user does not want to see specific notifications for something, maybe a new message by person XY, it should not appear!
So is there an opportunity for hide specific pushs via the app or do I have stop them server-side?
You'll have to make the change server-side. From the app side, you can't stop only certain push notifications, because it's while the app is backgrounded (or not even running) that push notifications will be showing, so your app has no control over whether specific ones will show or not.
If the app is not in the foreground then the push notifications don't get delivered to the app, they get delivered directly to the user and hence there is no chance for the app to intervene and filter them.
BUT if your app is for iOS7 only then you could use silent background push notifications, then when the push is delivered the OS will rouse your app and the push will be delivered to it, then the app can examine the content of the push and also examine the user preferences and then present the background push as a local push or not (to the user a local push looks just like a remote push).
One caveat is that if the user forcefully terminates your app (by upwardly swiping it out of the task manager) and the user has not restarted it then the OS will not deliver the silent push to it.
In the scenario where a user did not swipe a push notification before it disappeared, is there any way to retrieve the last one sent to the device for my app? I can go into the notification center and see the last few push notifications for my app there, is there any way I can retrieve the last one when my app opens?
There is no way to retrieve past push notifications.
Typically, this isn't needed. Once launched, your app can communicate with your server to see what's new.
If the app is launched from a notification, your app will receive the push notification passed in as an option with the key UIApplicationLaunchOptionsRemoteNotificationKey to the app delegate method application:didFinishLaunchingWithOptions.
If your app is running and in the foreground when the push notification arrives, the app delegate application:didReceiveRemoteNotification will be called
With iOS 7 and later, if the notification type is content-available and you have the Background App Refresh capability turned on (and the user has not disabled Background App Refresh), then an app in the background will also get application:didReceiveRemoteNotification