产品动态

使用 Android Vitals 唤醒锁定指标优化应用电池用量

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

电池续航时间是用户体验的一个重要方面,而唤醒锁定在其中发挥着重要作用。您是否过度使用了唤醒锁定?在这篇博文中,我们将探讨唤醒锁定是什么、使用唤醒锁定的一些最佳实践,以及如何通过 Play 管理中心指标更好地了解您自己的应用的行为。

Android Vitals 中过度使用局部唤醒锁定

Play 管理中心现在会监控电池耗电量,并将过度使用局部唤醒锁定 作为一项关键性能指标。

此功能提升了电池效率的重要性,与现有的核心指标稳定性指标(用户感知到的崩溃和 ANR 过多)并列。我们为过度使用唤醒锁定定义了不良行为阈值。从 2026 年 3 月 1 日起,如果您的应用不符合此质量阈值,我们可能会将该应用从醒目的曝光途径(例如推荐)中排除。在某些情况下,我们可能会在您的商品详情中显示一条警告,向用户表明您的应用可能会导致电池耗电过多。

warning.png

__Android Vitals 概览__中的过度使用唤醒锁定警告。

对于移动设备,Android Vitals 指标适用于在屏幕关闭且应用在后台运行或运行前台服务时获取的非豁免唤醒锁定。如果出现以下情况,Android Vitals 会认为局部唤醒锁定使用过多:

  • 在 24 小时内,唤醒锁定至少保持了 2 小时。
  • 在 28 天内,平均有超过 5% 的应用会话受到影响。

音频位置信息JobScheduler 用户发起的 API 创建的唤醒锁定不计入唤醒锁定计算。

了解唤醒锁定

唤醒锁定是一种机制,可让应用即使在用户未主动与设备互动时也能保持设备 CPU 运行。

局部唤醒锁定可让 CPU 即使在屏幕关闭时也能保持运行,防止 CPU 进入低功耗“暂停”状态。完全唤醒锁定可让屏幕和 CPU 都保持运行。

局部唤醒锁定可通过以下 2 种方法获取:

  • 应用针对特定用例使用 PowerManager API 手动获取和释放唤醒锁定;通常,此唤醒锁定与 前台服务(一种旨在用于用户可感知操作的平台生命周期 API)一起获取。
  • 或者,唤醒锁定由另一个 API 获取,并因使用该 API 而归因于应用;如需了解详情,请参阅最佳实践部分。

虽然唤醒锁定对于完成用户发起的大型文件下载等任务是必需的,但过度或不当使用唤醒锁定可能会导致电池耗电过多 。我们发现,有些应用会保持唤醒锁定数小时,或者无法正确释放唤醒锁定,导致用户抱怨即使在不与应用互动时,电池耗电量也会过多。

唤醒锁定使用最佳实践

在介绍如何调试过度使用唤醒锁定的问题之前,请确保您遵循了唤醒锁定最佳实践。

请考虑以下四个关键问题。


1. 您是否考虑过其他唤醒锁定选项?

在考虑获取手动局部唤醒锁定之前,请遵循以下决策流程图:

wakelock.png

用于确定何时手动获取唤醒锁定的流程图

  1. 屏幕是否需要保持开启状态?
  2. 应用是否正在运行前台服务?
    • 否:您无需手动获取唤醒锁定。
  3. 如果设备暂停,是否会对用户体验造成不利影响?
    • 否:例如,在设备唤醒后更新通知不需要唤醒锁定。
    • 是:如果防止设备暂停至关重要(例如与外部设备进行持续通信),请继续。
  4. 是否有 API 已经代表您保持设备唤醒状态?
  5. 如果您已回答所有这些问题,并且确定没有其他替代方案,则应继续手动获取唤醒锁定。

**2. 您是否正确命名了唤醒锁定?

手动获取唤醒锁定时,正确的命名对于调试非常重要:

  • 在名称中省去任何个人身份信息 (PII),例如电子邮件地址。如果检测到 PII,唤醒锁定将记录为 _UNKNOWN,从而妨碍调试。
  • 请勿使用类名或方法名称以编程方式命名唤醒锁定,因为这些名称可能会被 Proguard 等工具混淆。您可以改用硬编码字符串。
  • 请勿向唤醒锁定标签添加计数器或唯一标识符。每次运行唤醒锁定时都应使用相同的标签,以便系统按名称汇总使用情况,从而更轻松地检测异常行为。

3. 获取的唤醒锁定是否始终会被释放?

如果您是手动获取唤醒锁定,请确保始终执行唤醒锁定释放。未能释放唤醒锁定可能会导致电池耗电过多。

例如,如果在 processingWork() 期间抛出未捕获的异常,则可能永远不会发生 release() 调用。您可以改用 try-finally 代码块来保证唤醒锁定会被释放,即使发生异常也是如此。

此外,您还可以为唤醒锁定添加超时,以确保其在特定时间段后释放,防止其无限期保持。

fun processingWork() {
    wakeLock.apply {
        try {
            acquire(60 * 10 * 1000) // timeout after 10 minutes
            doTheWork()
        } finally {
            release()
        }
    }
}

4. 您可以降低唤醒频率吗?

对于定期数据请求,减少应用唤醒设备的频率是电池优化的关键。以下是一些降低唤醒频率的示例:

您可以在唤醒锁定最佳实践文档中查看更多详细信息。

调试过度使用唤醒锁定的问题

即使是出于好意,也可能会出现过度使用唤醒锁定的情况。如果您的应用在 Play 管理中心内被标记,请按以下步骤进行调试:

使用 Play 管理中心进行初步识别

Android Vitals 过度使用局部唤醒锁定信息中心提供了与您的应用关联的非豁免唤醒锁定名称的细分数据,显示了受影响的会话和时长。请注意,您可以使用文档来帮助您确定唤醒锁定名称是由应用保持还是由其他 API 保持。

breakdowns2.png

Android Vitals 过度使用局部唤醒锁定信息中心向下滚动到细分数据部分,以查看过度使用唤醒锁定标签。

调试工作器/作业保持的过度使用唤醒锁定

您可以使用以下唤醒锁定名称来识别工作器保持的唤醒锁定:

*job*/<package_name>/androidx.work.impl.background.systemjob.SystemJobService

文档中提供了工作器保持的唤醒锁定名称的所有变体,请参阅文档。如需调试这些唤醒锁定,您可以使用后台任务检查器在本地进行调试,也可以利用 getStopReason 在现场调试问题。

Android Studio 后台任务检查器

taskinspector.png


后台任务检查器的屏幕截图,其中能够识别出频繁重试但失败的工作器“WeatherSyncWorker”。

如需在本地调试 WorkManager 问题,请在模拟器或已连接的设备(API 级别 26 及更高版本)上使用此工具。它会显示工作器及其状态(已完成、正在执行、已排队)的列表,让您可以检查详细信息并了解工作器链。

例如,它可以显示工作器是否因达到系统限制而频繁失败或重试。

如需了解详情,请参阅后台任务检查器文档

WorkManager getStopReason

如需在现场调试具有过度使用唤醒锁定的工作器,请在 WorkManager 2.9.0 及更高版本上使用 WorkInfo.getStopReason(),或对于 JobScheduler,请使用 SDK 31 及更高版本上提供的 JobParameters.getStopReason()

此 API 可帮助记录工作器停止的原因(例如 STOP_REASON_TIMEOUTSTOP_REASON_QUOTA),从而找出问题,例如因运行时时长耗尽而频繁超时。

backgroundScope.launch {
    WorkManager.getInstance(context)
        .getWorkInfoByIdFlow(workRequest.id)
        .collect { workInfo ->
            logStopReason(workRequest.id, workInfo?.stopReason)
        }
}

如需了解详情,请参阅针对任务调度 API 优化电池用量

调试其他类型的过度使用唤醒锁定

对于涉及手动保持的唤醒锁定或保持唤醒锁定的 API 等更复杂的场景,我们建议您使用系统跟踪记录收集进行调试。

系统跟踪记录收集

系统跟踪记录 是一种强大的调试工具,可捕获一段时间内系统活动的详细记录,提供有关 CPU 状态、线程活动、网络活动以及电池相关指标(例如作业时长和唤醒锁定使用情况)的洞见。

您可以使用多种方法捕获系统跟踪记录:

powermgmt.png

 在 Perfetto 界面的 Android 应用和服务标签页下启用“power:PowerManagement”Atrace 类别。

无论选择哪种方法,都必须确保收集 “power:PowerManagement”Atrace 类别 ,以便查看设备状态轨迹。

Perfetto 界面检查和 SQL 分析

您可以在 Perfetto 界面 中打开和检查系统跟踪记录。打开跟踪记录后,您将看到时间轴上各种进程的可视化效果。在本指南中,我们将重点介绍“设备状态”下的轨迹。

perfetto.png


固定“设备状态”下的轨迹,例如“热门应用”“屏幕状态”“长时间唤醒锁定”和“作业”轨迹,以直观地识别长时间运行的唤醒锁定切片。

每个代码块都会列出事件的名称、事件的开始时间和结束时间。在 Perfetto 中,这称为切片。

如需对多个跟踪记录进行可扩缩的分析,您可以使用 Perfetto 的 SQL 分析。SQL 查询可以找到按时长排序的所有唤醒锁定,帮助识别导致过度使用的主要因素。

以下是一个示例查询,用于汇总系统跟踪记录中发生的所有唤醒锁定标签,并按总时长排序:

SELECT slice.name as name, track.name as track_name,SUM(dur / 100000) as total_dur_ms
FROM slice
JOIN track ON slice.track_id = track.id
WHERE track.name = 'WakeLocks'GROUP BY slice.name, track.name
ORDER BY total_dur_ms DESC

使用 ProfilingManager 进行现场跟踪记录收集

对于难以重现的问题,ProfilingManager(在 SDK 35 中添加)是一种程序化 API,可让开发者在现场使用开始和结束触发器收集系统跟踪记录。它可以更好地控制配置文件收集的开始和结束触发点,并强制执行系统级速率限制,以防止影响设备性能。

如需了解有关如何在现场实现系统跟踪记录收集的后续步骤,请查看 ProfilingManager 文档,其中包括如何以编程方式 捕获跟踪记录分析性能分析数据以及使用 本地调试命令

使用 ProfilingManager 收集的系统跟踪记录与手动收集的跟踪记录类似,但系统进程和其他应用进程会从跟踪记录中删除。

总结

Android Vitals 中的过度使用局部唤醒锁定指标只是我们持续致力于帮助开发者减少电池耗电量和提高应用质量的一小部分。

通过了解和正确实现唤醒锁定,您可以显著优化应用的电池性能。利用替代 API、遵循唤醒锁定最佳实践,以及使用强大的调试工具(例如后台任务检查器、系统跟踪记录和 ProfilingManager)是确保您的应用在 Google Play 上取得成功的关键。

作者:

继续阅读