使用CoreLocation重要位置监控和CoreBluetooth时,电池耗尽

我们已经发布了一个在后台运行的应用程序,并使用CoreBluetoothCoreLocation自动保存您的停车位置。

在高层次上,我们的应用程序只是寻找一个CoreBluetooth断开事件,并打开GPS,直到我们得到一个定位(精度<= 10米)或3分钟的最大时间(这可能发生在停放在没有GPS覆盖的地下停车场)。 然后,我们使用重要的位置监测来自动重新启动我们的应用程序,以防系统终止我们的应用程序。

在我们的开发过程中,我们从来没有看到自己的电池耗尽问题,但是我们75%的用户表示他们看到了显着的电池消耗。 我们的支持者中有10%对此次调查做出了回应,因此很难确定细分的代表性,但是这个用户的比例很大。 http://www.findmycarsmarter.com/forum/viewtopic.php?f=4&t=30

然后,我们发布了一个更新,允许用户禁用重要的位置监控,60%的人表示通过禁用重要的位置监控漏洞消失。 http://www.findmycarsmarter.com/forum/viewtopic.php?f=4&t=42

最初,我们不能自己重复排水问题,但是我们发现,当我们安装了一个简单的应用程序,只需打开显着的位置监测,结合查找我的汽车更智能,我们间歇性地看到了stream失的重现。 在排水状态下,手机不进入hibernate状态。 即使手机已进入睡眠状态并且显示屏已closures,((设置 – >使用情况 – >自上次完整充电以来的时间))中的使用时间也会持续增加。 有些东西阻止系统进入hibernate状态。 电池在这个阶段每小时消耗大约15%。 这个排水pipe间歇性地出现,似乎在一两个小时后自行清除,随机再来。 我们还没有find一种可靠性重现stream失的方法。

我们认为这个问题是由多个客户端调用CoreLocation引起的。 我们询问了一些遇到问题的用户,以便擦除他们的电话,并只安装“查找我的智能汽车”应用程序。 只是安装了这个应用程序,排水渠没有展示。 我们有其他的报道,当我们的应用程序与谷歌纵横或Facebook等使用,当他们看到stream失发生。 或者,如果他们去杀了其他的应用程序,漏水消失。 我们已经看到通过一个电源周期的漏洞,没有启动应用程序。 这意味着它必须是防止操作系统进入hibernate状态的系统级服务。

尽pipe我们认为这个问题是由多个客户端调用CoreLocation的一些竞争条件引起的,但我们从来没有看到使用CoreLocation的应用程序重现问题。 我们甚至创build了4个或5个不同的应用程序,将同时访问CoreLocation,我们没有看到漏水发生。 然而,当我们使用CoreLocation的应用程序和使用CoreLocation + CoreBluetooth的第二个应用程序时,我们看到了问题。 有很less的应用程序使用CoreLocation + CoreBluetooth组合,所以潜在的这就是为什么更多的开发者没有遇到这个问题。 尽pipe我们无法解释CoreLocation和CoreBluetooth如何相互作用导致这个漏洞,以及CoreLocation的第二个应用程序如何进入等式。 由于漏极是间歇性的,所以只是在我们使用CoreLocation + CoreBluetooth进行testing的时候才会出现问题。

在只有这两个应用程序安装了CTM1和FMC的5.0.1 iPhone 4S上,我们可以间歇性地进入漏极状态。 有趣的是,在我们的普通设备上,擦除设备上的漏水问题似乎不太常见。 不幸的是,我们只看到了几次排水状态,没有能够可靠地重现排水,我们没有一个良好的控制状态工作。

我们已经向苹果公司提交了一个错误报告,并且发布了一个技术支持事件,但是Stackover社区也可以提供一些见解。 我们在5.0.1和5.1 Beta 3中都看到了这个问题。

CTM1 http://www.findmycarsmarter.com/files/CTM1.zip

 On Going into the Background [locationManager stopUpdatingLocation]; [locationManager stopUpdatingHeading]; [locationManager startMonitoringSignificantLocationChanges]; On Re-entering Foreground [locationManager stopMonitoringSignificantLocationChanges]; [locationManager startUpdatingLocation]; [locationManager startUpdatingHeading]; On didUpdateToLocation //do nothing On didUpdateHeading //do nothing 

FMC http://www.findmycarsmarter.com/files/FMC.zip

 On Going into the Background [btleManager stopScan]; [locationManager stopUpdatingLocation]; [locationManager stopUpdatingHeading]; [locationManager startMonitoringSignificantLocationChanges]; On Re-entering Foreground [locationManager stopMonitoringSignificantLocationChanges]; [locationManager startUpdatingLocation]; [locationManager startUpdatingHeading]; [btleManager scanForPeripheralsWithServices:nil options:nil]; On didUpdateToLocation //do nothing On didUpdateHeading //do nothing On centralManagerDidUpdateState [btleManager scanForPeripheralsWithServices:nil options:nil]; On didDiscoverPeripheral [btleManager connectPeripheral:device options:nil]; On didConnectPeripheral //update log On didDisconnectPeripheral //initiate reconnect [btleManager connectPeripheral:device options:nil]; 

如果您发现任何可能导致stream失的编码错误,请告诉我们。

我们还有另一个问题,如果我们同时使用GPS和显着位置监测,是否有理由调用stopMonitoringSignificantLocationChanges ? 看看区域示例代码,他们在进入前台时调用stopMonitoringSignificantLocationChangesstartLocationUpdate在进入后台时调用stopMonitoringSignificantLocationChangesstartLocationUpdate ,但是我想知道这是必要/推荐/必需的吗?

更新:

我们已经向苹果开发者技术支持部门证实,对于使用GPS和重要位置监测的应用,我们在启用GPS更新之前closures重要位置监测的顺序是正确的。

我们也已经证实,在GM 5.1中仍然可以看到排水问题,并且针对5.1框架重新编译了Find My Car Smarter应用程序。

更新:

看起来问题是在我们的应用程序从后台启动以响应“重要位置监视”事件时触发的。 我们实际上并没有在我们的示例代码中正确处理这个场景,而是在我们的实际应用程序中。

在示例代码中,在后台重新启动时,我们将打开位置更新,并且由于没有applicationDidEnterBackground调用,GPS将保持打开状态。

在我们的应用程序中,我们通过查找UIApplicationLaunchOptionsLocationKey标志来检查我们是否从后台启动,如果是这样,我们开始显着的位置监控,否则我们在前台启动,我们开始更新位置。

苹果回到我们这里,并指出使用重要的位置监测不需要在Info.plist中的UIBackgroundModes数组中设置的位置。 我们删除了这个条目,看起来电池耗尽状态不再受到打击。 UIBackgroundModes列表中还有蓝牙中心。 目前我们还不清楚为什么这有助于。 我们将运行更多的实验来帮助我们更好地理解这一点。 如果有人有任何build议,请让我们知道。

在一天结束的时候,苹果build议从UIBackgroundModes中删除位置,这就解决了我们的电池漏电问题。

为了仍然在后台获取位置信息,我们必须使用以下命令来封装[locationManager startLocationUpdates][locationManager stopLocationUpdates]调用:

 [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler]; [[UIApplication sharedApplication] endBackgroundTask:]; 

您可以使用任何重复的信号声音debugging应用程序的状态。 只要确保在本次testing的背景模式要求中没有放置“播放audio”。 如果你的应用程序运行 – 你会听到这听起来即使应用程序在后台。 如果应用程序被暂停 – 你什么也听不到。 这可能是最简单的方法来检测应用程序没有正确挂起。

使用Profiler对这个问题进行debugging是有问题的,因为当设备连接到计算机时,在debugging模式下,许多事情都会有所不同。 尤其是省电的东西。

此外,请确保您做的一切正确,以应对重大的位置变化。 如果你开始位置更新 – 确保你已经设置了一些closures位置更新的计时器(例如3分钟)。 无论如何,iOS会杀死你的应用程序,甚至开始从响应重大的位置更改的位置更新。 无论你做了什么回应 – 如果仍在运行,应用程序将在10分钟内死亡 – 注意崩溃日志 – 这样的事件将被logging在那里。

另外,请检查您的所有第三方代码和库 – 也许其中一些变成GPS并用于某些事情。 主要是偏执狂,但可能出于分析和广告定位的目的。

CoreLocation启用的应用程序通常用于后台模式,所以它可以在后台运行,绝对使用更多的电池,因为我的build议总是试图停止位置服务时,不需要。

[locationManager stopUpdatingLocation];

然后根据您的要求然后启动,

谢谢