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

Ala*_*met 35 objective-c core-location ios ios7 ios-background-mode

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

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

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

Ric*_*cky 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];
 }
Run Code Online (Sandbox Code Playgroud)

2014年5月更新:我收到一些请求,要求在将位置发送到服务器一定时间间隔时添加示例代码.我已经添加了示例代码,并结合了BackgroundTaskManager的修复程序,以解决在较长时间内运行的后台故障.如果您有任何疑问,欢迎您加入我们的讨论:iOS7的后台位置更新编程,服务器讨论位置更新

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


Obj*_*ift 18

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

在此输入图像描述


Nik*_*kov 15

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

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

我记录的数据显示地理更新在约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;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @NikolayTsenkov你可以发一个代码片段吗?我发现如果我在后台重新启动位置管理器,当`backgroundTimeRemaining`达到零时,任务最终会被终止. (3认同)

and*_*rer 7

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

从iOS 7开始:

  • 应用程序必须已经使用位置服务(startUpdatingLocation)之前已经背景化以便符合条件的后台运行时间
  • 后台宽限期超时从10分钟减少到3分钟
  • 停止位置更新(通过stopUpdatingLocation)将启动3分钟backgroundTimeRemaining倒计时
  • 已经在后台启动位置更新将不会重置backgroundTimeRemaining

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

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

  • 当应用程序仍处于前台时,启动位置更新(startUpdatingLocation),但将精度和距离过滤器设置为非常粗略(例如3 km)的更新.在前台执行此操作非常重要(在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/


Ric*_*cky 5

在后台任务 Sash中提到了另一个在iOS 7中启动位置管理器的线程

我发现了问题/解决方案.当是时候启动位置服务并停止后台任务时,应该延迟后台任务(我设置1秒).否则位置服务不会启动.

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

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

更新:

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

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

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

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

2014年2月更新: 经过几个月的尝试,我可以在使用iOS 7的设备上连续获取该位置.您可以在此处看到完整的答案:后台位置服务在iOS 7中不起作用

  • 经过两个多月的尝试,人们尝试了许多不同类型的解决方案.我找到了一个非常好的解决方案,每小时消耗的电池少于5%.我将在几天内与大家分享解决方案. (6认同)

Mr.*_*pot 1

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

我发现重大位置更改已开启,但简单地停止并重新启动服务(对于重大更改)并不会触发新位置。