应用程序转到后台后,每n分钟获取一次用户位置
我正在尝试实施本文中给出的build议。
不幸的是,我不清楚这些步骤。 我尝试实施这些build议,但即使在启动和停止locationServices后,backgroundTimeRemaining仍在继续减less。 这是我开发它的方式:
- (void)applicationDidEnterBackground:(UIApplication *)application { UIApplication* app = [UIApplication sharedApplication]; bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ [app endBackgroundTask:bgTask]; bgTask = UIBackgroundTaskInvalid; }]; // Start the long-running task and return immediately. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // Do the work associated with the task. self.timer = nil; [self initTimer]; }); }
initTimer:
- (void)initTimer { // Create the location manager if this object does not // already have one. if (nil == self.locationManager) self.locationManager = [[CLLocationManager alloc] init]; self.locationManager.delegate = self; [self.locationManager startMonitoringSignificantLocationChanges]; if (self.timer == nil) { self.timer = [NSTimer scheduledTimerWithTimeInterval:0.3 target:self selector:@selector(checkUpdates:) userInfo:nil repeats:YES]; } }
checkUpdates:
- (void)checkUpdates:(NSTimer *)timer{ UIApplication* app = [UIApplication sharedApplication]; double remaining = app.backgroundTimeRemaining; if(remaining < 580.0) { [self.locationManager startUpdatingLocation]; [self.locationManager stopUpdatingLocation]; [self.locationManager startMonitoringSignificantLocationChanges]; } DbgLog(@"Reminaing %f", app.backgroundTimeRemaining); }
有没有人有什么可能是我的代码错误的build议? 正在调用initTimer和checkUpdates,但只在后台执行时间(+ – 10分钟)。 我希望应用程序每隔n分钟“永远”更新位置。
我的应用程序的UIBackgroundModes被设置为位置。
更新:
我现在重置didUpdateToLocation和didFailWithError上的计时器。 但仍保持backgroundTimeRemaining不断下降:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { NSLog(@"Did Update Location = %f / %f", [newLocation coordinate].latitude, [newLocation coordinate].longitude); UIApplication* app = [UIApplication sharedApplication]; bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ [app endBackgroundTask:bgTask]; bgTask = UIBackgroundTaskInvalid; }]; // Start the long-running task and return immediately. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // Do the work associated with the task. [self initTimer]; }); } - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error { [self.locationManager stopUpdatingLocation]; UIApplication* app = [UIApplication sharedApplication]; bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ [app endBackgroundTask:bgTask]; bgTask = UIBackgroundTaskInvalid; }]; // Start the long-running task and return immediately. [self initTimer]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // Do the work associated with the task. }); }
我也无效的计时器:
- (void)checkUpdates:(NSTimer *)timer{ UIApplication* app = [UIApplication sharedApplication]; double remaining = app.backgroundTimeRemaining; if(remaining < 580.0 && remaining > 570.0) { [self.timer invalidate]; self.timer = nil; [self.locationManager startUpdatingLocation]; [self.locationManager stopUpdatingLocation]; } DbgLog(@"*************************Checking for updates!!!!!!!!!!! Reminaing %f", app.backgroundTimeRemaining); }
对于有一段时间的梦想试图找出这个问题的人,我有一个简单的解决scheme。
- 研究来自raywenderlich.com的例子。 示例代码完美地工作,但不幸的是,在后台位置没有计时器。 这将无限期地运行。
-
通过使用这个代码片段添加计时器:
-(void)applicationDidEnterBackground { [self.locationManager stopUpdatingLocation]; UIApplication* app = [UIApplication sharedApplication]; bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ [app endBackgroundTask:bgTask]; bgTask = UIBackgroundTaskInvalid; }]; self.timer = [NSTimer scheduledTimerWithTimeInterval:intervalBackgroundUpdate target:self.locationManager selector:@selector(startUpdatingLocation) userInfo:nil repeats:YES]; }
-
只要不要忘记在info.plist中添加“位置更新的应用程序寄存器”。
经过几天尝试所有可能的解决scheme,我终于能够使其工作。 以下是我的解决scheme中的错误:
- 我需要设置2个 UIBackgroundTaskIdentifiers,一个用于定时器,另一个用于locationManager
在我的解决scheme,只需添加:
UIApplication *app = [UIApplication sharedApplication]; bgTask2 = [app beginBackgroundTaskWithExpirationHandler:^{ [app endBackgroundTask:bgTask2]; bgTask2 = UIBackgroundTaskInvalid; }]; self.locationManager.delegate = self; [self.locationManager startUpdatingLocation];
一旦你在后台,你只能有10分钟的额外时间。 没有办法延长这一点。 您应该使用位置后台服务。
工作代码(整个逐步代码) 修改scurioni的代码
步骤1
- 转到项目 – >function – >背景模式 – >select位置更新。
- 转到项目 – >信息 – >添加一个NSLocationAlwaysUsageDescription一个可选string的关键。
第2步
将此代码添加到AppDelegate.m
@interface AppDelegate ()<CLLocationManagerDelegate> @property (strong, nonatomic) CLLocationManager *locationManager; @property (strong, nonatomic) NSTimer *timer; @end
步骤3将此代码添加到AppDelegate.m中的 applicationDidEnterBackground方法中
- (void)applicationDidEnterBackground:(UIApplication *)application { UIApplication *app = [UIApplication sharedApplication]; __block UIBackgroundTaskIdentifier bgTaskId = [app beginBackgroundTaskWithExpirationHandler:^{ [app endBackgroundTask:bgTaskId]; bgTaskId = UIBackgroundTaskInvalid; }]; dispatch_async( dispatch_get_main_queue(), ^{ self.timer = nil; [self initTimer]; [app endBackgroundTask:bgTaskId]; bgTaskId = UIBackgroundTaskInvalid; }); } - (void)initTimer { if (nil == self.locationManager) self.locationManager = [[CLLocationManager alloc] init]; self.locationManager.delegate = self; [self.locationManager requestAlwaysAuthorization]; [self.locationManager startMonitoringSignificantLocationChanges]; if (self.timer == nil) { self.timer = [NSTimer scheduledTimerWithTimeInterval:0.3 target:self selector:@selector(checkUpdates:) userInfo:nil repeats:YES]; } } - (void)checkUpdates:(NSTimer *)timer{ UIApplication *app = [UIApplication sharedApplication]; double remaining = app.backgroundTimeRemaining; if(remaining < 580.0) { [self.locationManager startUpdatingLocation]; [self.locationManager stopUpdatingLocation]; [self.locationManager startMonitoringSignificantLocationChanges]; } } - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { NSLog(@"Did Update Location = %f / %f", [newLocation coordinate].latitude, [newLocation coordinate].longitude); [self updateLocationWithLatitude:[newLocation coordinate].latitude andLongitude:[newLocation coordinate].longitude]; UIApplication* app = [UIApplication sharedApplication]; __block UIBackgroundTaskIdentifier bgTask = bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ [app endBackgroundTask:bgTask]; bgTask = UIBackgroundTaskInvalid; }]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [self initTimer]; }); } - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error { [self.locationManager stopUpdatingLocation]; UIApplication *app = [UIApplication sharedApplication]; __block UIBackgroundTaskIdentifier bgTask = bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ [app endBackgroundTask:bgTask]; bgTask = UIBackgroundTaskInvalid; }]; [self initTimer]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // Do the work associated with the task }); } -(void)updateLocationWithLatitude:(CLLocationDegrees)latitude andLongitude:(CLLocationDegrees)longitude{ //Here you can update your web service or back end with new latitude and longitude }