MSU_Bulldog
MSU_Bulldog

Reputation: 3519

iOS: Decrease frequency of background location updates

I am doing background location tracking in an app and it is firing way too often. I'm not sure what is the best technique for setting a minimum time interval for updating location. I only want to save location data every 2 minutes or so. Some have said to use an NSTimer but I'm not sure how or where to incorporate that in my current code. Below is all of my location tracking code in AppDelegate, does anyone know the best technique for decreasing the frequency of location updates given my current code?

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
{
    isBackgroundMode = NO;
    _deferringUpdates = NO;

    self.locationManager = [CLLocationManager new];
    [self.locationManager setDelegate:self];
    if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
        [self.locationManager requestAlwaysAuthorization];
    }
    [self.locationManager startUpdatingLocation];
    [self.locationManager startMonitoringSignificantLocationChanges];
    [self initializeRegionMonitoring];
}


-(void) initializeRegionMonitoring {
    self.locationManager = [[CLLocationManager alloc] init];
    self.locationManager.delegate = self;

    // notify changes when the device has moved x meters
    self.locationManager.distanceFilter = 10;
    self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    [self.locationManager startUpdatingLocation];
    [self.locationManager startMonitoringSignificantLocationChanges];
}

// Delegate method from the CLLocationManagerDelegate protocol.
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
    [self saveLocation];

    //tell the centralManager that you want to deferred this updatedLocation
    if (isBackgroundMode && !_deferringUpdates)
    {
        _deferringUpdates = YES;
        [self.locationManager allowDeferredLocationUpdatesUntilTraveled:CLLocationDistanceMax timeout:60];
    }

}

- (void) locationManager:(CLLocationManager *)manager didFinishDeferredUpdatesWithError:(NSError *)error {

    _deferringUpdates = NO;    
}


-(void) saveLocation {
    // save information database/ communication with web service
}

- (void)applicationWillResignActive:(UIApplication *)application {
    isBackgroundMode = YES;

    [self.locationManager stopUpdatingLocation];
    [self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
    [self.locationManager setDistanceFilter:kCLDistanceFilterNone];
    self.locationManager.pausesLocationUpdatesAutomatically = NO;
    self.locationManager.activityType = CLActivityTypeAutomotiveNavigation;
    [self.locationManager startUpdatingLocation];
}


-(BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];
    return true;
}

-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {

    [self saveLocation];

    completionHandler(UIBackgroundFetchResultNewData);
    NSLog(@"Fetch completed");
}

Also since a lot of what I am doing is compile from various tutorials, please feel free to point out anything I am doing incorrectly in terms of performance or battery usage. Thanks!

Upvotes: 1

Views: 892

Answers (4)

Himanshu Bhatia
Himanshu Bhatia

Reputation: 31

  1. Start the service when user Moves and stop the service when location. Accuracy is less than locatonManager's Accuracy.
  2. Location manager should be paused automatically & try to use resume locations delegate.

  3. Check time of last location and new location.

  4. This will reduce some battery.

Upvotes: 0

P.J.Radadiya
P.J.Radadiya

Reputation: 1541

self.locationManager.distanceFilter = 10;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest; 
[self.locationManager startUpdatingLocation];

Try This....!!

Upvotes: -1

Rajat
Rajat

Reputation: 11127

As you have declared in your

-(void) initializeRegionMonitoring

the value of distance filter to 10

self.locationManager.distanceFilter = 10;

Therefore, after user move to 10 meters, your didUpdateLocations will be called,

If you want to minimize the call of this delegate method, then you have to increase the value of distanceFilter.

Upvotes: 1

Peter Branforn
Peter Branforn

Reputation: 1677

In other (open source) projects I have seen the following strategies to save power:

  • Reduce the requested accuracy (setDesiredAccuracy) very big (not "kCLLocationAccuracyBest", but actually "kCLLocationAccuracyKilometer")
  • Reduce the callback "didUpdateLocations:" count by setting a large threshold in "distanceFilter"
  • Return from callback if writes are not needed (with other criteria such as time)

Any way I do not see the need for an extra timer here. What you want to do is start with a rough accuracy (if you can!) and additionally set your distanceFilter to a high value (more than 10 meters for example).

What you can do additionally is this: in your "didUpdateLocations:" callback, let the "saveLocation" only be called if "lastSaveTime" is more than 5 minutes ago if(lastSaveTime + 5 < thisSaveTime) { ... } assuming time measured in seconds.

Upvotes: 4

Related Questions