Will iOS launch my app into the background if it was force-quit by the user?
Asked Answered
M

7

227

I am triggering a background fetch by using the content-available flag on a push notification. I have the fetch and remote-notification UIBackgroundModes enabled.

Here is the implementation I am using in my AppDelegate.m:

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
    NSLog(@"Remote Notification Recieved");
    UILocalNotification *notification = [[UILocalNotification alloc] init];
    notification.alertBody =  @"Looks like i got a notification - fetch thingy";
    [application presentLocalNotificationNow:notification];
    completionHandler(UIBackgroundFetchResultNewData);

}

When the app is running in the background, it works fine. (The notification is received and the app triggered the "looks like i got a notification" local notification, as the code above should do).

However, when the app is not running and a push notification is received with the content-available flag, the app is not launched and the didRecieveRemoteNotification delegate method is never called.

The WWDC Video Whats New With Multitasking (#204 from WWDC 2013) shows this: enter image description here

It says that the application is "launched into background" when a push notification is received with the content-available flag.

Why is my app not launching into the background?

So the real question is:

Will iOS perform background tasks after the user has force-quit the app?

Monophthong answered 28/9, 2013 at 15:53 Comment(2)
How are you checking whether the app launches in the background?Saxony
@Saxony I log a bunch of crap in - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptionsMonophthong
M
218

UPDATE2:

You can achieve this using the new PushKit framework, introduced in iOS 8. Though PushKit is used for VoIP. So your usage should be for VoIP related otherwise there is risk of app rejection. (See this answer).


UDPDATE1:

The documentation has been clarified for iOS8. The documentation can be read here. Here is a relevant excerpt:

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.


Although this was not made clear by the WWDC video, a quick search on the developer forums turned this up:

https://devforums.apple.com/message/873265#873265 (login required)

Also keep in mind that if you kill your app from the app switcher (i.e. swiping up to kill the app) then the OS will never relaunch the app regardless of push notification or background fetch. In this case the user has to manually relaunch the app once and then from that point forward the background activities will be invoked. -pmarcos

That post was by an Apple employee so I think i can trust that this information is correct.

So it looks like when the app is killed from the app switcher (by swiping up), the app will never be launched, even for scheduled background fetches.

Monophthong answered 5/10, 2013 at 20:38 Comment(18)
For me adding the action in "didFinishLaunchingWithOptions" when launching options are not nil did the work. I have the same method here as in "didreceiveRemoteNotification"Hint
@harsh.prasad that's interesting. The problem was that the app isn't launched when the app has been killed from the app switcher.Monophthong
The app needn't be shown in the app switcher if a silent push is received. It could be launched in the background without adding it to the app switcher, and be allowed to run and "do its thing" and then exit. Apps that stay active too long would be killed in the same way as they are already.Synchroscope
@chrizstone I think he was just giving an example as to how Apple could handle this kind of thing.Monophthong
@chrizstone The solution is that this is intended behavior, and you can't do anything about it.Monophthong
Yes, Santa Claus is right. It was a hypothetical way it could be done. I hoped that there was a slim chance the Apple person might read this. :-)Synchroscope
Tested with iOS 7.1, as long as background refresh is ON in the settings app, the app will get woken up and the delegate methods will get called (even if the app is terminated or the device is rebooted).Cytochemistry
@PsychoDad I didn't check with iOS 7.1. I guess I'll have to try that out! Thanks!Monophthong
@PsychoDad For me, it still doesn't work when the user terminates the app. As long as the user doesn't terminate the app, background fetch continues to function.Monophthong
@PsychoDad Yep. Figured that out when I posted this answer.Monophthong
What if you've started a background transfer service (BTS)? Will the app be woken up when the NSURLSession completes? Use case : 1)You start the BTS, 2)user taps home, 3)after a while the user kills your app from the app switcher, 4)your BTS completes. Will it fire the app up again ?Murphy
iOS8 Update (Hopes not enforce NDA).Documentation is changed now.Schwa
@Schwa Thanks for notifying me of that! I updated my answer.Monophthong
@JPK Uh, push notifications themselves aren't affected. It's just doing background tasks that won't work after it's been force quit.Monophthong
Thanks Santa Claus. I just realized the issue is only with the silent push notifications being able to download once the app is force closed. Since my app is having trouble with regular push notifications when force closed, I realize there is a problem with my app's code at this point.Emplacement
The notification opens my app but to a blank screen, then immediately closes it.Emplacement
@JPK Then it crashed. You need to take a look at how you are handling opening the app through a push notification.Monophthong
This is not possible anymore from iOS 13.0Declass
S
70

You can change your target's launch settings in "Manage Scheme" to Wait for <app>.app to be launched manually, which allows you debug by setting a breakpoint in application: didReceiveRemoteNotification: fetchCompletionHandler: and sending the push notification to trigger the background launch.

I'm not sure it'll solve the issue, but it may assist you with debugging for now.

screenshot

Saxony answered 28/9, 2013 at 16:40 Comment(9)
so this helped but the issue still existsMonophthong
Strange. I assume you've more than double-checked all the flash are set in your plist, etc.?Saxony
Also, i know i have everything set right because when the app is in the background, everything works perfectly. Its just when the app is not running at all that it doesn't.Monophthong
I wonder if a push notification launch-trigger is system-determined. For example, if iOS determines it's not a great time to launch the app right now it might postpone it until later. Perhaps try and close all running/background apps and see what happens? I am just guessing at this point :-/Saxony
just tried that. Nothing happened, just like usual. I might ask on dev forums.Monophthong
Well...lucky you. Nobody found the answer besides me, and your answer was most helpful, so here is the bounty. Merry Christmas.Monophthong
Tested with iOS 7.1, as long as background refresh is ON in the settings app, the app will get woken up and the delegate methods will get called (even if the app is terminated or the device is rebooted).Cytochemistry
As long as you don't swipe it out of the task list it will get woken up and re-launched (even if you reboot your device or the app is terminated due to memory)Cytochemistry
U saved my life man ! I put control in didFinishLaunchingWithOptions:(NSDictionary *)launchOptions , if launchOptions is not nil, and launchOptions objectForKey:@"UIApplicationLaunchOptionsRemoteNotificationKey has an objects, i can understand push message received. Otherwise, launchOptions comes with nil argument.Yasmineyasu
E
39

The answer is YES, but shouldn't use 'Background Fetch' or 'Remote notification'. PushKit is the answer you desire.

In summary, PushKit, the new framework in ios 8, is the new push notification mechanism which can silently launch your app into the background with no visual alert prompt even your app was killed by swiping out from app switcher, amazingly you even cannot see it from app switcher.

PushKit reference from Apple:

The PushKit framework provides the classes for your iOS apps to receive pushes from remote servers. Pushes can be of one of two types: standard and VoIP. Standard pushes can deliver notifications just as in previous versions of iOS. VoIP pushes provide additional functionality on top of the standard push that is needed to VoIP apps to perform on-demand processing of the push before displaying a notification to the user.

To deploy this new feature, please refer to this tutorial: https://zeropush.com/guide/guide-to-pushkit-and-voip - I've tested it on my device and it works as expected.

Eunuchize answered 24/3, 2015 at 11:26 Comment(5)
Looks like to me you have to set your app as using VoIP. If you app isn't actually a VoIP app, won't it just get rejected during review?Thetos
Unfortunately, knowing the validation process by Apple, it would be logical that the application was rejected.Graeme
Used for VoIP. If not using VoIP for the user, this will greatly increase the risk of review rejection.Supplication
Looks like big providers are using this facility as an excuse to run stuff in the background and Apple is running a blind eye. Becoming Android one feature at the time.Ovoviviparous
PushKit is reserved for VoIP, File Providers, and Watch Complications. It is not available for the use cases this answer describes.Tuberosity
C
15

Actually if you need to test background fetch you need to enable one option in scheme:

enabling bg fetch

Another way how you can test it: simulate bg fetch

Here is full information about this new feature: http://www.objc.io/issue-5/multitasking.html

Coldshoulder answered 1/4, 2014 at 16:42 Comment(0)
L
4

I've been trying different variants of this for days, and I thought for a day I had it re-launching the app in the background, even when the user swiped to kill, but no I can't replicate that behavior.

It's unfortunate that the behavior is quite different than before. On iOS 6, if you killed the app from the jiggling icons, it would still get re-awoken on SLC triggers. Now, if you kill by swiping, that doesn't happen.

It's a different behavior, and the user, who would continue to get useful information from our app if they had killed it on iOS 6, now will not.

We need to nudge our users to re-open the app now if they have swiped to kill it and are still expecting some of the notification behavior that we used to give them. I'm worried this won't be obvious to users when they swipe an app away. They may, after all, be basically cleaning up or wanting to rearrange the apps that are shown minimized.

Lobotomy answered 18/10, 2013 at 23:3 Comment(2)
That's exactly what we did (applicationWillTerminate), but I don't believe it gave the notification during memory purges, at least not on iOS 7. I did notice that it showed the notification right before a reboot for an OS upgrade, but that's so rare it didn't seem too bad.Lobotomy
"On iOS 6, if you killed the app from the jiggling icons, it would still get re-awoken on SLC triggers. Now, if you kill by swiping, that doesn't happen." This does now happen, it was a temporary regression in an early version of iOS 7.Hessler
R
4

For iOS13

For background pushes in iOS13, you must set below parameters:

apns-priority = 5
apns-push-type = background
//Required for WatchOS
//Highly recommended for Other platforms 

Background PUSHES The video link: https://developer.apple.com/videos/play/wwdc2019/707/

Radioactivate answered 20/8, 2019 at 4:41 Comment(1)
Can you share me the video link please?Issuable
J
3

This might help you

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.

Source: https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html

Janka answered 5/4, 2018 at 10:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.