35

我最近升级了我的 iOS 设备以使用 iOS 7。我们正在开发的应用程序之一使用后台定位服务来跟踪设备位置,我们所有的测试人员都报告说该应用程序似乎不再在 iOS 下在后台进行跟踪7.

我们已经验证在设备的设置中启用了应用程序的后台,并且之前的构建在 iOS 6 下完美运行。即使设备被循环,应用程序也会在位置更新后重新启动。

在 iOS 7 下是否需要做其他事情才能使这项工作?

4

7 回答 7

47

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

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

  1. iOS 7 和 8 的后台位置更新编程

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

方法和说明:-

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

  2. 我允许位置管理器在关闭设备之前从设备获取位置 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 的修复程序,以解决后台长时间运行的故障。如果您有任何问题,欢迎在这里加入我们的讨论:iOS 7 的后台位置更新编程与服务器位置更新讨论

2015 年 1 月更新:如果您想在应用程序暂停时获取位置更新,请参阅:即使在暂停时也为 iOS 应用程序获取位置更新

于 2014-02-23T09:49:26.793 回答
18

如果您查看 WWDC 2013 会议视频 #204 - What's new with multitasking pdf,第 15 页清楚地提到如果用户从应用程序切换器中删除应用程序,应用程序将不会在后台启动。请看图,

在此处输入图像描述

于 2013-09-30T17:03:54.947 回答
15

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

  1. 开始位置更新;(测试精度为 10 米和 100 米,各 3 次)
  2. 关闭设备屏幕以将应用置于后台;
  3. 让设备静止(例如放在桌子上)30 分钟。

我记录的数据显示地理更新在大约 15m 和 30s 之后停止。这样,您所做的所有其他后台处理也将终止。

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

我有 95% 的把握,在 iOS 6/6.1 上并非如此。在过去,以 100m 的精度获取地理更新可以让您在后台几乎连续运行。

更新

如果您每 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;
    }
}
于 2013-09-24T09:13:58.433 回答
7

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

从 iOS 7 开始:

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

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

在网上搜索了很多之后,找到了一个为iOS 7提供可行解决方案的链接。解决方案如下:

  • 当应用程序仍在前台时,开始位置更新 (startUpdatingLocation),但将精度和距离过滤器设置为非常粗略(例如 3 公里)的更新。在前台执行此操作很重要(在 applicationDidEnterBackground 中为时已晚)。
  • 当需要细粒度的分辨率时,临时设置精度和距离过滤器以获得最佳位置,然后将它们恢复为粗粒度值 - 但永远不要停止位置更新。
  • 由于始终启用位置更新,因此应用程序在进入后台时不会暂停。

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

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

于 2014-07-07T09:50:45.253 回答
5

我从后台任务Sash 中找到了另一个线程Start Location Manager in iOS 7提到

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

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

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

更新:

经过高低搜索,我从苹果论坛找到了解决方案!

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

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

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

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

于 2013-09-27T03:46:03.240 回答
1

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

我发现重要的位置更改已开启,但只是停止并重新启动服务(对于重大更改)并没有触发新的位置。

于 2013-09-23T15:30:33.457 回答
0

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

于 2018-11-06T10:14:29.417 回答