iOS Retrieving Push Notifications on applicationDidBecomeActive when application:didReceiveRemoteNotification isn't triggered - ios

I'm writing an app that receives push notifications. When it gets one, and someone opens their phone through that notification, my application's delegate receives a application:didReceiveRemoteNotification: which comes with important notification data in the second argument.
However, if they get a push notification for another app, and open their phone through that, and then open my app, my apps notification is still queue in the pull-down notification center, and my app's delegate does not receive an application:didReceiveRemoteNotification: message with that push data until they tap that notification in the pull-down notification center. Ergo, I don't get the push data I want processed in my app regardless of how the user opens the app...
Is there a way I can get that notification in applicationDidBecomeActive: somehow?
Help appreciated. Thanks,
Nick

Unfortunately, it isn't possible.
As far as I know, there are only two ways for your app to learn about a push notification:
The user opens your app by tapping/swiping the notification
You app is open when the device receives the push notification

Related

iOS retrieve remote notification payload

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

iOS Push Notification - check if the banner is showing when app is in background

I have a VoIP app, where the incoming call notification is very important.
The problem is, sometimes I don't get the push notification (even Apple said it's not guaranteed). But, I do have a mechanism to notice that an call is coming while the app is in the background.
So, what I want to do is.. still use Push Notification as the main handler for incoming call (because it handles the situation when app is closed). However, if the push notification failed to deliver and my app gets the call invite, I will raise a local notification, telling user that you have an incoming call.
My question is... how can I check if a notification is showing before I decide whether to fire a local notification?
AFAIK you can only detect the notification when the user taps on the banner OR if the app is open when the notification comes. So I can't see a way to detect if the notification has come yet or not. Just adding to the pain, push notification is famous for its unreliability.
There’s no API to get any information about the state of your notifications. Since you’re making a VoIP app, you have the option to have it get woken up for incoming data, which would let you post your “incoming call” notification whenever you need it—see the “Configuring Sockets for VoIP Usage” section here.

Handling remote notification while app is totally off by launching from app icon

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.

iOS - change a view's content on push notification received event

I'm coming from Android development background. In Android you send a push notification and then you handle the rest using a service (creating the actual system notification, modifying app's content, etc).
As far as I know, when sending iOS push notifications, it automatically creates a system notification for you in the notification center based on your message payload. After searching here and on google, I think I have to use application:didReceiveRemoteNotification event to add/remove a view's content. How can I access the push notification's content so I can put it in the app as well (I want to display the message in the app even if the user has dismissed the notification in the notification center)? There will be another message later on (usually the same day) to remove the message from the app.
I understand that the application:didReceiveRemoteNotification method won't be called if the app is closed, so I will have to use some other event (like didfinishlaunching) to get the message. But how do I access the push notification's message itself?
I want to display the message in the app even if the user has dismissed the notification in the notification center
This can't be done. iOS passes the notification data to your app only if the user opens the app from the notification center. If the user dismisses the notification and later launches the app, the only way for the app to get this data is to retrieve in from your server.
As for getting the notification data if the app is launched from the notification center, see this question.

Is there a way to get the last push notification when my app starts up?

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

Resources