应用程序转到后台后,每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。

  1. 研究来自raywenderlich.com的例子。 示例代码完美地工作,但不幸的是,在后台位置没有计时器。 这将无限期地运行。
  2. 通过使用这个代码片段添加计时器:

     -(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]; } 
  3. 只要不要忘记在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 }