We have an app that uses PushKit to receive notifications. (It is not a VoIP app but we have a dispensation from Apple to use PushKit due to being a special app category that has specific needs in healthcare).
When the app is not running and a PushKit notification comes in, the system launches the app into the background and the push kit delegate payload processor is called (PKPushRegistryDelegate pushRegistry:didReceiveIncomingPushWithPayload:forType:). Then the app is closed down again. The app never reaches a graphical interactive state.
This is fine and how it should be. However, iOS does a complete app launch, loading the storyboard and everything. In addition, in the UIApplicationDelegate application:willFinishLaunchingWithOptions:, launch options is nil, so you don't know you're being launched to handle push kit and won't be going interactive.
This is causing us problems as our app does a complete, "heavy" set up of resources, server connections, etc. that don't need and shouldn't be set up to just handle the PushKit notification. This is causing us some issues as certain things being connected (server connections etc.) cause some behavior we don't want when the PushKit is being processed (and then the app going away).
Is there a way to be able know you were launched for pushkit purposes and not do all the app setup that normally happens? (If the app were to then transition to Active we should be able to use the normal active state transition to finish setup)
Once you getting Pushkit payload in didReceiveIncomingPushWithPayload, you have to schedule local notification with info based on pushkit payload. then you can make your app interactive. you can also keep details in NSUserDefault and check on local notification tap events and in didFinishLaunchingWithOption.
This way you can initiate storyboard and get redirect to particular viewControllers.
Let me know if you need more clarification on same.
Related
shortly after this post I managed to convince our team to use push notifications instead of polling! We will use AWS Pinpoint, which uses APNs for IOS. So far everything is amazing, but we are missing a crucial functionality:
We need to make sure that push notification is delivered if the app is in foreground even if user has disabled notification and has disabled background app refresh for our app.
I understand that push notifications would if app is in background and user has disabled background app refresh, but why it affects foreground? Otherwise, polling is still essential, because it does work if user is in foreground...
Perhaps I am mistaken (I hope so), but I have tested various cases and could not solve this particular case.
If the user has disabled notifications, you will not get notifications.
Also, just a caution, push notifications are not a guaranteed quick delivery. If your connections are odd, they can come slowly. Also, if you move from cell to wifi or vice-versa it can make weird things happen with the notifications.
One thing you can try-- don't let your app run if they have disabled notifications. If it is required for your app to function properly, check for enabled notifications in your app delegate at applicationDidBecomeActive
My problem is: I just can't make silent notifications work when a user has force-quit(swiped away) the app!
I guess the following is a fact: A silent push (with content-available:1) will NOT trigger application(_:didReceiveRemoteNotification:fetchCompletionHandler:) nor any other method (it will NOT launch the app) if the application was force-quit (swiped away) by the user! Can anyone prove this wrong?
I have made sure I've enabled Background Mode: Remote Notifications.
But what if non-silent notifications don't work for me? I need silent ones, I need to be able to run some checks before I show it! What If I want to check if the right user is logged on to my application after I receive a notification from remote server? (since I can't guarantee that when he logged out he successfully let the server know about it, so I assume the server doesn't know for sure)
What would be the right approach to take in my situation?
There are many questions about similar things, but not many people involved, I wonder why? I don't believe that I have such a rare case. Maybe my basic approach to solving this kind of problem is wrong? It doesn't seem to be a problem on Android platform at all!
I am using FCM as central point of sending out notifications, so if you say that PushKit can solve my problems, too bad that FCM doesn't support VoIP certificates. But, I wonder, can PushKit really solve this? Or Apple just designed it this way that when a user force-quit an app, it means that this app must shut up altogether with its ability to push remote notifications?!
I don't consider this a duplicate of Firebase silent notification does not start up a closed iOS app because what I am asking here is what would be the solution if you want to check if the user to whom the notification is addressed for corresponds to the user logged in to the application? It can be considered duplicate if it turns out that there is absolutely no solution for this on iOS platform.
You ask:
Or [has] Apple just designed it this way that when a user force-quit an app, it means that this app must shut up altogether with its ability to push remote notifications?
Yes, this is how it is designed. App Programming Guide for iOS: Understanding When Your App Gets Launched into the Background says:
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. When password protection is enabled on the device, the system does not launch an app in the background before the user first unlocks the device.
Is not possible. when the app is in background or suspended modes, you will have 30 sec to do some stuff. But if user kill app manually func didReceiveRemoteNotification will never called.
Upd:
When an iOS device receives a silent notification, the system wakes your app in the background and calls the application(_:didReceiveRemoteNotification:fetchCompletionHandler:) method of its app delegate. Your app has 30 seconds of wall-clock time to perform any tasks and call the provided completion handler. For more information, see Handling Notifications and Notification-Related Actions.
I have an application which has communication with a remote server. The server should push data into it using remote notification silently, and I need to get and store these data into a CoreData database. The user won't be aware of the whole process.
I can successfully get notified when the app receives a remote notification, while it is either in the foreground or background mode. However, I need to get data while the app is terminated as well.
I searched for the possible solutions. For example, this SO question was good if I don't tend to use silent notification. I also saw the PushKit capability, but I am not sure about the Apple Review result.
What is the possible solution?
If I want to use VoIP and PushKit to get notified when the app is terminated, would Apple reject my application?
If you’re not creating a VoIP app and you want your app to be in the App Store then the correct answer is: it is not possible. The only thing that can be done is adjusting your requirements in some way.
For instance you can send some notifications that will be visible for user in the Notification Center and wait until the user taps the notification or starts the app the usual way. Then the app will be able to do all the operations you need.
The delivery of push notifications is not guaranteed, so you should not rely on them to synchronise data.
For example, if multiple push notifications are sent while the device is offline, only the last notification is delivered when the device comes back online; the earlier notifications are lost.
When your app launches one of the first things it should do is check with your server for new data.
I have implemented AWS SNS push notification service.
We have an issue which is explained below :
Scenario :
We are trying to save the notification message we receive as a part of requirement.
When the app is killed (swipe out from recent apps) we are able to receive notification, also we are able to save the notification message when we open the message directly from the notification panel it works fine,but when we open the app directly the notification message is not getting saved.
In short we are not able to know if we had received a notification message if we directly open the app rather than clicking the message from the notification panel.
Is this default behavior ? or is there any work around for this ?
Have looked into many posts on about Push Notifications but haven't seen any threads pointing to this scenario.
This is a normal behavior, and there is no workaround.
If your app is killed by the user, it won't be able to run ANY code before it's manually launched again.
If it's manually launched from a notification, this notification's payload will be handled by your AppDelegate.
On top of that, don't forget that Push notifications are Best Effort. That means that they are not reliable, they can be heavily delayed or never delivered at all. Don't rely on Push notifications to achieve any critical work.
If you need to keep a copy of your notifications in-app, keep them server side and fetch them as you would do with any other object.
In order to execute code when the app is killed by the user you need to implement VOIP using PushKit framework provided by apple.
VOIP push unlike regular push notification enables the app to become active even if the app is killed by user.
I am currently facing a problem with push notifications in iOS.
My app receives silent push notifications containing an identifier. This identifier is then used to fetch data from a remote server from which a local notification is created.
As far as I'm aware, if the user has force-quit an app (i.e. by double tapping the home button and swipe closing the app) then the silent push notification does not get passed onto the didReceiveRemoteNotification method in the AppDelegate class [1] [2], thus preventing the app from doing any kind of processing.
I have done a fair amount of research into handling the situation mentioned above. However, was unable to find a definitive answer and was hoping someone could help me out or point me in the right direction.
TLDR: What should I do when the user has force-quit my app, but I still need to process a silent notification?
Further Information:
My app only needs to support iOS8+.
[1] https://developer.apple.com/library/mac/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html#//apple_ref/doc/uid/TP40008194-CH100-SW1
The Notification Payload
If the target app isn’t running when the notification arrives, the alert message, sound, or badge value is played or shown. If the app is running, the system delivers the notification to the app delegate as an NSDictionary object.
[2] https://stackoverflow.com/a/19202487/2472819
Previously in iOS 7 and before, once a user force-quit an app, it will not be able to run and background tasks at all, including location monitoring, push notification handling with content-available:1 etc.
However the problem is that such behavior is not documented. The reason is that it may change in a new iOS update and Apple doesn't want to nail the coffin too early. As in iOS 8, PushKit is introduced and is supposed to be able to deal with the force-quit scenario. Please check this tutorial for details: https://zeropush.com/guide/guide-to-pushkit-and-voip