后台位置服务在iOS 7中不起作用

时间:2013-09-22 17:46:23

标签: ios objective-c ios7 core-location ios-background-mode

我最近将我的iOS设备升级为使用iOS 7.我们正在开发的其中一个应用程序使用后台位置服务来跟踪设备位置,我们所有的测试人员都报告该应用程序似乎不再跟踪iOS 7下的背景。

我们已经确认在设备上的设置中启用了该应用的后台处理,并且之前的版本在iOS 6下运行良好。即使设备已循环播放,应用也会在位置更新后重新启动。

在iOS 7下还有什么需要做才能让这项工作成功吗?

7 个答案:

答案 0 :(得分:47)

以下是我用来从iOS 7设备获取连续位置的解决方案,无论它是在前台还是后台。

您可以从博客和github找到完整的解决方案和解释: -

  1. Background Location Update Programming for iOS 7 and 8

  2. Github Project: Background Location Update Programming for iOS 7 and 8

  3. 方法和说明: -

    1. 我在功能 didUpdateLocations

    2. 中每1分钟重新启动一次位置管理器
    3. 我允许位置管理员在关闭之前从设备获取位置10秒(以节省电池电量)。

    4. 下面的部分代码: -

      -(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的修复程序,以解决在较长时间内运行的后台故障。如果您有任何疑问,欢迎您加入我们的讨论:Background Location Update Programming for iOS 7 with Location Update to Server Discussion

      2015年1月更新:如果您希望在应用暂停时获取位置更新,请参阅:Get Location Updates for iOS App Even when Suspended

答案 1 :(得分:18)

如果你看一下WWDC 2013会议视频#204 - 多任务处理的新功能pdf,第15页清楚地提到,如果用户从应用程序切换器中杀死应用程序,应用程序将无法在后台启动。请看图片,

enter image description here

答案 2 :(得分:15)

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

  1. 开始位置更新; (测试精度为10米和100米,每次3次)
  2. 关闭设备屏幕以将应用程序置于后台;
  3. 将设备静止(例如放在桌子上)30分钟。
  4. 我记录的数据显示地理更新在约15分钟和30秒后停止。使用所有其他后台处理也会终止。

    我的设备是带有iOS 7的iPhone 5。

    我95%肯定,iOS 6 / 6.1上并非如此。如果获得100米精度的地理更新,可以让你在后台连续运行。

    <强>更新

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

    更新#2

    我最近没有对此进行测试,但这是我在撰写帖子时重新启动它的方法。我希望这有用。

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

答案 3 :(得分:7)

我的一个iOS应用需要定期向服务器发送位置更新,并且以下方法适用于我们....

从iOS 7开始:

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

所以,不要随时停止位置更新......而是更喜欢使用必要的准确度(精确位置与粗略位置)。粗糙的位置不会耗费太多电池......所以这个解决方案可以解决您的问题。

经过大量在线搜索后,找到了一个为iOS 7提供可行解决方案的链接。解决方案如下:

  • 当应用程序仍处于前台时,启动位置更新 (startUpdatingLocation)但设置精度和距离过滤器 非常粗略(例如3公里)的更新。这样做很重要 在前台(在applicationDidEnterBackground中为时已晚)。
  • 当需要细粒度分辨率时,暂时设置 准确度和距离过滤器以获得最佳位置,以及 然后将它们恢复到课程粒度值 - 但永远不会停止 位置更新。
  • 由于始终启用了位置更新,因此该应用无法获取 当它到达后台时暂停。

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

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

答案 4 :(得分:5)

我发现另一个帖子Start Location Manager in iOS 7 from background task Sash提到了

  

我发现了问题/解决方案。当需要启动位置服务并停止后台任务时,应该延迟后台任务(我设置1秒)。否则,位置服务将无法启动。

任何人都可以尝试并验证吗?

Nikolay,你能在这里粘贴你的代码吗?我试图每隔8分钟重新启动一次位置管理器,但它不能连续运行。

<强>更新

在搜索了High and Low之后,我从Apple Forum找到了解决方案!

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

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

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

2014年2月更新: 经过几个月的尝试,我可以在使用iOS 7的设备上连续获取该位置。您可以在此处看到完整的答案:Background Location Services not working in iOS 7

答案 5 :(得分:1)

状态栏上的图标是否已开启?这也是一种奇怪的行为。 检查我的问题:startMonitoringSignificantLocationChanges but after some time didUpdateLocations is not called anymore

我发现重要的位置更改已启用,但只是停止并重新启动服务(进行重大更改)并未触发新位置。

答案 6 :(得分:0)

您必须将pausesLocationUpdatesAutomatically类的CLLocationManager属性设置为 false ,以禁止系统暂停位置更新。