背景定位服务不适用于iOS 7

我最近升级了我的iOS设备以使用iOS 7.我们正在开发的其中一个应用程序使用后台定位服务来跟踪设备位置,我们所有的testing人员都报告说应用程序不再出现在iOS下的后台7。

我们已经validation在设备上的设置中启用了应用程序的背景,并且之前的构build在iOS 6下完美地工作。即使设备被循环,应用程序也会在位置更新后重新启动。

还有什么需要做的,使之在iOS 7下工作?

我很抱歉延迟发布解决scheme。 在过去的几个月里,我一直很忙,直到忘记这个线程,才开始追求自己的个人生活。 以下是我用来从iOS 7设备获取连续位置的解决scheme,无论它处于前景还是后台。

您可以从博客和github上find完整的解决scheme和解释:

  1. 背景位置更新iOS 7和8的编程

  2. Github项目:iOS 7和8的背景位置更新编程

方法和说明: –

  1. 我在函数didUpdateLocations中每隔1分钟重新启动一次位置pipe理器

  2. 我允许位置pipe理器在closures之前从设备获取位置10秒(以节省电池)。

部分代码如下:

-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{ for(int i=0;i<locations.count;i++){ CLLocation * newLocation = [locations objectAtIndex:i]; CLLocationCoordinate2D theLocation = newLocation.coordinate; CLLocationAccuracy theAccuracy = newLocation.horizontalAccuracy; NSTimeInterval locationAge = -[newLocation.timestamp timeIntervalSinceNow]; if (locationAge > 30.0) continue; //Select only valid location and also location with good accuracy if(newLocation!=nil&&theAccuracy>0 &&theAccuracy<2000 &&(!(theLocation.latitude==0.0&&theLocation.longitude==0.0))){ self.myLastLocation = theLocation; self.myLastLocationAccuracy= theAccuracy; NSMutableDictionary * dict = [[NSMutableDictionary alloc]init]; [dict setObject:[NSNumber numberWithFloat:theLocation.latitude] forKey:@"latitude"]; [dict setObject:[NSNumber numberWithFloat:theLocation.longitude] forKey:@"longitude"]; [dict setObject:[NSNumber numberWithFloat:theAccuracy] forKey:@"theAccuracy"]; //Add the vallid location with good accuracy into an array //Every 1 minute, I will select the best location based on accuracy and send to server [self.shareModel.myLocationArray addObject:dict]; } } //If the timer still valid, return it (Will not run the code below) if (self.shareModel.timer) return; self.shareModel.bgTask = [BackgroundTaskManager sharedBackgroundTaskManager]; [self.shareModel.bgTask beginNewBackgroundTask]; //Restart the locationMaanger after 1 minute self.shareModel.timer = [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:@selector(restartLocationUpdates) userInfo:nil repeats:NO]; //Will only stop the locationManager after 10 seconds, so that we can get some accurate locations //The location manager will only operate for 10 seconds to save battery NSTimer * delay10Seconds; delay10Seconds = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(stopLocationDelayBy10Seconds) userInfo:nil repeats:NO]; } 

2014年5月更新 :我收到了一些要求在发送位置到服务器一定时间间隔的示例代码的请求。 我已经添加了示例代码,并且还为BackgroundTaskManager组合了一个修复程序,以解决长时间运行的背景故障。 如果您有任何问题,欢迎您join我们的讨论: 背景位置更新编程的iOS 7位置更新到服务器讨论

2015年1月更新 :如果即使应用程序被暂停,您也想获取位置更新,请参阅: 如何获取iOS 7和8的位置更新即使应用程序暂停

如果你看WWDC 2013会议video#204 – 什么是多任务处理pdf的新function,第15页清楚地提到,如果用户从应用程序切换器中将应用程序杀死,应用程序将不会在后台启动。 请看图片,

在这里输入图像描述

我认为他们做了一个优化(可能使用运动传感器),以检测手机的“相对”固定位置,并停止位置更新。 这只是一个猜测,但我的testing目前显示:

  1. 开始位置更新; (testing精度10米和100米,每个3次)
  2. closures设备的屏幕,把应用程序放在后台;
  3. 将设备保持静止(例如在桌子上)30分钟。

我logging的数据显示在〜15m和30s之后停止的地理更新。 所有其他的后台处理,你也会被终止。

我的设备是iOS 5的iPhone 5。

我有95%的把握,iOS 6 / 6.1的情况并非如此。 获得100米精度的地理更新用于在后台给你几乎连续的运行。

更新

如果每8分钟重新启动一次位置pipe理器,则应该连续运行。

更新#2

我最近还没有testing过这个,但是这是我写这篇文章的时候重启的。 我希望这是有帮助的。

 - (void)tryRestartLocationManager { NSTimeInterval now = [[NSDate date] timeIntervalSince1970]; int seconds = round(floor(now - locationManagerStartTimestamp)); if ( seconds > (60 * 8) ) { [locationManager stopUpdatingLocation]; [locationManager startUpdatingLocation]; locationManagerStartTimestamp = now; } } 

我的iOS应用程序需要定期发送位置更新到服务器,以下方法为我们工作….

从iOS 7开始:

  • 一个应用程序必须已经使用位置服务(startUpdatingLocation)之前已经后台,为了有资格的后台运行时间
  • 后台宽限期超时从10分钟减less到3分钟
  • 停止位置更新(通过stopUpdatingLocation)将启动3分钟的backgroundTimeRemaining倒计时
  • 当已经在后台启动位置更新不会重置backgroundTimeRemaining

所以,不要随时停止位置更新…相反,更喜欢使用必要的准确性(精确位置vs粗略位置)。 粗略的位置不会消耗太多电量…所以这个解决scheme可以解决您的问题。

在网上进行了大量的search之后,find了一个为iOS 7提供可行解决scheme的链接。解决scheme如下:

  • 虽然应用程序仍处于前台,但启动位置更新(startUpdatingLocation),但将精度和距离filter设置为非常粗糙(例如3公里)的更新。 在前台执行此操作非常重要(在applicationDidEnterBackground中已经太迟了)。
  • 当需要细粒度的分辨率时,临时设置精度和距离filter以获得最佳位置,然后将其恢复为粗粒度值 – 但是不会停止位置更新。
  • 由于位置更新始终处于启用状态,因此该应用在进入后台时不会被暂停。

并确保将以下内容添加到您的应用程序的Info.plist“位置”到UIBackgroundModes项“location-services”和“gps”到UIRequiredDeviceCapabilities项

学分: http : //gooddevbaddev.wordpress.com/2013/10/22/ios-7-running-location-based-apps-in-the-background/

我发现另一个线程开始在iOS 7中的位置pipe理器从后台任务中提到

我find了问题/解决scheme。 当开始定位服务并停止后台任务的时候,后台任务应该延时停止(我设置1秒)。 否则位置服务将无法启动。

任何人都可以尝试,并validation?

尼古拉,你可以在这里粘贴你的代码吗? 我试图每8分钟重新启动一次位置pipe理器,但是它不会持续运行。

更新:

经过高低search,我find了苹果论坛的解决scheme!

在iOS 7中,您无法在后台启动位置服务 。 如果您希望位置服务在后台继续运行,则必须在前台启动它,并将继续在后台运行。

如果你像我一样,停止位置服务,并使用计时器在后台重新启动它,它将无法正常工作。

有关更详细的信息,您可以观看WWDC 2013的前8分钟video307: https : //developer.apple.com/wwdc/videos/

2014年2月更新:经过几个月的尝试,我可以从使用iOS 7的设备连续获取位置信息。 您可能会在这里看到完整的答案: 背景定位服务不适用于iOS 7

状态栏上的图标是否打开? 这也是我的一个奇怪的行为。 检查我的问题: startMonitoringSignificantLocationChanges,但一段时间didUpdateLocations不被调用了

我发现,重大的位置变化已经开始,但只是停止和重新启动服务(对于重大变化)并没有发射新的地点。