By Vardhan


2012-08-22 11:06:35 8 Comments

In my app, I am uploading images to server from iPhone. While sync if user press home button, App will close.

I want app must be running in background till sync finish.

My question is: How can I add currently running task with "beginBackgroundTaskWithExpirationHandler"?

Please share your ideas.

6 comments

@Vardhan 2013-04-14 19:32:36

I used below code for background task handler:

__block UIBackgroundTaskIdentifier backgroundTaskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{

    NSLog(@"Background Time:%f",[[UIApplication sharedApplication] backgroundTimeRemaining]);

    [[UIApplication sharedApplication] endBackgroundTask:backgroundTaskIdentifier];

    backgroundTaskIdentifier = UIBackgroundTaskInvalid;
}];

@ozgur 2014-07-01 23:04:05

what does [self endBackgroundTask] method do? What is self?

@Vardhan 2014-12-16 07:50:37

@ozgurv : Updated code. thx

@BuvinJ 2015-06-09 13:46:32

Here's a slight variation on the other answers which I'm using when the app is going to the background and I need to do something on the main thread:

- (void)applicationWillResignActive:(UIApplication *)application
{
     UIApplication *app = [UIApplication sharedApplication];

    // Register auto expiring background task
    __block UIBackgroundTaskIdentifier bgTaskId =
        [app beginBackgroundTaskWithExpirationHandler:^{
        [app endBackgroundTask:bgTaskId];
        bgTaskId = UIBackgroundTaskInvalid;
    }];

    // Execute background task on the main thread
    dispatch_async( dispatch_get_main_queue(), ^{
        // ------------------
        // DO SOMETHING INVOLVING THE WEBVIEW - WHICH MUST OCCUR ON THE MAIN THREAD!
        // ------------------
        [app endBackgroundTask:bgTaskId];
        bgTaskId = UIBackgroundTaskInvalid;
    });
}

@user28434 2018-05-21 14:02:04

I know it's too late to ask, but why do you need to declare app local variable if the application is the parameter of applicationWillResignActive?

@BuvinJ 2018-05-21 14:10:23

Good question! Having, written this 3 years ago, I don't recall. It's very possible that's a mistake on my part. I'm certain the code works as posted, but you may be able to shave off that line. Please confirm this for us if you get the chance.

@Duyen-Hoa 2014-10-24 08:33:58

Take a look at this page, Apple describe how to keep iOS application not suspended while it is in background. Apple Documentation

And here is what I've implemented:

UIBackgroundTaskIdentifier bgTask;

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    NSLog(@"=== DID ENTER BACKGROUND ===");
    bgTask = [[UIApplication  sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
        NSLog(@"End of tolerate time. Application should be suspended now if we do not ask more 'tolerance'");
        // [self askToRunMoreBackgroundTask]; This code seems to be unnecessary. I'll verify it.
    }];

    if (bgTask == UIBackgroundTaskInvalid) {
        NSLog(@"This application does not support background mode");
    } else {
        //if application supports background mode, we'll see this log.
        NSLog(@"Application will continue to run in background");  
    }
}

/*

- (void)askToRunMoreBackgroundTask
{
    [[UIApplication sharedApplication] endBackgroundTask:bgTask];
    NSLog(@"restart background long-running task");
    bgTask = [[UIApplication  sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
        NSLog(@"End of tolerate time. Application should be suspended now if we do not ask more 'tolerance'");
        [self askToRunMoreBackgroundTask]; 
    }];

}

*/

- (void)applicationWillEnterForeground:(UIApplication *)application
{
    NSLog(@"=== GOING BACK FROM IDLE MODE ===");
    //it’s important to stop background task when we do not need it anymore
    [[UIApplication sharedApplication] endBackgroundTask:UIBackgroundTaskInvalid];  
}

@Joe M 2013-12-10 10:48:08

Here's how I used beginBackgroundTaskWithExpirationHandler, including the call to the method to be done in the background. This includes code for starting the new async task. So not exactly what is asked in the question. Adding code below, thinking someone might be looking for this scenario:

- (void)didReceiveObjList:(CFDataRef)message
{
  // Received Object List. Processing the list can take a few seconds.
  // So doing it in separate thread with expiration handler to ensure it gets some time to do     the task even if the app goes to background.

  UIApplication *application = [UIApplication sharedApplication];
  __block UIBackgroundTaskIdentifier bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
    [application endBackgroundTask:bgTask];
    bgTask = UIBackgroundTaskInvalid;
}];

  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
      [self processObjList:message];

    [application endBackgroundTask:bgTask];
    bgTask = UIBackgroundTaskInvalid;
  });

  NSLog(@"Main Thread proceeding...");

}

@Rob Napier 2012-08-22 14:02:17

Despite its name, beginBackgroundTaskWithExpirationHandler: does not actually "begin" a task. It might be better thought of as "register..." rather than "begin...." You're just telling the system that you're in the middle of doing something that would like to complete if that's ok.

Several points:

  • In almost all cases, you want to call beginBackgroundTaskWithExpirationHandler: when you start doing the thing you want to do, and then endBackgroundTask: when you're done. You almost never call these at the point that the user presses the Home button (unless that's the point when you start the task, such as saving something to the server).

  • You can have as many "background tasks" as you want open at a time. They cost nothing. They're like retain counts. As long as you still have one open (a "begin" that did not get to its "end"), then the system will consider that a request for more time. There is very little cost to calling the "begin" and "end" methods, so use these to bracket anything that you want extra time to finish.

  • There is no way to be certain that you will get to finish your sync. These methods just make a request. The OS may still deny that request. The OS may still kill you anytime it needs some extra resources. The OS is not infinitely patient; if you take too long (about 10 minutes usually), it'll kill you anyway after calling your expiration handler. The OS may kill you because the phone is being turned off. Your app must be able to deal with not getting to finish. The OS just gives you this ability so that you can improve the user experience.

@n0_quarter 2015-02-24 09:13:13

Your answer is completely awesome, thanx man. Just one update: since iOS 7 you have only 3 minutes for background tasks, not 10 anymore.

@theFool 2016-10-24 06:43:28

is it advisable to use beginBackgroundTaskWithExpirationHandler with scanning bluetooth devices on app background?

@Rob Napier 2016-10-24 12:55:34

Bluetooth background scanning is generally better done by registering with the background mode bluetooth-central. Scanning generally doesn't fall in the "just need a little more time to finish this" camp.

@Honey 2017-07-19 16:50:21

Other than writing your backgroundTasks inside the applicationDidEnterBackground is there any other place where you might want to right them? I can understand the syntax. Just can't understand how you'd know "oh no! The task isn't finished yet" and where you'll need to put it all together.

@Honey 2017-07-19 18:15:03

or is that you you just wrap any important download inside a backgroundTask? Later if the app ever went to background you'd still be able to download in the background and if it didn't go background it would just download it as a normal download?

@Rob Napier 2017-07-19 18:31:30

The latter. Always wrap any operation that you would want to continue in the background if necessary in an beginBackgroundTaskWithExpirationHandler block. That said, you should rarely need to do that for downloading. URLSession's background sessions are much more powerful.

@Honey 2017-07-19 20:19:12

Thank you so much! Why not just use background sessions for every task? Is there any overhead? The only diff I can see is that for observing the downloads you can't use completionHandlers and you must use delegates. Not sure how much of a difference that would make

@Rob Napier 2017-07-19 20:43:36

For regular REST calls, background sessions are much less convenient, and generally not what you'd want. They're not a general purpose tool for every request; they're for performing uploads and downloads.

@Honey 2017-07-20 15:50:01

@RobNapier Thanks. I already deviated too much. So I asked a new question about why it's less convenient?.

@Honey 2017-08-02 21:58:17

Took me a while to figure this out. IMHO "then the system will consider that a request for more time" is misleading. That is: You're implying: if you have 2 backgroundTasks you get 2 * 180 seconds, but that's just incorrect. It means that if you have a background task backgroundTask1 started at second 0 and backgroundTask2 at second 140 and then backgroundTask1 finishes at 160...your backgroundTask2 will still have to end at 180. It won't be allowed to expand the remainingTime to end at 140 + 160... 180 is ALL you get.

@Amit Thakur 2019-03-25 10:16:02

@RobNapier, thanks for the answer, can you tell me is it necessary to call method endbackgroundtask

@Rob Napier 2019-03-25 13:05:01

@AmitThakur Yes. Every begin is required to be balanced with an end.

@Amit Thakur 2019-03-26 14:05:48

@RobNapier. Thanks again for your reply, actually what issue I am facing is, if any API is getting called and putting the app in background mode, the API got successfully called and it also don't kill the app, but let suppose at login screen I put the app in the background mode and after few minutes I getting the app in foreground mode, I don't see the login screen, the app starts from splash screen.

@Rob Napier 2019-03-26 14:08:08

yeah, if you don't call "end" when you're supposed to, the app will be killed and will relaunch fresh. If you're having trouble, you should open a new question with details about what you are doing, what you expect to happen, and what does happen.

@tikhop 2012-08-22 11:22:36

You should run your task after beginBackgroundTaskWithExpirationHandler or capture notification when the application change app's state to background and then cancel your current task and run again with beginBackgroundTaskWithExpirationHandler.

Related Questions

Sponsored Content

40 Answered Questions

[SOLVED] How can I develop for iPhone using a Windows development machine?

  • 2008-08-22 13:35:01
  • ryan
  • 1098095 View
  • 1153 Score
  • 40 Answer
  • Tags:   ios iphone windows

15 Answered Questions

2 Answered Questions

[SOLVED] Standard iPhone app that runs as a background service, jail-broken or not

  • 2012-07-01 20:23:41
  • Junba Tester
  • 115 View
  • -3 Score
  • 2 Answer
  • Tags:   iphone ios

3 Answered Questions

[SOLVED] Application close notification in iphone when press home button twice

  • 2012-06-20 10:17:23
  • Manisha Khare
  • 4113 View
  • 2 Score
  • 3 Answer
  • Tags:   iphone ios ios5

1 Answered Questions

UIBackgroundModes, Logging out on temporary (or permanent) exit

1 Answered Questions

[SOLVED] beginBackgroundTaskWithExpirationHandler, downloading data from server

  • 2012-03-09 19:48:32
  • Crystal
  • 934 View
  • 1 Score
  • 1 Answer
  • Tags:   iphone

2 Answered Questions

[SOLVED] How to save state of app on application exit

1 Answered Questions

How to let download file keep running after Home button pressed on iphone

  • 2011-09-19 09:46:33
  • bandw
  • 231 View
  • 0 Score
  • 1 Answer
  • Tags:   iphone ios4 ios5

2 Answered Questions

[SOLVED] Running application in background like google latitude

2 Answered Questions

[SOLVED] How to terminate process when home button is pressed?

  • 2010-11-21 09:22:15
  • user510951
  • 1394 View
  • 0 Score
  • 2 Answer
  • Tags:   iphone ipad ios

Sponsored Content