首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >定期更新iOS后台位置

定期更新iOS后台位置
EN

Stack Overflow用户
提问于 2013-09-27 12:44:30
回答 9查看 96.6K关注 0票数 93

我正在写一个应用程序,需要与高精度和低频率的后台位置更新。解决方案似乎是一个后台NSTimer任务,它启动位置管理器的更新,然后立即关闭。这个问题以前已经问过了:

How do I get a background location update every n minutes in my iOS application?

Getting user location every n minutes after app goes to background

iOS Not the typical background location tracking timer issue

iOS long-running background timer with "location" background mode

iOS full-time background-service based on location tracking

但是我还没有得到一个可以正常工作的最小示例。在尝试了上述公认答案的每一种排列之后,我将一个起点放在一起。进入背景:

代码语言:javascript
复制
- (void)applicationDidEnterBackground:(UIApplication *)application
{
    self.bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
        NSLog(@"ending background task");
        [[UIApplication sharedApplication] endBackgroundTask:self.bgTask];
        self.bgTask = UIBackgroundTaskInvalid;
    }];


    self.timer = [NSTimer scheduledTimerWithTimeInterval:60
                                                  target:self.locationManager
                                                selector:@selector(startUpdatingLocation)
                                                userInfo:nil
                                                 repeats:YES];
}

和委托方法:

代码语言:javascript
复制
- (void)locationManager:(CLLocationManager *)manager 
    didUpdateToLocation:(CLLocation *)newLocation 
           fromLocation:(CLLocation *)oldLocation {

    NSLog(@"%@", newLocation);

    NSLog(@"background time: %f", [UIApplication sharedApplication].backgroundTimeRemaining);
    [self.locationManager stopUpdatingLocation];

}

当前的行为是backgroundTimeRemaining从180秒递减到零(在记录位置时),然后执行过期处理程序,并且不会生成进一步的位置更新。如何修改上面的代码,以便在后台无限期地接收定期位置更新

更新:我的目标是iOS 7,似乎有一些证据表明后台任务的行为有所不同:

Start Location Manager in iOS 7 from background task

EN

回答 9

Stack Overflow用户

回答已采纳

发布于 2013-09-30 10:13:54

似乎是stopUpdatingLocation触发了后台看门狗计时器,所以我在didUpdateLocation中将其替换为:

代码语言:javascript
复制
[self.locationManager setDesiredAccuracy:kCLLocationAccuracyThreeKilometers];
[self.locationManager setDistanceFilter:99999];

这似乎有效地切断了GPS的电源。然后,后台NSTimer的选择器变为:

代码语言:javascript
复制
- (void) changeAccuracy {
    [self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
    [self.locationManager setDistanceFilter:kCLDistanceFilterNone];
}

我所做的就是定期切换精度,每隔几分钟获得一个高精度的坐标,因为locationManager没有停止,所以backgroundTimeRemaining保持在它的最大值。在我的设备上,这将电池消耗从每小时约10%(后台使用恒定的kCLLocationAccuracyBest )降低到每小时约2%。

票数 62
EN

Stack Overflow用户

发布于 2014-07-10 10:18:06

我写了一个使用定位服务的应用程序,应用程序必须每10秒发送一次位置。它运行得非常好。

只需使用"allowDeferredLocationUpdatesUntilTraveled:timeout“方法,遵循苹果的文档。

具体步骤如下:

需要:更新位置的注册后台模式。

1.创建LocationManger和startUpdatingLocation,并根据需要使用accuracy和filteredDistance:

代码语言:javascript
复制
-(void) initLocationManager    
{
    // Create the manager object
    self.locationManager = [[[CLLocationManager alloc] init] autorelease];
    _locationManager.delegate = self;
    // This is the most important property to set for the manager. It ultimately determines how the manager will
    // attempt to acquire location and thus, the amount of power that will be consumed.
    _locationManager.desiredAccuracy = 45;
    _locationManager.distanceFilter = 100;
    // Once configured, the location manager must be "started".
    [_locationManager startUpdatingLocation];
}

2.为了让后台使用"allowDeferredLocationUpdatesUntilTraveled:timeout“方法的应用永远运行,必须在应用移到后台时使用新参数重启updatingLocation,如下所示:

代码语言:javascript
复制
- (void)applicationWillResignActive:(UIApplication *)application {
     _isBackgroundMode = YES;

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

3.应用程序通过"locationManager:didUpdateLocations:“updatedLocations获取回调:

代码语言:javascript
复制
-(void) locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
//  store data
    CLLocation *newLocation = [locations lastObject];
    self.userLocation = newLocation;

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

4.回调,但您应该根据自己的目的在中处理数据

代码语言:javascript
复制
- (void) locationManager:(CLLocationManager *)manager didFinishDeferredUpdatesWithError:(NSError *)error {

     _deferringUpdates = NO;

     //do something 
}

5. 注意:我认为每次应用程序在后台/前台模式之间切换时,我们都应该重置LocationManager的参数。

票数 46
EN

Stack Overflow用户

发布于 2013-09-27 21:02:26

  1. 如果你的plist中有UIBackgroundModeslocation键,那么你就不需要使用beginBackgroundTaskWithExpirationHandler方法。这是多余的。你也没有正确地使用它(参见here),但这是没有意义的,因为你的plist已经设置好了。在plist中有UIBackgroundModes location
  2. 只有在CLLocationManger运行的时候,应用程序才会无限期地在后台运行。如果你在后台调用stopUpdatingLocation,那么应用程序将会停止并且不会再次启动。

也许你可以在调用stopUpdatingLocation之前调用beginBackgroundTaskWithExpirationHandler,然后在调用startUpdatingLocation之后,你可以调用endBackgroundTask来在GPS停止时保持它的后台,但我从来没有尝试过--这只是一个想法。

另一个选择(我还没有尝试过)是在后台保持位置管理器运行,但是一旦你得到一个准确的位置,将desiredAccuracy属性更改为1000m或更高,以允许关闭GPS芯片(以节省电池)。然后10分钟后,当你需要再次更新位置时,将desiredAccuracy调回100m以打开定位系统,直到你得到准确的位置,重复一次。

  • 当你在位置管理器上调用startUpdatingLocation时,你必须给它时间来获得一个位置。您不应该立即调用stopUpdatingLocation。我们让它运行最多10秒,或者直到我们得到一个非缓存的高精度location.

  • You,我们需要过滤出缓存的位置,并检查您获得的位置的准确性,以确保它满足您的最低要求精度(请参阅here)。你得到的第一个更新可能是10分钟或10天前的。你得到的第一个精度可能是3000米。

  • 考虑使用重要的位置更改API。一旦你得到重要的变化通知,你可以启动CLLocationManager几秒钟来获得一个高精度的位置。我不确定,我从来没有使用过重要的位置改变服务。
票数 39
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19042894

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档