0

I am writing a code to constantly track the user applying CoreLocation. Since I cannot keep the GPS on all the time, I use StartMonitoringSignificantLocationChange in my AppDelegate to detect a significant change. I have registered for location in the UIBackgroundMode. in didUpdateLocations method, I check the current distance from the previously recorded location. If it is significant, I apply StopMonitoringSignificantLocationChange and StartUpdatingLocation to get accurate locations. Meanwhile I initiate a timer (30 secs) to see whether the user is stationary or moving. If the user is not moving anymore, I apply StopUpdatingLocation and StartMonitoringSignificantLocationChange again. I have also defined a background task in my AppDelegate: -(void)applicationWillResignActive:(UIApplication *)application as follows:

- (void)applicationWillResignActive:(UIApplication *)application
{
    if (![[GeoSampleManager sharedManager] isLiveTracking])
    {
        GeoSampleManager *manager = [HTSGeoSampleManager sharedManager];

        [manager.locationManager stopMonitoringSignificantLocationChanges];

        self.bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
        [application endBackgroundTask:self.bgTask];
            self.bgTask = UIBackgroundTaskInvalid;
        }];

        [manager.locationManager startMonitoringSignificantLocationChanges];
    }
}

I close the background task when the app eneters foreground:

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    if(self.bgTask != UIBackgroundTaskInvalid)
    {
        [[UIApplication sharedApplication] endBackgroundTask:self.bgTask];
        self.bgTask = UIBackgroundTaskInvalid;
    }
}

And here is my didUpdateLocations method:

- (void)locationManager:(CLLocationManager *)manager
 didUpdateLocations:(NSArray *)locations
{
    CLLocation* newLocation = [locations lastObject];

    if(self.isLiveTracking)
    {
        //Test that the horizontal accuracy does not indicate an invalid measurement
        if (newLocation.horizontalAccuracy < 0 || newLocation.horizontalAccuracy > 200)
        {
            return;
        }

        if([self.lastLocation distanceFromLocation:newLocation] > 0)
        {
            //Create and save a GeoSample
            [GeoSampleManager createSampleForLocation:newLocation onTrip:self.activeTrip];

            self.lastLocation = newLocation;
        }
    }
    else
    {
        if([self.lastLocation distanceFromLocation:newLocation] > 0)
        {
            [self.locationManager stopMonitoringSignificantLocationChanges];
    self.idleChecker = [NSTimer scheduledTimerWithTimeInterval:30 target:self selector:@selector(checkIdle:) userInfo:nil repeats:YES];

    [self.locationManager startUpdatingLocation];
            self.isLiveTracking = YES;
        }
    }
}

And finally here is the timer method:

- (void)checkIdle:(NSTimer*)timer
{
    if(abs([self.lastLocation.timestamp timeIntervalSinceNow]) >= 30.0)
    {
        //Stopping the idle-time checking timer
    [self.idleChecker invalidate];
    self.idleChecker = nil;

    [self.locationManager stopUpdatingLocation];
    [self.locationManager startMonitoringSignificantLocationChanges];
        self.isLiveTracking = NO;
    }
}

However, the app is suspended (sometimes after 5-10 secs, sometimes after 10 mins) and stops receiving location updates.Since I am struggling with this problem for more than a month and I have tried almost all possible solution, I really appreciate if you can help me to solve the issue in any way.

Cheers

Behrang
  • 1
  • 1
  • Do you ever remove the app from the App Switcher? – sangony Feb 14 '14 at 01:40
  • No, It is just sent to the background when I lock the screen. – Behrang Feb 14 '14 at 01:56
  • Take a look at this previous post. It might give you an idea (look at ALL the answers). http://stackoverflow.com/questions/18946881/background-location-services-not-working-in-ios-7 – sangony Feb 14 '14 at 01:59
  • 1
    Thank you @sangony! I have tried almost all of the suggested solutions. Now, I found this question: http://stackoverflow.com/questions/18901583/start-location-manager-in-ios-7-from-background-task/19043587#19043587 and I am trying to use the solution suggested by @sash to see whether it solves the problem or not. – Behrang Feb 14 '14 at 02:28
  • I hope it works. If not, keep searching StackOverflow and I am sure you will find something to put you on the right track. Good luck. – sangony Feb 14 '14 at 02:43

1 Answers1

2
  • Backgrounding tasks will die after 10 minutes unless the correct multitasking mode is set (such as a navigation app) in which case you need to keep the GPS on.
  • You will have to keep the GPS on or play a sound in the background. You say you cannot keep the GPS on all the time, but if this is the case then what you are seeing is likely the expected behavior (or i misread something).
  • Refer to the different CLLocationAccuracy constants available:

Available at: https://developer.apple.com/library/ios/documentation/CoreLocation/Reference/CoreLocationConstantsRef/Reference/reference.html#//apple_ref/c/data/kCLLocationAccuracyKilometer

extern const CLLocationAccuracy kCLLocationAccuracyBestForNavigation;
extern const CLLocationAccuracy kCLLocationAccuracyBest;
extern const CLLocationAccuracy kCLLocationAccuracyNearestTenMeters;
extern const CLLocationAccuracy kCLLocationAccuracyHundredMeters;
extern const CLLocationAccuracy kCLLocationAccuracyKilometer;
extern const CLLocationAccuracy kCLLocationAccuracyThreeKilometers;

At the very least this "may" help manage your GPS battery consumption if you do keep it running all the time.

Jeef
  • 26,861
  • 21
  • 78
  • 156
  • Thank you for your comments @jeef. Because of the battery consumption, I cannot keep the GPS on and thus, I turn it off when the user does not move for 30 secs. However, I use `StartMonitoringSignificantLocationChange` to check the GSM/WIFI signals and detect user's movements. Just in case the user moves, I turn on the GPS again. It seems switching between GPS(`StartUpdatingLocation`) and GSM/WIFI (`StartMonitoringSignificantLocationChanges`) does not work in the background mode. – Behrang Feb 14 '14 at 01:30
  • @Behrang Significant often means a chnage of 1000m (next GSm cell) , is that what you want? – AlexWien Feb 14 '14 at 17:28
  • Look here for the different modes: This (might) help but not directly perhaps with what you want to do -- https://developer.apple.com/library/ios/documentation/CoreLocation/Reference/CoreLocationConstantsRef/Reference/reference.html#//apple_ref/c/data/kCLLocationAccuracyBestForNavigation – Jeef Feb 14 '14 at 17:59
  • @AlexWien, yes! If I detect a significant location change, then I need to start recording the user's accurate path by turning on the GPS. – Behrang Feb 18 '14 at 03:50