0

I am trying to enable background location mode in my application. I have enabled 'Location updates' background mode in my plist file. The app contains a timer that is updating every 15 seconds.

When the app is navigating to background, I am doing the following

- (void)applicationDidEnterBackground:(UIApplication *)application {
UIApplication*    app = [UIApplication sharedApplication];
self.bgTaskID = [app beginBackgroundTaskWithExpirationHandler:^{
        NSLog(@"background task %lu expired", (unsigned long)self.bgTaskID);
        [app endBackgroundTask:self.bgTaskID];
        self.bgTaskID = UIBackgroundTaskInvalid;
}];


 [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(initializeLocationManager) userInfo:nil repeats:NO];

            if(self.timerLocationBackground)
            {
                [self.timerLocationBackground invalidate];
                self.timerLocationBackground = nil;
            }
            self.timerLocationBackground = [NSTimer scheduledTimerWithTimeInterval:15
                                                                            target:self
                                                                          selector:@selector(initializeLocationManager)
                                                                          userInfo:nil
                                                                           repeats:YES];}`

The initializeLocationManager is below

  -(void)initializeLocationManager
{
    if(!self.locationManager)
        self.locationManager = [[CLLocationManager alloc] init];
    else
        [self.locationManager stopUpdatingLocation];

    if ((![CLLocationManager locationServicesEnabled])
        || ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusRestricted)
        || ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied))
    {
        //user has disabled his location
    }
    else
    {
        self.locationManager.delegate = self;
        self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
        self.locationManager.distanceFilter = kCLDistanceFilterNone;
        [self.locationManager setAllowsBackgroundLocationUpdates:YES];
        [self.locationManager startUpdatingLocation];
    }
}

When I navigate back to the application after 10 minutes for ex, my timer is being stopped at 3 min which is the time for the app to be suspended.

My code when the app get back to foreground is the below:

- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.

//
//Remove the baground task
//
if (self.bgTaskID != UIBackgroundTaskInvalid) {
    [[UIApplication sharedApplication] endBackgroundTask:self.bgTaskID];
    self.bgTaskID = UIBackgroundTaskInvalid;
}
[self.locationManager stopUpdatingLocation];

Any help?

Iphone User
  • 1,930
  • 2
  • 17
  • 26
  • Can you post the code where you set self.bgTaskID ? – rjpadula Oct 26 '16 at 17:33
  • @rjpadula Updated, please check, it is set the first line in the didenterbackground method – Iphone User Oct 26 '16 at 17:38
  • Are you able to see if your "background task %lu expired" message is showing? It's likely that you need to renew your background task. In my experience, three minutes is about how long you get until you need to. – rjpadula Oct 26 '16 at 18:08
  • @rjpadula How can i renew it? isn't supposed that the location retrieval keeps the app awake? – Iphone User Oct 26 '16 at 18:13

1 Answers1

0

Should be something like this. I've switched over to swift myself, so my objective-c might not be perfect.

- (void)applicationDidEnterBackground:(UIApplication *)application {

    [self keepAwakeInBackground ] ; 

    /// rest of your function to set up timers
}

- (void) keepAwakeInBackground {

    //Remove the old background task, if there was one
    if (self.bgTaskID != UIBackgroundTaskInvalid) {
        [[UIApplication sharedApplication] endBackgroundTask:self.bgTaskID];
        self.bgTaskID = UIBackgroundTaskInvalid;
    }
    /*
     *  You probably want something here to decide that the app should really be suspended here
     *  if ( ) return
     */

    // Set up new background task 
    UIApplication*    app = [UIApplication sharedApplication];
    self.bgTaskID = [app beginBackgroundTaskWithExpirationHandler:^{
        [self keepAwakeInBackground] 
    }];
}
rjpadula
  • 944
  • 7
  • 7
  • I have tried to remove the old background task, if there was one (I think it is the only change from your part), but I still got the timer suspended after 3 minutes when i go back to foreground. I am getting desperate about this issue! – Iphone User Oct 26 '16 at 19:22
  • The change I've made makes it so that the expiration handler will create a new background task when the first expires (which is the 3 minutes you are seeing). Sorry about posting it wrong. – rjpadula Oct 26 '16 at 19:52
  • I have tried the above code but still didn't work, I guess when you call the method keepAwakeInBackground when the background task is finished, and the self.bgTaskID = UIBackgroundTaskInvalid; is being performed, then the app is set automatically to the suspended state without continuing to the new task. – Iphone User Oct 26 '16 at 21:16
  • The location updates that i am getting and setting the background mode location enabled shouldn't be enough to keep the app alive?? I can't understand what is wrong – Iphone User Oct 26 '16 at 21:18
  • keepAwakeInBackground should be getting called "before time expires" according to [Apple's Docs](https://developer.apple.com/reference/uikit/uiapplication/1623031-beginbackgroundtaskwithexpiratio) The method is then expiring the old task and starting a new one, which should keep the app alive (and is working for me). I don't see why this isn't working for you. I got a lot of help from [this thread](http://stackoverflow.com/questions/12071726/how-to-use-beginbackgroundtaskwithexpirationhandler-for-already-running-task-in) – rjpadula Oct 27 '16 at 15:19
  • What are you doing to know that the is still alive in your case? did you try to set a timer on the screen? can you please send me your sample example? – Iphone User Oct 28 '16 at 09:27
  • I'm writing into a log file. I've looked at my log files, and I have discovered that in some cases my app stays running, but in others it stops after the first task expires. I'm trying to determine what might be the difference. – rjpadula Oct 31 '16 at 14:36
  • Hello exactly, i have discovered the same, the app is suspended after the first task expires, but when I re enter the app in the background for a second time then it keeps running. I still don't understand why! HELP! – Iphone User Oct 31 '16 at 15:17
  • No, I haven't found anything new. – rjpadula Nov 07 '16 at 17:34
  • What i found today is the following, if i start retrieving locations updates one the app is launched, the the app keeps running in background. but in case i start retrieving locations once the app is sent to background then most of the times the app is being suspended after 3 min! I am not sure if i must use the above since it will takes lot of the battery as i suppose. – Iphone User Nov 08 '16 at 14:27