我正在写一个应用程序,需要与高精度和低频率的后台位置更新。解决方案似乎是一个后台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
但是我还没有得到一个可以正常工作的最小示例。在尝试了上述公认答案的每一种排列之后,我将一个起点放在一起。进入背景:
- (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];
}
和委托方法:
- (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,似乎有一些证据表明后台任务的行为有所不同:
发布于 2013-09-30 10:13:54
似乎是stopUpdatingLocation
触发了后台看门狗计时器,所以我在didUpdateLocation
中将其替换为:
[self.locationManager setDesiredAccuracy:kCLLocationAccuracyThreeKilometers];
[self.locationManager setDistanceFilter:99999];
这似乎有效地切断了GPS的电源。然后,后台NSTimer
的选择器变为:
- (void) changeAccuracy {
[self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[self.locationManager setDistanceFilter:kCLDistanceFilterNone];
}
我所做的就是定期切换精度,每隔几分钟获得一个高精度的坐标,因为locationManager
没有停止,所以backgroundTimeRemaining
保持在它的最大值。在我的设备上,这将电池消耗从每小时约10%(后台使用恒定的kCLLocationAccuracyBest
)降低到每小时约2%。
发布于 2014-07-10 10:18:06
我写了一个使用定位服务的应用程序,应用程序必须每10秒发送一次位置。它运行得非常好。
只需使用"allowDeferredLocationUpdatesUntilTraveled:timeout“方法,遵循苹果的文档。
具体步骤如下:
需要:更新位置的注册后台模式。
1.创建LocationManger和startUpdatingLocation,并根据需要使用accuracy和filteredDistance:
-(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,如下所示:
- (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获取回调:
-(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.回调,但您应该根据自己的目的在中处理数据
- (void) locationManager:(CLLocationManager *)manager didFinishDeferredUpdatesWithError:(NSError *)error {
_deferringUpdates = NO;
//do something
}
5. 注意:我认为每次应用程序在后台/前台模式之间切换时,我们都应该重置LocationManager的参数。
发布于 2013-09-27 21:02:26
UIBackgroundModes
和location
键,那么你就不需要使用beginBackgroundTaskWithExpirationHandler
方法。这是多余的。你也没有正确地使用它(参见here),但这是没有意义的,因为你的plist已经设置好了。在plist中有UIBackgroundModes location
的CLLocationManger
运行的时候,应用程序才会无限期地在后台运行。如果你在后台调用stopUpdatingLocation
,那么应用程序将会停止并且不会再次启动。也许你可以在调用stopUpdatingLocation
之前调用beginBackgroundTaskWithExpirationHandler
,然后在调用startUpdatingLocation
之后,你可以调用endBackgroundTask
来在GPS停止时保持它的后台,但我从来没有尝试过--这只是一个想法。
另一个选择(我还没有尝试过)是在后台保持位置管理器运行,但是一旦你得到一个准确的位置,将desiredAccuracy
属性更改为1000m或更高,以允许关闭GPS芯片(以节省电池)。然后10分钟后,当你需要再次更新位置时,将desiredAccuracy
调回100m以打开定位系统,直到你得到准确的位置,重复一次。
startUpdatingLocation
时,你必须给它时间来获得一个位置。您不应该立即调用stopUpdatingLocation
。我们让它运行最多10秒,或者直到我们得到一个非缓存的高精度location.
CLLocationManager
几秒钟来获得一个高精度的位置。我不确定,我从来没有使用过重要的位置改变服务。https://stackoverflow.com/questions/19042894
复制相似问题