【问题标题】:Battery drain when using CoreLocation Significant Location Monitoring & CoreBluetooth使用 CoreLocation 重要位置监控和 CoreBluetooth 时的电池消耗
【发布时间】:2012-03-19 18:32:58
【问题描述】:

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

在高层次上,我们的应用只查找CoreBluetooth 断开连接事件并打开 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

最初我们无法自己复制排水问题,但我们发现,当我们安装一个简单的应用程序时,它刚刚打开了重要位置监控以及 Find My Car Smarter,我们间歇性地看到排水问题重现。在排水状态下,手机不会进入休眠状态。这由(设置->使用->自上次完全充电以来的时间)中的使用时间指示,即使手机已进入睡眠状态且显示屏关闭,也会继续增加。有些东西阻止系统进入休眠状态。在这个阶段,电池每小时消耗大约 15%。这种排水断断续续地出现,似乎在一两个小时后自行清除,然后随机再次出现。我们还没有找到可靠再现流失的方法。

我们认为该问题是由多个客户端调用 CoreLocation 引起的。我们要求一些遇到此问题的用户擦除他们的手机并仅安装我们的 Find My Car Smarter 应用程序。仅安装此应用程序,排水管就没有表现出来。我们有其他报告称,当我们的应用程序与谷歌纵横或 Facebook 等一起使用时,他们会看到出现流失。或者,如果他们去杀死其他应用程序,流失就会消失。我们已经看到在电源循环中持续消耗,没有启动任何应用程序。这意味着它必须是防止操作系统休眠的系统级服务。

尽管我们认为该问题是由多个客户端调用 CoreLocation 的某种竞争条件引起的,但我们从未发现仅使用 CoreLocation 的应用会重现该问题。我们甚至创建了 4 或 5 个不同的应用程序,它们可以同时访问 CoreLocation,而且我们没有看到出现消耗。然而,当我们有一个带有 CoreLocation 的应用程序和另一个带有 CoreLocation + CoreBluetooth 的应用程序时,我们确实看到了这个问题。可能很少有应用程序使用 CoreLocation + CoreBluetooth 组合,因此可能这就是更多开发人员没有遇到此问题的原因。尽管我们无法解释 CoreLocation 和 CoreBluetooth 如何交互导致这种消耗以及第二个具有 CoreLocation 的应用程序如何进入等式。由于排水是间歇性的,因此问题可能只是在我们使用 CoreLocation + CoreBluetooth 进行测试时才发生。

在只安装了这两个应用程序 CTM1 和 FMC 的已擦除 5.0.1 iPhone 4S 上,我们能够间歇性地进入排水状态。有趣的是,与我们的普通设备相比,擦除设备上的排水问题似乎要少得多。不幸的是,我们只看到了几次流失状态,并且无法可靠地重现流失,我们没有良好的控制状态可以工作。

我们已向 Apple 提交了错误报告并公开了技术支持事件,但也许 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];

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

我们确实有另一个问题,如果我们同时使用 GPS 和重要位置监控,是否有理由致电 stopMonitoringSignificantLocationChanges?查看他们在进入前台时调用 stopMonitoringSignificantLocationChangesstartLocationUpdate 并在进入后台时调用 stopLocationUpdatestartMonitoringSignificantLocationChanges 的区域示例代码,但我想知道这是否必要/推荐/必需?

更新:

我们已与 Apple 开发者技术支持确认,对于同时使用 GPS 和重要位置监控的应用程序,我们在启用 GPS 更新之前关闭重要位置监控的顺序是正确的。

我们还确认,在 GM 5.1 和针对 5.1 框架重新编译的 Find My Car Smarter 应用程序中仍然可以看到排水问题。

更新:

当我们的应用从后台启动以响应重要的位置监控事件时,似乎触发了该问题。我们实际上并没有在示例代码中正确处理这种情况,但我们在实际的应用程序中这样做了。

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

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

Apple 回复我们并表示使用重要位置监控不需要在 Info.plist 的 UIBackgroundModes 数组中设置位置。我们删除了此条目,看来电池耗尽状态不再受到影响。我们在 UIBackgroundModes 列表中仍然有 bluetooth-central。目前我们还不清楚为什么这会有所帮助。我们将进行更多实验,以帮助我们更好地理解这一点。如果有人有任何建议,请告诉我们。

【问题讨论】:

  • Instruments 中有一个合适的电池消耗分析器。
  • “然后我们使用重要位置监控来自动重新启动我们的应用程序,以防系统终止我们的应用程序。”你能解释一下你的意思吗?我正在尝试找到一种解决方案来确保 BTLE 在后台持续存在。截至目前,在后台运行 5 分钟后,我的 iOS 应用程序失去了 BTLE 接收功能。
  • @user2057736 免责声明:我不知道我在说什么。但是OP甚至自己也说过这一点。在UIBackgroundModes 中设置蓝牙,让您的蓝牙保持活跃。

标签: ios core-location cllocationmanager power-management core-bluetooth


【解决方案1】:

最终,Apple 建议从 UIBackgroundModes 中删除位置,从而解决了我们的电池消耗问题。

为了仍然在后台获取位置,我们必须将 [locationManager startLocationUpdates][locationManager stopLocationUpdates] 调用包装为:

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

【讨论】:

  • 你能粘贴一个如何做到这一点的例子吗?据我所知,beginBackgroundTaskWithExpirationHandler 只会给你 10 分钟的后台时间。如果您没有将应用设置为 UIBackgroundModes,它不会因为位置变化而“唤醒”...
  • 即使在 UIBackgroundModes 中未设置位置,如果您的应用已调用 startMonitoringSignificantLocationChanges,它仍会在发生重大位置更改事件时重新启动。执行的时间不会超过几秒钟,这就是 beginBackgroundTaskWithExpirationHandler 发挥作用的地方,最多可为您提供 10 分钟的执行时间。这对我们来说也是新闻,没有明确记录。这是一个 beginBackgroundTaskWithExpirationHandler 示例stackoverflow.com/questions/7346278/…
  • 所以我应该在 "locationManager:didUpdateToLocation:FromLocation" 中添加 beginBackgroundTaskWithExpirationHandler 以在位置更新后再获得 10 分钟,对吗?
  • 在我们的应用程序中,当我们收到didDisconnectPeripheral 回调时,我们调用beginBackgroundTaskWithExpirationHandler 这给了我们最多10 分钟的时间来获得GPS 定位,然后我们调用startUpdatingLocation,等到我们得到一个准确的 GPS 定位并致电 stopUpdatingLocationendBackgroundTask。这可能不适用于您的应用程序。我认为您不想在locationManager:didUpdateToLocation:FromLocation 中拨打beginBackgroundTaskWithExpirationHandler,因为您可能最终永远不会让手机进入睡眠状态,这会导致电池耗尽。
  • iOS 6、7 或 8 中是否修复了这个错误?
【解决方案2】:

您可以使用任何重复的信号声音来调试应用的状态。只需确保您没有在此测试的背景模式要求中添加“播放音频”。 如果您的应用程序正在运行 - 即使应用程序在后台,您也会听到这种声音。如果应用程序被暂停 - 您将听不到任何声音。这可能是检测应用程序未正确挂起的最简单方法。

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

另外,请确保您在应对重大位置变化时采取正确的措施。如果您开始位置更新 - 请确保您设置了一些关闭位置更新的计时器(例如 3 分钟)。 无论如何,iOS 会杀死你的应用程序,即使它从响应重大位置变化开始位置更新。不管你做了什么开始响应 - 如果应用程序仍在运行,它将在 10 分钟内被终止 - 请注意崩溃日志 - 此类事件将记录在那里。

另外,请检查您所有的第 3 方代码和库 - 也许其中一些会打开 GPS 并将其用于某些用途。主要是偏执狂,但可能出于分析和广告定位目的而发生。

【讨论】:

  • 好建议!不幸的是,如果我们没有在 UIBackgroundModes 中声明音频,即使我们的应用程序正在运行,也不会播放音频。如果我们确实将音频放在 UIBackgroundModes 中,那么音频播放会导致我们的应用程序不会挂起。
【解决方案3】:

启用CoreLocation的应用程序通常是为后台模式制作的,所以它可以在后台运行,肯定会消耗更多的电池,因为我的建议是在不需要的时候尝试停止定位服务。

[locationManager stopUpdatingLocation];

然后根据您的要求然后相应地开始,

谢谢

【讨论】:

  • 我们绝对不会让 startUpdatingLocation 或 startUpdatingHeading 保持开启状态,我们会在此回调获取时放置调试消息,并且可以判断这不是导致问题的原因。
猜你喜欢
  • 2012-11-30
  • 1970-01-01
  • 1970-01-01
  • 2014-08-21
  • 2016-05-14
  • 2013-07-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多