I already implemented this:
enable remote notifications in background modes
silent notification {"aps": {"content-available": 1}}
In Apple docs on Push Notification, they are saying:
When a silent notification arrives, iOS wakes up your app in the
background so that you can get new data from your server or do
background information processing.
#
(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
After receive silent notification. In this method, I am downloading some data from the server then data synchronization.
EXPECTED:
The goal is when user open/using the app, it should reflect the latest position for the user.
ACTUAL:
Receive silent notification, download data from server, then data synchronization are works fine when app is running in foreground and background.
But can't wakes up the app in background and to do that when my app is not in running state (app is not launched or killed from app switcher).
QUESTION:
I silent notification doesn't work when app not running? (can't wake up app in background)
Is there missing code in my code which need implemented?
If this way doesn't work when app not running. Is there any way to keep my app local data always same/synced with the database server (when I'm using or not the app)? how other app do it?
Silent notifications are able to bring your app into the background to do any tasks that you may require, as per the Apple documentation:
the system wakes the app in the background (or launches it into the background)
The method you are using, userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:,
is called to let your app know which action was selected by the user for a given notification.
The correct method you should be implementing (even in iOS10) is:
application:didReceiveRemoteNotification:fetchCompletionHandler:. This tells the app that a remote notification arrived that indicates there is data to be fetched.
The way you are doing it is the correct (and probably most popular way) of syncing data between a server and application instance when the user is not actively engaging with the app. Your issue seems to be that you are using the wrong app delegate instance method for your callback.
Update 1:
As per your updated question, I have updated my answer.
That the notifications are not being delivered to your app after it has been terminated by the user is by design. According to the documentation:
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.
To combat this, you can look into Apple PushKit. Originally intended for VoIP apps, it would also work for your application. However unlike regular silent notifications, these do wake up your app even if it has been terminated by the user.
However, keep in mind that once a user terminates an application he expects to have terminated it for good (or until he manually restarts it). To override this would be poor design. Maybe it is fine with the user if the app spends some time downloading the latest data upon launch if the user had terminated the app previously? Depending on the exact reason why you need your app to have the latest information before launch, maybe you don't need to account for this scenario.
Related
Right now I have a framework that receives a silent notification, get the data from it (custom data) and translate it into a local notification to show the alert to the user (this is donde in didReceiveRemoteNotification:fetchCompletionHandler method). I have implemented this framework on an app and everything seems to be working correctly, silent notifications are being process when the app is in background and foreground. However, when the app is killed by the user or it is not running, I cannot receive notifications because of this:
Use this method to process incoming remote notifications for your app.
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. In addition, if you enabled the remote notifications
background mode, the system launches your app (or wakes it from the
suspended state) and puts it in the background state when a remote
notification arrives. However, 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.
The reason I use this method for showing notifications is because the payload I sent to APNS has custom data with key-values that indicate how the notification must behave.
I've been doing some research and I found that Pushkit for VoIP can do the job. However, many post suggest that this can cause app rejection.
So my question is, how can I achieve receiving remote notifications even if my app was killed and considering that data in the payload has custom information to build the notification?
Silent push notifications are unreliable: they might get delayed, delivered in groups or even not delivered at all.
If you need to modify the content of the notification before presenting a banner for the user, you should use a Notification Service App Extension. You can also share some information between your app and this extension - using app groups or the keychain - if it needs something from your app to process the notification data.
I am trying to implement silent push notification in my application where I need to update some data in the server when silent notification comes. I am using Pushkit and it uses VoIP certificate for silent push notification but the app has been rejectd by Apple saying that "I can't use VoIP" certificate. It seems that apple has rejected it as I don't have any VoIP call functionality in my app. In that case how can I implement silent push notification so that my app gets activated even if it is not runnning(not even in the background) and I can update the server?
From my experience, iOS respects user's choice, so in case the user has killed the app, it will remain killed - no silent push notification will wake this app. VoIP is an exception to that, but as you wrote, it should be used only in VoIP apps. This makes sense, consider it a platform limitation: thanks to that user have some control over what is actually running on the phone, the device consumes less battery and lastly, foreground/system Apps has the most CPU time to utilize.
There are few techniques to work with data in the background:
Content-available push notification: will wake up the application in case it is suspended, or startup it in case it has been killed by the system/crashed. Note, that this only opens a 30-second window and amount of notifications is throttled by APNS.
Background fetch capability will act in a similar manner.
Background task to finish existing task - but this is only used when app is moved to the background.
If you need App to send updates to the server, I believe above should be sufficient (unless your app is spying on a user, it should have all relevant data available once the user finishes interaction with the App).
If you need a server to send data to the App, use silent push notification (or background fetch for periodic pulling), or in case this data is critical to the user, you can present him a remote notification - if the user considers that an important update, he will open the app.
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.
When I receive a remote notification I updated a counter that I save to UserDefaults and I also show a local notification. Everything works as expected when the app is in the foreground, background, and suspended states Ref. When the app is in the Not Running state my counter is not updated nor is my local notification shown.
It is my understanding that I should be able to receive and process Remote Notifications while the app is completely off. A few articles online claim that when a Remote Notification arrives while in the Not Running state that the application:didFinishLaunchingWithOptions: should be called followed by application: didReceiveRemoteNotification:fetchCompletionHandler: but in my case it is not.
Is it possible to receive remote notifications while in Not Running state?
If your app is a VoIP app and you are using VoIP pushes through PushKit then a push notification will launch your app from the terminated state in order to deliver the notification. If you are using standard push notifications then your app will not receive the notification if it is terminated. You can include an alert text with a 'silent' notification that will be displayed to the user in the event that your app is terminated in order to prompt them to launch your app.
First of all, it sounds like you have a silent notification set up. Once you add alert data to your push notification (information like the title, body etc.. you can find more on that here), it'll start to display on the lock screen.
Second, it's not possible for your application to launch from a push notification, silent or otherwise, if it's in the Not Running state. The documentation on this is actually incorrect, as it states that the application will only not be launched if the user has quit the app. However, this actually also applies for any circumstance under the not-running state, for example if your app has never been launched since installation/rebooting, or if it was quit due to memory (a fairly common occurrence - iOS purges apps which haven't been run recently as required).
did you check this mark when app is background?
Official document from apple developer network mentions that the payload of a push notification is provided to an application when it’s running in foreground, or when it’s activated because of a push notification. I cannot find the statement about what happens when the app is running in background.
I did a test with an instant message application, and found something that I do not understand. Procedure of the test is:
Enable push notification for the app
Switch the app to background
Send two IMs to the client. Two push notification arrives at the client and the badge on the app's icon becomes 2
Shut down cellular network to prevent the app from communicating with its server
Click the app icon to switch it to foreground
After these steps, I can see the 2 messages in the chat window. Because the app is not able to retrieve the messages directly from server, the only explanation is that the push notifications are processed by the app when it’s in background, or they are cached somewhere and can be accessed by the app when it's switched to foreground. But does iOS really allows an app to execute codes when it’s in background, or cache notifications for apps?
The application caches the notifications for 2-5 minutes(i don't know exact) time..
If you receive a notification and you open the app in 2-5 minutes
then in your app delegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
}
You will have the notification object then .. you can get it using launchOPtions object for key UIApplicationLaunchOptionsRemoteNotificationKey
If you don't open it within 2-5 minutes.. there will be no notification object,
This is based on my experience..cant totally support this answer