位置更新在后台和暂停的应用程序模式

我想写的应用程序,每5分钟发送到服务器的低精度位置为它的两种模式:前景和背景。 因为我不想减less电池充电,并且位置信号变化只给出高精度值,所以我每5分钟就从GPS开始/停止位置更新。 应用程序从前台模式工作正常,但从后台模式只工作约1小时(并停止发送位置后)。 我想我在backgroundTask / NSTimer代码丢失的东西,因为我是新的iOS。 我会非常感谢你的帮助。 该应用程序将只适用于iOS 7及以上。

一般来说,我的algorithm如下:

** start backGroundTask ** [_locationManager startUpdatingLocation] ** handle received location in "didUpdateLocations:" listener ** [_locationManager stopUpdatingLocation] ** create new thread and fire the NSTimer with delay 5 min ** end backGroundTask 

这是我的代码:

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [self startLocationManager]; // .. other init app code } - (void) startLocationManager { _locationManager = [[CLLocationManager alloc] init]; _locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters; _locationManager.distanceFilter = 10; _locationManager.delegate = self; _locationManager.pausesLocationUpdatesAutomatically = NO; [_locationManager startLocation]; } - (void) startLocation { UIApplication * app = [UIApplication sharedApplication]; self.bkgdTask = [app beginBackgroundTaskWithExpirationHandler:^{ }]; [self.locationManager startUpdatingLocation]; } - (void) stopUpdatingLocation { [_locationManager stopUpdatingLocation]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ self.locationNextTimer = [NSTimer scheduledTimerWithTimeInterval:5 * 60 target:self selector:@selector(startLocation) userInfo:nil repeats:NO]; [[NSRunLoop currentRunLoop] addTimer:self.locationNextTimer forMode:NSDefaultRunLoopMode]; [[NSRunLoop currentRunLoop] run]; [app endBackgroundTask:self.bkgdTask]; self.bkgdTask = UIBackgroundTaskInvalid; }); } - (void) locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { [self.locationNextTimer invalidate]; self.locationNextTimer = nil; //ToDo Location Handling [self stopUpdatingLocation]; } 

编辑:

正如我从iOS7的理解,苹果希望locationManager的startUpdatingLocation只能从前台完成。 那么有什么解决这个问题的想法? 我也尝试了另外的解决scheme:用NSTimer停止/ startUpdatingLocation,用NSTimer改变大/小值的精度和distanceFilter。 它没有工作,因为我在“didUpdateLocations:”监听器中接收4次“高速公路驱动器”的触发器而不是一次。

位置pipe理员将根据您的设置自行决定最less的活动。 根据您的用例设置适当的参数,然后在您的代表中负责任地行事。 testing收到的地点,如果他们太近,那么你什么都不做。 这将允许您的应用程序处理,以尽可能less的影响电池。

significantLocationChanges是为了减less影响,而且根据我的经验,它做得相当不错。 另一种select是使用区域监视来代替或一起使用。

您可以根据您希望达到的准确性,通过创build大小的区域来进一步限制活动。 更新地区和保存位置只有边界越过。 这可能会更适合您的需求。

要在应用程序处于后台时获取位置更新与应用程序暂停时的位置更新是非常不同的情况。 你将不得不以不同的方式处理它们。

获取位置更新时

A)该应用程序在后台,请参阅: 背景位置服务不适用于iOS 7

B)该应用程序被暂停/终止,请参阅: 如何获取iOS 7和8的位置更新即使该应用程序被暂停

上述2场景的源代码在GitHub上可用。