pco*_*ing 91 objective-c core-location ios background-task ios-background-mode
我正在编写一个需要高精度和低频率的背景位置更新的应用程序.该解决方案似乎是一个后台NSTimer任务,它启动位置管理器的更新,然后立即关闭.之前已经问过这个问题:
但我还没有得到最起码的例子.在尝试了上述接受的答案的每一个排列后,我总结了一个起点.输入背景:
- (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];
}
Run Code Online (Sandbox Code Playgroud)
和委托方法:
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
NSLog(@"%@", newLocation);
NSLog(@"background time: %f", [UIApplication sharedApplication].backgroundTimeRemaining);
[self.locationManager stopUpdatingLocation];
}
Run Code Online (Sandbox Code Playgroud)
当前行为是backgroundTimeRemaining从180秒减少到零(记录位置时),然后执行到期处理程序,不再生成进一步的位置更新.如何修改上述代码以便在后台无限期地接收定期位置更新?
更新:我的目标是iOS 7,似乎有一些证据表明后台任务的行为有所不同:
pco*_*ing 61
这似乎stopUpdatingLocation是触发后台看门狗定时器的原因,所以我将其替换didUpdateLocation为:
[self.locationManager setDesiredAccuracy:kCLLocationAccuracyThreeKilometers];
[self.locationManager setDistanceFilter:99999];
Run Code Online (Sandbox Code Playgroud)
这似乎有效地关闭了GPS.NSTimer然后背景的选择器变为:
- (void) changeAccuracy {
[self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[self.locationManager setDistanceFilter:kCLDistanceFilterNone];
}
Run Code Online (Sandbox Code Playgroud)
我所做的就是定期切换精度以便每隔几分钟获得一个高精度坐标,并且因为locationManager没有停止,所以backgroundTimeRemaining保持其最大值.这样可以减少电池消耗,从每小时约10%(kCLLocationAccuracyBest背景恒定)到我的设备每小时约2%.
sam*_*ui7 45
我确实使用位置服务编写应用程序,应用程序必须每10秒发送一次位置.而且效果很好.
只需按照Apple的doc 使用" allowDeferredLocationUpdatesUntilTraveled:timeout "方法即可.
步骤如下:
必需:注册更新位置的后台模式.
1.创建LocationManger和startUpdatingLocation,精确度和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];
}
Run Code Online (Sandbox Code Playgroud)
2.要在后台使用"allowDeferredLocationUpdatesUntilTraveled:timeout"方法永久保持app运行,当app移动到后台时,必须使用新参数重新启动updatesLocation,如下所示:
- (void)applicationWillResignActive:(UIApplication *)application {
_isBackgroundMode = YES;
[_locationManager stopUpdatingLocation];
[_locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[_locationManager setDistanceFilter:kCLDistanceFilterNone];
_locationManager.pausesLocationUpdatesAutomatically = NO;
_locationManager.activityType = CLActivityTypeAutomotiveNavigation;
[_locationManager startUpdatingLocation];
}
Run Code Online (Sandbox Code Playgroud)
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];
}
}
Run Code Online (Sandbox Code Playgroud)
4.但是,你应该在随后处理数据":didFinishDeferredUpdatesWithError:的LocationManager"回调你的目的
- (void) locationManager:(CLLocationManager *)manager didFinishDeferredUpdatesWithError:(NSError *)error {
_deferringUpdates = NO;
//do something
}
Run Code Online (Sandbox Code Playgroud)
5. 注意:我认为每次app在background/forground模式之间切换时我们都应该重置LocationManager的参数.
pro*_*rmr 36
如果你UIBackgroundModes的plist有location钥匙,那么你不需要使用beginBackgroundTaskWithExpirationHandler方法.那是多余的.你也错误地使用它(见这里),但是因为你的plist被设置了,所以没有实际意义.
随着UIBackgroundModes location在plist中的应用程序将继续无限期只只要在后台运行CLLocationManger正在运行.如果您stopUpdatingLocation在后台打电话,那么应用程序将停止并且不会再次启动.
也许你可以在打电话beginBackgroundTaskWithExpirationHandler之前拨打电话stopUpdatingLocation,然后在打电话之后startUpdatingLocation你可以打电话endBackgroundTask给它,以便在GPS停止时让它保持背景,但我从来没有尝试过 - 这只是一个想法.
另一个选项(我没有尝试过)是让位置管理器在后台运行但是一旦你得到一个准确的位置desiredAccuracy就把属性改成1000米或更高,以便让GPS芯片关闭(以节省电池电量).然后10分钟后,当您需要另一个位置更新时,将desiredAccuracy背面更改为100米以打开GPS,直到您获得准确的位置,重复.
当你打电话startUpdatingLocation给位置经理时,你必须给它时间来获得一个位置.你不应该立即打电话stopUpdatingLocation.我们让它运行最多10秒或直到我们得到一个非缓存的高精度位置.
您需要过滤掉缓存的位置并检查所获得位置的准确性,以确保它符合您所需的最低精度(请参阅此处).您获得的第一个更新可能是10分钟或10天.您获得的第一个准确度可能是3000米.
请考虑使用重要的位置更改API.一旦获得重要更改通知,您可以启动CLLocationManager几秒钟以获得高精度位置.我不确定,我从未使用过重要的位置变更服务.
当需要启动位置服务并停止后台任务时,应该延迟后台任务(1秒应该足够).否则位置服务不会启动.位置服务也应保持开启几秒钟(例如3秒).
有一个cocoapod APScheduledLocationManager,它允许每n秒获得具有所需位置精度的背景位置更新.
let manager = APScheduledLocationManager(delegate: self)
manager.startUpdatingLocation(interval: 170, acceptableLocationAccuracy: 100)
Run Code Online (Sandbox Code Playgroud)
存储库还包含一个用Swift 3编写的示例应用程序.
| 归档时间: |
|
| 查看次数: |
92397 次 |
| 最近记录: |