49

I am trying to keep the iOS app in active state for more than 10 mins when it enters in background state.

How can I implement this.

Richard J. Ross III
  • 55,009
  • 24
  • 135
  • 201
user968597
  • 1,164
  • 2
  • 15
  • 30
  • @RichardJ.RossIII nop, he want's to run code when the app is in background, not in a background thread. – fbernardo Mar 16 '12 at 14:04

7 Answers7

58

See "Background Execution" section of the iPhoneAppProgrammingGuide. In short, your app must be one of these types:

  • Apps that play audible content to the user while in the background, such as a music player app
  • Apps that keep users informed of their location at all times, such as a navigation app
  • Apps that support Voice over Internet Protocol (VoIP)
  • Newsstand apps that need to download and process new content
  • Apps that receive regular updates from external accessories

And you must add to the Info.plist as follows: Add the UIBackgroundModes key to your Info.plist file and set its value to an array containing one or more of the following strings:

  • audio—The app plays audible content to the user while in the background. (This content includes streaming audio or video content using AirPlay.)
  • location—The app keeps users informed of their location, even while it is running in the background.
  • voip—The app provides the ability for the user to make phone calls using an Internet connection.
  • newsstand-content—The app is aNewsstand app that downloads and processesmagazine or newspaper content in the background.
  • external-accessory—The app works with a hardware accessory that needs to deliver updates on a regular schedule through the External Accessory framework.
  • bluetooth-central—The app works with a Bluetooth accessory that needs to deliver updates on a regular schedule through the CoreBluetooth framework

Note that part of the review process will be checking to make sure that your app does what it says it's doing with regard to background processing.

Mehul Thakkar
  • 12,440
  • 10
  • 52
  • 81
Brian Cooley
  • 11,622
  • 4
  • 40
  • 39
  • 4
    Note that just setting these types won't keep the app alive per se. For example: when you are playing audio, it will stay alive during the music. But when your song ends, the app can still be suspended. – Jelle Feb 05 '14 at 13:52
  • if i want to run an alaram , once the notification receives , how can i play a music , when the app is in background ?? this time duration can be more than 1 hour – Mr.G Jan 27 '16 at 12:34
  • @Mr.G: You've got the solution for your problem yet? – nghien_rbc Jul 25 '16 at 15:18
20

Here's what I've done using beginBackgroundTaskWithExpirationHandler.

  • Write a method that starts a background task.
  • Inside that background task, run a NSTimer with a scheduled (non repeating) time that is under 10 minutes. For the purposes of my situation I was using 5 minutes.
  • Once the NStimer's selector fires, end the background task and then instantly call the method that you wrote earlier to start off another background task.
  • If you want to schedule methods to run at specific times, you will have to check for them in the background task.

This solution isn't really ideal and is still power hungry but will do what you want.

Edit: Since iOS7, I suggest you read this excellent post. Note that this article was last updated in 2013 and is probably irrelevant now.

ingh.am
  • 25,981
  • 43
  • 130
  • 177
  • 2
    Did Apple approve this app for the App Store? – Hope4You Jan 01 '13 at 15:48
  • 1
    Yes. I dont know if this helped, but I released it as a "Power Saver" mode as an alternative to what we had already which ran GPS on all the time to keep the app alive in the background, but the user can now choose. Because of this I still kept the "GPS can dramatically decrease battery life" message they make you disclose. – ingh.am Jan 01 '13 at 18:39
  • I was originally going to use GPS to keep the app alive, but this method is better for me, because then I don't have to ask to use the person's location. Thank you so much for explaining your scenario. – Hope4You Jan 02 '13 at 14:50
  • No problem, that's true. Does the app still run in the background if they deny location access? I can't remember. To be honest, I don't think Apple will reject because of this technique, unless I slipped through! Let me know if they let it through! – ingh.am Jan 02 '13 at 15:22
  • I've wondered if doing something like this would work, nice to know it does. I'd be careful betting on it always being that way though -- Apple clearly wants apps to exit after 10 minutes unless they're performing specific tasks, so I wouldn't be surprised if they eventually fix this oversight. – John Stephen Feb 09 '13 at 03:12
  • Hi ing0. I'm looking at doing something similar to what you described above. Can you confirm that Apple has approved this technique in your app? It would be great to discuss this more with you if you are available over email. Thanks – Brian Boyle Feb 28 '13 at 12:16
  • Hey, I didn't explicitly tell Apple what I had done but I did explain we had developed a power saving mode. Feel free to email me at james@. – ingh.am Feb 28 '13 at 12:21
  • Did you have to denote the use of location services in the plist for this to work? – jjxtra Mar 21 '13 at 21:28
  • In my case, we did. But I don't think you have too as all I'm doing is running a background task, and then restarting the background task before the 10 minute expiry time is up. – ingh.am Mar 22 '13 at 10:05
  • I tried your approach, but first time background task runs properly, then after end background task if is run randomly. I put separate query for this,please have a look on http://stackoverflow.com/q/16182910/1119440 – Ramprasad Apr 24 '13 at 08:12
  • 8
    @ing0 update: I've tried several code combinations and can't seem to keep my app running in the background for an indefinite period of time (using this method). Do you have any working code? – Hope4You Sep 09 '13 at 15:53
  • @ing0: Hey man, can you post some code? Or pseudocode? I can't get this running in any way. I do have the background location updates mode set. I'm on iOS 7.1.1. Thanks! – Marcel N. Apr 24 '14 at 13:48
  • You might want to read this: http://gooddevbaddev.wordpress.com/2013/10/22/ios-7-running-location-based-apps-in-the-background/ Apparently the background grace period is now shorter (3 mins, not 10) and if your app is suspended in the bg, you cannot run a timer. In this post they do talk about changing the accuracy to achieve the same thing though. – ingh.am Apr 24 '14 at 14:22
  • I cannot seem to recreate or restart the background task. – SleepNot Jul 14 '14 at 09:21
  • Running iOS7? Read the article in the link in my previous comment. – ingh.am Jul 15 '14 at 15:45
  • @ing0 i have an alarm app , do you think i can use this process to run alarm in background, coz i want to run a long ruining process , i have put my question here , http://stackoverflow.com/questions/35054240/playing-alarm-tone-in-background-after-scheduling/35054522#35054522 – Mr.G Jan 28 '16 at 07:38
  • @ing0: Hi. I have similar situation in my app wherein I need to send a ping after every 20 secs while being in the background. Its a VOIP based app so I cannot use Location framework. When the app moves to background, it runs for 3-4 mins and then stops. I have almost done similar steps as you have mentioned. Please help me with some example codes. Thanks. – neha_sinha19 Jun 01 '16 at 12:32
  • @neha_sinha19 Since iOS7, what I said above doesn't apply. There is (sort of) a way of achieving the same effect but it requires using the Location background mode still. Sorry but I have no experience with VOIP apps. I assume you have read this: https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html - Does it still stop the background process when you have all your audio streaming stuff setup? I suspect that it shouldn't, although I have never tried to do anything like this. – ingh.am Jun 01 '16 at 14:43
  • @ing0: Thanks for your reply. No, it doesn't stop when audio stream is set up. Web Socket closes just after 3 mins after being in background. I assume its the background restriction though I feel that it has been increased from 180 sec to 600 sec. I am not sure what is causing it to close: an error in web socket or background limitations. – neha_sinha19 Jun 02 '16 at 06:02
  • @neha_sinha19 Have you added both the audio and voip values to the UIBackgroundModes key in info.plist? – ingh.am Jun 02 '16 at 10:08
  • @ing0: Yes. I added both of them. – neha_sinha19 Jun 03 '16 at 06:46
  • @ing0 : Please Help me : http://stackoverflow.com/questions/42266258/ios-9-beginbackgroundtaskwithexpirationhandler-is-getting-called-before-timout – Abhishek Thapliyal Feb 16 '17 at 10:52
  • 1
    @AbhishekThapliyal I have replied. It's been a while since I've done this, but I think my answer will help. – ingh.am Feb 16 '17 at 12:54
  • Could you please locate the lost "excellent post" you refer to? the link is dead. – Motti Shneor Dec 01 '19 at 16:49
  • @MottiShneor I have updated the link to a cached version of the article, but please note that it is quite old and probably not relevant anymore. – ingh.am Dec 05 '19 at 10:30
2

This code makes your iOS app run indefinitely in the background. Copy and paste the below methods into a singleton / manager which handles the tasks you need to perform in the background.

// @interface

// Declare Private property
@property (nonatomic) UIBackgroundTaskIdentifier backgroundTask;

//@end
// ...

// Copy into
//@implementation 

- (void)setupBackgrounding {
    [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(appBackgrounding:)
                                                 name: UIApplicationDidEnterBackgroundNotification
                                               object: nil];
    [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(appForegrounding:)
                                                 name: UIApplicationWillEnterForegroundNotification
                                               object: nil];
}

- (void)appBackgrounding: (NSNotification *)notification {
    [self keepAlive];
}

- (void) keepAlive {
    self.backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
        [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask];
        self.backgroundTask = UIBackgroundTaskInvalid;
        [self keepAlive];
    }];
}

- (void)appForegrounding: (NSNotification *)notification {
    if (self.backgroundTask != UIBackgroundTaskInvalid) {
        [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask];
        self.backgroundTask = UIBackgroundTaskInvalid;
    }
}
rismay
  • 271
  • 2
  • 8
2

Only certain types of apps are allowed to run in the background. See the "Implementing Long-Running Background Tasks" section of this guide.

If you aren't requesting permissions to do background processing you can use UIApplication's beginBackgroundTaskWithExpirationHandler but you cannot get extra time.

CJ Foley
  • 101
  • 4
1

https://github.com/yarodevuci/backgroundTask Check my code here I am using audio player that plays blank wav file Works perfectly on IOS 8 Battery usage around 10% in 24 hour period How to use:

var backgroundTask = BackgroundTask()
backgroundTask.startBackgroundTask() //Starts playing blank audio file. You can run NSTimer() or whatever you need and it will continue executing in the background.

backgroundTask.stopBackgroundTask() //Stops the task

Warning: Apple will reject this if you try to submit it!

Frederic Adda
  • 5,905
  • 4
  • 56
  • 71
Yaroslav Dukal
  • 3,894
  • 29
  • 36
1

You can't. Unless your app uses audio, voip or gps. What you can do is notify the user (via local notifications) that the time is almost up and ask him to open/close the app.

Also if you just need to notify the user, you can use push notifications.

fbernardo
  • 10,016
  • 3
  • 33
  • 46
0

If your App type is not one of VOIP/Audio/Location....(check Background Modes),

or you don't want to specify your App as a background App, you can implement beginBackgroundTaskWithName:expirationHandler or beginBackgroundTaskWithExpirationHandler to ask for more time to run your process in background. You can find the detailed description here

Apps moving to the background are expected to put themselves into a quiescent state as quickly as possible so that they can be suspended by the system. If your app is in the middle of a task and needs a little extra time to complete that task, it can call the beginBackgroundTaskWithName:expirationHandler: or beginBackgroundTaskWithExpirationHandler: method of the UIApplication object to request some additional execution time. Calling either of these methods delays the suspension of your app temporarily, giving it a little extra time to finish its work. Upon completion of that work, your app must call the endBackgroundTask: method to let the system know that it is finished and can be suspended.

Each call to the beginBackgroundTaskWithName:expirationHandler: or beginBackgroundTaskWithExpirationHandler: method generates a unique token to associate with the corresponding task. When your app completes a task, it must call the endBackgroundTask: method with the corresponding token to let the system know that the task is complete. Failure to call the endBackgroundTask: method for a background task will result in the termination of your app. If you provided an expiration handler when starting the task, the system calls that handler and gives you one last chance to end the task and avoid termination.

DàChún
  • 4,751
  • 1
  • 36
  • 39