如何在 deferredlocationupdatesavailable returns NO 时使用 ios 高效地获取位置更新
How to get location updates power efficiently with ios when deferredlocationupdatesavailable returns NO
我正在尝试推迟 ios11 中的位置更新以节省电量。默认似乎正在尽可能快地更新(即每秒更新一次),所以我想推迟更新或做一些其他聪明的事情来制作一个节能的应用程序。
当实现 CLLocationManager 并像这样设置时:
_locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = _sharedInstance = [[LocationManager alloc] init];
[_locationManager requestAlwaysAuthorization];
_locationManager.allowsBackgroundLocationUpdates = true;
_locationManager.desiredAccuracy = kCLLocationAccuracyBest;
_locationManager.distanceFilter = 0;
_locationManager.pausesLocationUpdatesAutomatically = NO;
_locationManager.activityType = CLActivityTypeFitness;
[CLLocationManager deferredLocationUpdatesAvailable] returns 在 didUpdateLocations 中为 false,因此在尝试使用 allowDeferredLocationUpdatesUntilTraveled[=26= 方法延迟时出现错误 11 ].
这些问题( and )表明不再支持延迟位置更新。
无论如何,当您希望每 x(例如 15)秒更新一次、最佳(即 gps)精度和 working/running 始终在后台时,您如何使 ios 定位应用程序高效节能?
这个答案可能有点离谱,因为即使文档没有被删除,实际上也不再可能使用延迟功能。但目的是每隔一段时间切换 on/off 位置,以避免一直打开它以节省电量。
为了接近完全转动 on/off,可能会在高精度和低精度之间切换,这肯定会节省电量。 (高精度通常<10m会使用GPS模块,低精度>500m通常会使用AGPS.
首先,以您想要的间隔启动一个 NSTimer,然后开始高精度更新。当在 didUpdateLocations 中接收到位置时,从高精度更改为低精度。 NSTimer 的回调请求新的高精度位置更新(即调用 setupHighAccuracy
)。因此,计时器设置了高精度更新的频率。这也将在后台工作,因为定位服务仍然是 运行。如果停止更新,应用程序将在后台停止。当停止并再次启动位置管理器时,它会立即调用 didUpdateLocation,但检查时间戳,位置可能被缓冲。
显示下面的一些片段以开始。生产代码将需要更多过滤和测试:
@property (retain, nonatomic) NSTimer *atimer;
static BOOL _lowAccuracy;
- (void)timerCallback {
[self setupHighAccuracy];
}
- (void)setupTimer
{
if(self.atimer != nil)
{
return;
}
UIApplication *app = [UIApplication sharedApplication];
__block UIBackgroundTaskIdentifier bgTaskId =
[app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTaskId];
bgTaskId = UIBackgroundTaskInvalid;
}];
dispatch_async( dispatch_get_main_queue(), ^{
self.atimer = [NSTimer scheduledTimerWithTimeInterval:15.0 // consider higher interval
target:self
selector:@selector(timerCallback)
userInfo:nil
repeats:YES];
}
[app endBackgroundTask:bgTaskId];
bgTaskId = UIBackgroundTaskInvalid;
});
}
- (void)setupHighAccuracy
{
if(_lowAccuracy)
{
[_locationManager performSelectorOnMainThread:@selector(stopUpdatingLocation) withObject:nil waitUntilDone:YES];
_locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters; // or kCLLocationAccuracyBest, tune yourself
_locationManager.activityType = CLActivityTypeFitness;
_locationManager.distanceFilter = 15; // or 0, tune yourself
_lowAccuracy = false;
[_locationManager performSelectorOnMainThread:@selector(startUpdatingLocation) withObject:nil waitUntilDone:YES];
}
}
- (void)setupLowAccuracy
{
if(!_lowAccuracy)
{
s_initialized = true;
[_locationManager performSelectorOnMainThread:@selector(stopUpdatingLocation) withObject:nil waitUntilDone:YES];
_locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
_locationManager.activityType = CLActivityTypeFitness;
_locationManager.distanceFilter = 3000;
_lowAccuracy = true;
[_locationManager performSelectorOnMainThread:@selector(startUpdatingLocation) withObject:nil waitUntilDone:YES];
}
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations
{
CLLocation *location = locations.lastObject;
if(!_lowAccuracy) {
// update system with location here
[_locationManager.delegate setupLowAccuracy];
self.s_lastLocation = location;
}
}
我正在尝试推迟 ios11 中的位置更新以节省电量。默认似乎正在尽可能快地更新(即每秒更新一次),所以我想推迟更新或做一些其他聪明的事情来制作一个节能的应用程序。
当实现 CLLocationManager 并像这样设置时:
_locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = _sharedInstance = [[LocationManager alloc] init];
[_locationManager requestAlwaysAuthorization];
_locationManager.allowsBackgroundLocationUpdates = true;
_locationManager.desiredAccuracy = kCLLocationAccuracyBest;
_locationManager.distanceFilter = 0;
_locationManager.pausesLocationUpdatesAutomatically = NO;
_locationManager.activityType = CLActivityTypeFitness;
[CLLocationManager deferredLocationUpdatesAvailable] returns 在 didUpdateLocations 中为 false,因此在尝试使用 allowDeferredLocationUpdatesUntilTraveled[=26= 方法延迟时出现错误 11 ].
这些问题(
无论如何,当您希望每 x(例如 15)秒更新一次、最佳(即 gps)精度和 working/running 始终在后台时,您如何使 ios 定位应用程序高效节能?
这个答案可能有点离谱,因为即使文档没有被删除,实际上也不再可能使用延迟功能。但目的是每隔一段时间切换 on/off 位置,以避免一直打开它以节省电量。
为了接近完全转动 on/off,可能会在高精度和低精度之间切换,这肯定会节省电量。 (高精度通常<10m会使用GPS模块,低精度>500m通常会使用AGPS.
首先,以您想要的间隔启动一个 NSTimer,然后开始高精度更新。当在 didUpdateLocations 中接收到位置时,从高精度更改为低精度。 NSTimer 的回调请求新的高精度位置更新(即调用 setupHighAccuracy
)。因此,计时器设置了高精度更新的频率。这也将在后台工作,因为定位服务仍然是 运行。如果停止更新,应用程序将在后台停止。当停止并再次启动位置管理器时,它会立即调用 didUpdateLocation,但检查时间戳,位置可能被缓冲。
显示下面的一些片段以开始。生产代码将需要更多过滤和测试:
@property (retain, nonatomic) NSTimer *atimer;
static BOOL _lowAccuracy;
- (void)timerCallback {
[self setupHighAccuracy];
}
- (void)setupTimer
{
if(self.atimer != nil)
{
return;
}
UIApplication *app = [UIApplication sharedApplication];
__block UIBackgroundTaskIdentifier bgTaskId =
[app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTaskId];
bgTaskId = UIBackgroundTaskInvalid;
}];
dispatch_async( dispatch_get_main_queue(), ^{
self.atimer = [NSTimer scheduledTimerWithTimeInterval:15.0 // consider higher interval
target:self
selector:@selector(timerCallback)
userInfo:nil
repeats:YES];
}
[app endBackgroundTask:bgTaskId];
bgTaskId = UIBackgroundTaskInvalid;
});
}
- (void)setupHighAccuracy
{
if(_lowAccuracy)
{
[_locationManager performSelectorOnMainThread:@selector(stopUpdatingLocation) withObject:nil waitUntilDone:YES];
_locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters; // or kCLLocationAccuracyBest, tune yourself
_locationManager.activityType = CLActivityTypeFitness;
_locationManager.distanceFilter = 15; // or 0, tune yourself
_lowAccuracy = false;
[_locationManager performSelectorOnMainThread:@selector(startUpdatingLocation) withObject:nil waitUntilDone:YES];
}
}
- (void)setupLowAccuracy
{
if(!_lowAccuracy)
{
s_initialized = true;
[_locationManager performSelectorOnMainThread:@selector(stopUpdatingLocation) withObject:nil waitUntilDone:YES];
_locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
_locationManager.activityType = CLActivityTypeFitness;
_locationManager.distanceFilter = 3000;
_lowAccuracy = true;
[_locationManager performSelectorOnMainThread:@selector(startUpdatingLocation) withObject:nil waitUntilDone:YES];
}
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations
{
CLLocation *location = locations.lastObject;
if(!_lowAccuracy) {
// update system with location here
[_locationManager.delegate setupLowAccuracy];
self.s_lastLocation = location;
}
}