I have implemented application:didReceiveRemoteNotification:fetchCompletionHandler:, which is necessary to run after receiving a push notification. I have also turned on "Background Fetch" and "Remote notifications" background modes. And my push notifications include the content-available flag, set to 1.
If my app is in the Active, Background or Suspended state, this function gets called appropriately and the app temporarily moves into the Inactive state. However, if my app has been purged from the Suspended state due to a low memory issue (i.e. the user has opened a number of other apps since launching my app, a fairly common occurrence), it moves into the Not Running state. At that point, it doesn't call the didReceiveRemoteNotifications function.
The documentation for this function states:
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 scenario where the user force quits the app and so the app doesn't call this function is acceptable. But what I'm seeing instead is if the system terminates the app for a fairly common reason, then this function doesn't get called.
I've also tried implementing application:didReceiveRemoteNotification:, the deprecated function, to see if that gets called when the app is in the Not Running state. It doesn't.
Related
Here a very tricky situation: I'm writing an alarm app in swift. At the moment the alarm is fired the application will most likely be in background or killed or even worse the iPhone is locked. As soon as the alarm is fired the app should set another notification automatically while in background. I'm able to do this in AppDelegate only if the app is in foreground, but in background, I'm only able to set a notification with a nice attachment and sound, but no code is executed. I'm not able to call a method after a local notification was received in background with a locked device.
Help would be very appreciated. I'm not sure there is a solution. Thank you very much.
Reading didReceiveRemoteNotification it says that this method is called if your app is running in the foreground or background.
What you may find useful is
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.
So, I don't the think you can work around the killed scenario. But with background mode enabled you can at least wake the app from at most the suspended mode.
Read Apple's Background Execution article, especially the section Understanding When Your App Gets Launched into the Background. Where it says a background execution is when
A push notification arrives for an app and the payload of the notification contains the content-available key with a value of 1.
You may be able to do some or most of what you want in here.
When i reboot my phone without opening my app, and send a remote notification with 'content-available' bit, my app is not launched or invoke the delegate. But I can get the notification alert. The app was even launched for scheduled background fetch! Once I started my app by tap icon, the delegate is invoked as expected even if my app is in background or killed(not force quit).
Am I misunderstanding Apple's doc of this method or I'm missing something in my implementation?
It's running on iOS 9.3.1.
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 push
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.
Silent notifications work via Background modes and content available flag, but only if the app is in background.
Is it possible to know if/when the user received the notification, even when the app is suspended(not in background) ?
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.
Here is the relevant section from the documentation:
application:didReceiveRemoteNotification:fetchCompletionHandler:
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 push
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.
I have tried various samples from the web (the last one being this one) in order to get a better understanding of NSUrlSession.
What I was hoping to see: file downloads will continue even if the app that triggered them gets killed (for instance by the user through the task manager). However this does not seem to happen.
Is this a configuration issue or does background file transfer not work if the app gets terminated?
I thought the whole idea was that iOS will restart the app.
If the system kills your app and your background session has active downloads, your downloads will continue and the system will launch your app when the downloads complete. However, if a user force quits your app, all tasks get cancelled.
Documentation for backgroundSessionConfigurationWithIdentifier:
If an iOS app is terminated by the system and relaunched, the app can
use the same identifier to create a new configuration object and
session and retrieve the status of transfers that were in progress at
the time of termination. This behavior applies only for normal
termination of the app by the system. If the user terminates the app
from the multitasking screen, the system cancels all of the session’s
background transfers. In addition, the system does not automatically
relaunch apps that were force quit by the user. The user must
explicitly relaunch the app before transfers can begin again.
No - the app is not relaunched for background downloads when the user has force quit.
The iOS8 documentation for application:didReceiveRemoteNotification:fetchCompletionHandler: says:
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 push
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.
I have created background nsurlsession to perform download task. It worked well when the app was in background. However, download task seems to be canceled and failed when I closed the app (double click "Home" button and swipe up), and it made me to download from the beginning again when I relaunched the app. According to Apple document, background transfer works even the app is no longer running. Am I doing anything wrong?
From the NSURLSessionConfiguration Class Reference:
If an iOS app is terminated by the system and relaunched, the app can use the same identifier to create a new configuration object and session and retrieve the status of transfers that were in progress at the time of termination. This behavior applies only for normal termination of the app by the system. If the user terminates the app from the multitasking screen, the system cancels all of the session’s background transfers.
So, while background transfers will continue if iOS itself closes your app during the normal course of things, if you force the quit from the multitasking screen, it will kill all your transfers.
The app is not relaunched for background downloads when the user has force quit.
The iOS8 documentation for application:didReceiveRemoteNotification:fetchCompletionHandler: says:
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 push
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.
In the first paragraph of NSURLSession documentation, we can observe:
This API provides a rich set of delegate methods for supporting
authentication and gives your app the ability to perform background
downloads when your app is not running or, in iOS, while your app is
suspended.
Now notice where it states:
or, in iOS, while your app is suspended.
It looks like only OS X applications have the ability to finish background tasks while your app isn't running.