操作指南

电池技术质量强制执行措施已推出:如何优化常见的唤醒锁定使用情形

8 分钟阅读时间
Alice Yuan
开发者关系工程师

考虑到 Android 用户最先想到电池消耗过快的问题,Google 一直在采取重大措施,帮助开发者构建能效更高的应用。自 2026 年 3 月 1 日 起,Google Play 商店开始推出 唤醒锁定技术质量处理措施,以改善耗电问题。此处理措施将在接下来的几周内逐步推广到受影响的应用。如果应用在 Android Vitals 中持续超出“过度局部唤醒锁定”阈值,可能会对其在商店中的展示产生切实的影响,包括在商品详情中显示警告 ,并被排除在推荐等发现途径之外。

appDetails.png

如果应用超出不良行为阈值,用户可能会在您的商品详情中看到警告。 

此举将电池效率提升为核心 Vitals 指标,与崩溃和 ANR 等稳定性指标并列。“不良行为阈值”是指在 过去 28 天内 ,当屏幕关闭时,在超过 5% 的用户会话 中,平均持有非豁免的局部唤醒锁定至少 2 小时 。如果唤醒锁定是系统持有的唤醒锁定,可提供明确的用户利益且无法进一步优化,例如音频播放、位置信息访问权限或用户发起的数据传输,则该唤醒锁定可豁免。如需查看过度唤醒锁定的完整定义,请参阅我们的 Android Vitals 文档

为了持续改进整个 Android 生态系统的电池续航时间,我们分析了数千个应用及其使用局部唤醒锁定的方式。虽然有时需要使用唤醒锁定,但我们经常看到应用以低效或不必要的方式持有唤醒锁定,而更高效的解决方案是存在的。这篇博文将介绍最常见的过度唤醒锁定使用情形,以及我们针对优化唤醒锁定的建议。我们已经看到 WHOOP 等合作伙伴取得了显著的成功,他们利用这些建议优化了后台行为。

使用前台服务与局部唤醒锁定

我们经常看到开发者在执行后台操作时难以理解前台服务和局部唤醒锁定这两个概念之间的区别。

前台服务是一种生命周期 API,用于向系统发出信号,表明应用正在执行用户可感知的工作,不应终止以回收内存,但它不会在屏幕关闭时自动阻止 CPU 进入休眠状态。相比之下,局部唤醒锁定是一种专门用于在屏幕关闭时保持 CPU 运行的机制。

虽然前台服务通常是继续用户操作所必需的,但只有在 CPU 活动期间与前台服务结合使用时,才需要手动获取局部唤醒锁定。此外,如果您已使用可保持设备唤醒状态的 API,则无需使用唤醒锁定。

请参阅 _选择合适的 API 以保持设备唤醒状态_ 中的流程图,确保您充分了解在不必要的情况下应使用哪种工具来避免获取唤醒锁定。

第三方库获取唤醒锁定

应用通常会发现,它被标记为持有过多的唤醒锁定,这些唤醒锁定由第三方 SDK 或代表其执行操作的系统 API 持有。如需识别和解决这些唤醒锁定问题,我们建议执行以下步骤:

  • 检查 Android Vitals: 在 过度局部唤醒锁定信息中心 中找到违规唤醒锁定的确切名称。将此名称与 识别由其他 API 创建的唤醒锁定 指南进行交叉引用,以查看该唤醒锁定是否由已知的系统 API 或 Jetpack 库创建。如果是,您可能需要优化 API 的使用方式,并可以参阅推荐的指南。
  • 捕获系统跟踪记录: 如果无法轻松识别唤醒锁定,请使用系统跟踪记录在本地重现唤醒锁定问题,并使用 Perfetto 界面检查该问题。如需详细了解如何执行此操作,请参阅这篇博文的 调试其他类型的过度唤醒锁定 部分
  • 评估替代方案: 如果低效的第三方库是造成问题的原因,并且无法配置为尊重电池续航时间,请考虑与 SDK 的所有者沟通此问题,寻找替代 SDK 或自行构建该功能。

常见的唤醒锁定使用情形

下面列出了一些我们审核过的特定使用情形,以及优化唤醒锁定实现的推荐方法。

用户发起上传或下载

使用情形示例

  • 视频流式传输应用,用户触发下载大型文件以供离线访问。
  • 媒体备份应用,用户通过通知提示触发上传最近的照片。

如何减少唤醒锁定: 

  • 请勿获取手动唤醒锁定。请改用用户发起的数据传输 (UIDT) API。这是用户发起的长时间运行的数据传输任务的指定路径,并且不计入过度唤醒锁定计算。

一次性或定期后台同步

使用情形示例

  • 应用执行定期后台同步以提取数据,供离线访问。 
  • 计步器应用,定期提取步数。

如何减少唤醒锁定

  • 请勿获取手动唤醒锁定。使用 WorkManager 配置为一次性或定期工作。WorkManager 通过批量处理任务来尊重系统健康状况,并且具有最短的定期间隔(15 分钟),这通常足以满足后台更新的需求。 
  • 如果您发现由 WorkManager 或 JobScheduler 创建的唤醒锁定具有较高的唤醒锁定使用率,可能是因为您错误地配置了工作器,使其在某些情况下无法完成工作。请考虑分析工作器停止原因,尤其是在看到STOP_REASON_TIMEOUT频繁出现时。 
workManager.getWorkInfoByIdFlow(syncWorker.id)
  .collect { workInfo ->
      if (workInfo != null) {
        val stopReason = workInfo.stopReason
        logStopReason(syncWorker.id, stopReason)
      }
  }
  • 除了记录工作器停止原因之外,请参阅我们关于 调试工作器 的文档。此外,请考虑收集和分析 系统跟踪记录 ,以了解何时获取和释放唤醒锁定。
  • 最后,请查看我们与 WHOOP 的案例研究,他们能够发现工作器配置方面的问题,并显著减少唤醒锁定的影响。

蓝牙通信

使用情形示例

  • 配套设备应用提示用户配对蓝牙外部设备。
  • 配套设备应用监听外部设备上的硬件事件和通知中用户可见的更改。
  • 配套设备应用的用户发起移动设备和蓝牙设备之间的文件传输。
  • 配套设备应用通过蓝牙对外部设备执行偶尔的固件更新。

如何减少唤醒锁定

  • 使用 配套设备配对 配对蓝牙设备,以避免在蓝牙配对期间获取手动唤醒锁定。 
  • 请参阅 在后台通信指南,了解如何在后台进行蓝牙通信。 
  • 如果延迟通信不会对用户造成影响,则通常使用 WorkManager 就足够了。如果认为手动唤醒锁定是必要的,则仅在蓝牙活动期间或处理活动数据期间持有唤醒锁定。

地理位置跟踪

使用情形示例

  • 健身应用,缓存位置数据以供日后上传,例如绘制跑步路线
  • 外卖应用,以高频率提取位置数据,以在通知或微件界面中更新配送进度。

如何减少唤醒锁定

  • 请参阅我们的指南,了解如何 优化位置信息使用方式。请考虑实现超时、利用位置信息请求批处理或利用被动位置信息更新来确保电池效率。
  • 使用 FusedLocationProvider 或 LocationManager API 请求位置信息更新 时,系统会在位置信息事件回调期间自动触发设备唤醒。这种短暂的系统管理的唤醒锁定不计入过度局部唤醒锁定计算。
  • 避免获取单独的连续唤醒锁定来缓存位置数据,因为这是多余的。请改为将位置信息事件保留在内存或本地存储空间中,并利用 WorkManager 以定期间隔处理这些事件。
override fun onCreate(savedInstanceState: Bundle?) {
    locationCallback = object : LocationCallback() {
        override fun onLocationResult(locationResult: LocationResult?) {
            locationResult ?: return
            // System wakes up CPU for short duration
            for (location in locationResult.locations){
                // Store data in memory to process at another time
            }
        }
    }
}

高频传感器监控

使用情形示例

  • 计步器应用,被动收集步数或行进距离。 
  • 安全应用,实时监控设备传感器以快速变化,提供崩溃检测或跌倒检测等功能。

如何减少唤醒锁定

  • 如果使用 SensorManager,请将使用频率降低到定期间隔,并且仅在用户通过界面互动明确授予访问权限时使用。由于发生的 CPU 唤醒和处理次数较多,高频传感器监控可能会大量消耗电池电量。
  • 如果您要跟踪步数或行进距离,请不要使用 SensorManager,而是利用 Recording API,或考虑利用 健康数据共享 访问历史和汇总的设备步数,以省电的方式捕获数据。
  • 如果您要使用 SensorManager 注册传感器,请指定 maxReportLatencyUs 为 30 秒或更长时间,以利用 传感器批处理 尽可能减少 CPU 中断的频率。当设备随后被其他触发器(例如用户互动、位置信息检索或预定作业)唤醒时,系统会立即调度缓存的传感器数据。
val accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)

sensorManager.registerListener(this,
                 accelerometer,
                 samplingPeriodUs, // How often to sample data
                 maxReportLatencyUs // Key for sensor batching 
              )
  • 如果您的应用需要位置数据和传感器数据,请同步其事件检索和处理。通过将传感器读数附加到系统为位置信息更新保留的短暂唤醒锁定,您可以避免需要唤醒锁定来保持 CPU 唤醒。使用工作器或短时唤醒锁定来处理此组合数据的上传和处理。

远程消息传递

使用情形示例

  • 视频或声音监控配套应用,需要监控使用本地网络连接的外部设备上发生的事件。
  • 消息传递应用,与桌面版保持网络套接字连接。

如何减少唤醒锁定

  • 如果可以在服务器端处理网络事件,请使用 FCM 在客户端接收信息。如果需要对 FCM 数据进行额外处理,您可以选择安排加速工作器。 
  • 如果必须通过套接字连接在客户端处理事件,则无需唤醒锁定来监听事件中断。当数据包到达 WLAN 或移动网络无线装置时,无线装置硬件会以内核唤醒锁定的形式触发硬件中断。 然后,您可以选择安排工作器或获取唤醒锁定来处理数据。
  • 例如,如果您使用 ktor-network 监听网络套接字上的数据包,则仅应在数据包已传送给客户端且需要处理时获取唤醒锁定。
val readChannel = socket.openReadChannel()
while (!readChannel.isClosedForRead) {
    // CPU can safely sleep here while waiting for the next packet
    val packet = readChannel.readRemaining(1024) 
    if (!packet.isEmpty) {
         // Data Arrived: The system woke the CPU and we should keep it awake via manual wake lock (urgent) or scheduling a worker (non-urgent)
         performWorkWithWakeLock { 
              val data = packet.readBytes()
              // Additional logic to process data packets
         }
    }
}

摘要

通过针对后台同步、位置信息跟踪、传感器监控和网络通信等常见使用情形采用这些推荐的解决方案,开发者可以努力减少不必要的唤醒锁定使用。如需继续学习,请阅读我们的其他技术博文,或观看我们的技术视频,了解如何发现和调试唤醒锁定:使用 Android Vitals 唤醒锁定指标优化应用电池。此外,请参阅我们更新后的唤醒锁定文档。为了帮助我们继续改进技术资源,请在我们的 文档反馈调查中分享您对指南的任何其他反馈。

作者:

继续阅读