iOS: уменьшение частоты фоновых обновлений местоположения

Я делаю фоновое отслеживание местоположения в приложении, и оно запускается слишком часто. Я не уверен, что является лучшим методом для установки минимального интервала времени для обновления местоположения. Я хочу сохранять данные о местоположении каждые 2 минуты или около того. Некоторые говорят, что используют NSTimer, но я не уверен, как и где включить это в мой текущий код. Ниже приведен весь мой код отслеживания местоположения в AppDelegate. Кто-нибудь знает лучшую технику для уменьшения частоты обновлений местоположения, учитывая мой текущий код?

- (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");
}

Кроме того, поскольку многое из того, что я делаю, компилируется из различных руководств, пожалуйста, не стесняйтесь указывать на все, что я делаю неправильно, с точки зрения производительности или использования батареи. Спасибо!

4 ответа

Решение

В других (с открытым исходным кодом) проектах я видел следующие стратегии для экономии энергии:

  • Уменьшите запрошенную точность (setDesiredAccuracy) очень большой (не "kCLLocationAccuracyBest", а фактически "kCLLocationAccuracyKilometer")
  • Уменьшите счетчик обратных вызовов "didUpdateLocations:", установив большой порог в "distanceFilter"
  • Возврат из обратного вызова, если запись не нужна (с другими критериями, такими как время)

В любом случае я не вижу необходимости в дополнительном таймере здесь. То, что вы хотите сделать, это начать с грубой точности (если вы можете!) И дополнительно установить для своего distanceFilter высокое значение (например, более 10 метров).

Кроме того, вы можете сделать следующее: в вашем обратном вызове didUpdateLocations: вызывать saveLocation, только если lastSaveTime более 5 минут назад if(lastSaveTime + 5 < thisSaveTime) { ... } при условии, что время измеряется в секундах.

Как вы заявили в своем

-(void) initializeRegionMonitoring

Значение расстояния фильтра до 10

self.locationManager.distanceFilter = 10;

Поэтому после того, как пользователь переместится на 10 метров, ваш didUpdateLocations будет называться,

Если вы хотите минимизировать вызов этого метода делегата, вам нужно увеличить значение distanceFilter,

  1. Запустите службу, когда пользователь перемещает, и остановите службу, когда местоположение. Точность меньше, чем Точность locatonManager.
  2. Менеджер местоположений должен быть автоматически приостановлен и попытаться использовать делегат резюме местоположений.

  3. Проверьте время последнего местоположения и нового местоположения.

  4. Это уменьшит батарею.

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

Попробуй это....!!

Другие вопросы по тегам