本文档可帮助您识别和优化应用中的唤醒锁定使用情形,并突出显示其他库或系统 API 是否获取了与此使用情形关联的唤醒锁定。 由于这些唤醒锁定可归因于您的应用,因此很难查明有问题的唤醒锁定的来源。即使您未明确获取唤醒锁定,不正确的 API 用法也可能会导致您的应用因过度使用唤醒锁定而被标记。
本文档列出了一些常见唤醒锁名称,您在使用唤醒锁调试工具时或在健康状态报告中可能会遇到这些名称。这些名称可能源自库或系统 API,也可能经过混淆处理。通过使用调试工具来识别行为异常的唤醒锁定,然后在本文档中搜索唤醒锁定名称,您可以确定哪个 API 可能导致了问题,并找到有关如何优化其使用的建议。
本文档概述了获取唤醒锁的常见用例,详细介绍了各种 API 和库使用的唤醒锁名称,并提供了有关优化和减少唤醒锁使用的建议和最佳实践。
- AlarmManager
- 音频和媒体
- 蓝牙
- 设备传感器
- Firebase Cloud Message (FCM)
- JobScheduler
- 位置信息
- 远程消息传递
- WorkManager
_UNKNOWN:如果唤醒锁名称似乎使用了个人身份信息 (PII),调试工具会显示此问题。
AlarmManager
AlarmManager 会获取唤醒锁定并将它们归因于调用应用。AlarmManager 会在闹钟响起时获取唤醒锁定,并在闹钟广播的 onReceive() 方法执行完毕时释放锁定。
唤醒锁定名称
AlarmManager 创建名为 *alarm* 的唤醒锁。(星号是唤醒锁名称的一部分,不代表通配符。)
建议
我们建议您采取以下做法来优化闹钟行为:
- 请参阅选择闹钟类型,以确定选择非精确闹钟还是精确闹钟。 如果闹钟不需要精确到秒,请使用非精确闹钟,以便系统在安排闹钟时有更大的灵活性,从而延长电池续航时间。
- 请注意系统施加的闹钟配额,并设计您的应用以遵守这些配额。
- 避免在
onReceive()方法中执行耗时较长的任务,如果闹钟响铃后需要进行额外处理,请安排工作器。
音频和媒体
媒体 API 在录制或播放音频时可以获取唤醒锁定。 唤醒锁定归因于调用方应用。
唤醒锁定名称
媒体 API 会获取以 Audio 开头的各种名称的唤醒锁定:
AudioBitPerfect:用于无损 USB 音频播放。AudioDirectOut:用于在电视或特殊设备上播放无损音频。AudioDup:用于在通过蓝牙或 USB 连接时播放通知。AudioIn:在摄像机模式下麦克风处于活动状态时,用于音频捕获。AudioMix:用于向通用设备播放音频。AudioOffload:用于长时间的纯音乐播放,适用于支持此模式的应用。AudioSpatial:用于在支持空间音频的设备上播放多声道电影或音乐音频。AudioUnknown:当其他情况均不适用时使用。MmapCapture:用于低延迟音频捕获。MmapPlayback:用于低延迟播放,例如游戏或专业音频应用。
建议
我们建议您采取以下做法:
- 不要声明以
Audio开头的唤醒锁定名称。 - 如果您使用的是媒体 API,则无需直接获取唤醒锁;您可以依靠这些 API 为您获取必要的唤醒锁。
- 使用媒体 API 时,如果不再需要媒体会话和关联的前台服务,请将其结束。
蓝牙
平台蓝牙 API 主要在蓝牙操作发生时持有内核唤醒锁,这不归因于应用。
建议
- 使用配套设备配对来配对蓝牙设备,以避免在蓝牙配对期间获取手动唤醒锁定。
- 请参阅在后台通信指南,了解如何进行后台蓝牙通信。
- 如果延迟通信不会对用户造成影响,通常使用
WorkManager就足够了。如果认为手动唤醒锁定是必要的,则仅在蓝牙活动或处理活动数据的持续时间内保持唤醒锁定。
设备传感器
您可以通过多种方法跟踪设备传感器数据,例如步数、加速度计或陀螺仪数据。
在 Wear OS 上,使用 Wear 健康服务来获取设备数据,例如海拔、心率和运动距离。
如果数据是由其他应用收集的,您可以结合使用 Health Connect 和 WorkManager 来定期检索数据。
对于跟踪步数或行进距离增量等场景,您可以结合使用移动设备上的 Recording API 和 WorkManager 来定期检索数据。如需访问历史步数数据(例如每日总步数或过去 6 小时的步数),对于搭载 Android 14 或更高版本的设备,健康数据共享还支持设备端步数跟踪。
在某些情况下,可能需要使用 SensorManager 进行自定义设备传感器跟踪。SensorManager 不会代表应用获取唤醒锁定,除非相应传感器是唤醒传感器(可以使用 isWakeUpSensor API 进行识别)。
建议
以高采样率使用传感器进行记录会消耗大量电池电量,以下是减少电池电量消耗和唤醒锁定使用量的建议:
- 如果需要跟踪步数或行进距离,请使用 Recording API 以省电方式记录数据。对于搭载 Android 14 或更高版本的设备,请考虑使用健康数据共享来访问历史设备步数和汇总步数。
- 如需在 Wear OS 上进行被动传感器跟踪,请使用 Wear 健康服务来优化电池用量。
- 使用
SensorManager注册传感器时,请定义一个超过 30 秒的maxReportLatencyUs,以使用传感器批处理逻辑并减少应用收到的中断次数。当设备随后因其他触发因素(例如用户互动、位置信息检索或预定作业)而被唤醒时,系统会立即调度缓存的传感器数据。 - 如果您的应用需要位置数据和传感器数据,请同步其事件检索和处理。通过将传感器读数合并到系统为位置信息更新而持有的短暂唤醒锁中,您可以避免需要唤醒锁来保持 CPU 唤醒。使用工作器或短时唤醒锁定来处理此组合数据的上传和处理。
Firebase Cloud Message (FCM)
在向应用传送 Firebase 云消息传递 (FCM) 广播时,会获取唤醒锁定。FCM 广播 onMessageReceived() 方法执行完毕后,唤醒锁定即会释放。
唤醒锁定名称
当设备收到 FCM 消息时,系统会短暂持有名称为 GOOGLE_C2DM 的唤醒锁;在 Android 16 及更高版本中,唤醒锁名称为 GCM_MESSAGE。
建议
我们建议您采取以下做法来优化 FCM 行为:
- 优化 FCM 传送频率。
- 除非消息确实需要立即传递,否则请勿使用高优先级 FCM。
- 让
onMessageReceived()方法尽快完成,或者安排工作器继续执行任务(如果需要进行额外处理)。如需了解详情,请参阅 Firebase 指南。
JobScheduler
JobScheduler 作业在后台执行任务时会获取唤醒锁定。唤醒锁归因于创建工作线程的应用。
唤醒锁定名称
JobScheduler 获取的唤醒锁名称取决于其运行的 Android 系统版本以及作业的用途。
尖括号中的项是变量。例如,“<package_name>”是应用的软件包名称,而不是字面文本 <package name>。不过,*job* 是字符序列 *job*,其中包含星号;这些星号并非用作通配符。
Android 15 及更低版本
用户发起的作业会创建遵循以下模式的唤醒锁:
*job*u/@<name_space>@/<package_name>/<classname>
其他作业使用此模式:
*job*/@<name_space>@/<package_name>/<classname>
Android 16 QPR2 及更高版本
用户发起的作业会创建遵循以下模式的唤醒锁:
*job*u/@<name_space>@/#<trace_tag>#/<package_name>/<classname>
加急作业使用以下模式:
*job*e/@<name_space>@/#<trace_tag>#/<package_name>/<classname>
常规作业使用以下模式:
*job*r/@<name_space>@/#<trace_tag>#/<package_name>/<classname>
示例
假设有一个命名空间为 backup 且轨迹标记为 started 的加急作业。软件包名称为 com.example.app,创建作业的类为 com.backup.BackupFileService。
在搭载 Android 15 或更低版本的设备上,唤醒锁的名称为:
*job*/@backup@/com.example.app/com.backup.BackupFileService
在搭载 Android 16 QPR2 或更高版本的设备上,唤醒锁的名称为:
*job*e/@backup@/#started#/com.example.app/com.backup.BackupFileService
建议
- 请勿为用户发起的下载/ 上传用例获取手动唤醒锁定。请改用由用户发起的数据传输 (UIDT) API。 这是用户发起的长时间运行的数据传输任务的指定路径。
- 如果您发现 JobScheduler 创建的唤醒锁的唤醒锁使用率很高,可能是因为您错误地配置了作业,导致作业在某些情况下无法完成。考虑分析作业的停止原因,尤其是在您发现
STOP_REASON_TIMEOUT出现频率很高时。 - 审核 JobScheduler 任务的使用情况。具体而言,请遵循我们关于优化任务调度 API 的电池使用的指南。
位置
LocationManager 和 FusedLocationProviderClient 使用唤醒锁定来获取和传递设备位置信息。唤醒锁定会归因于调用这些 API 的应用。
唤醒锁定名称
位置信息服务使用以下名称:
CollectionLib-SigCollectorNetworkLocationLocatorNetworkLocationScannerNlpCollectorWakeLockNlpWakeLock*location*
建议
- 请参阅我们关于优化位置信息使用的指南。考虑实现超时、利用位置信息请求批处理或使用被动位置信息更新。
- 避免获取单独的持续唤醒锁定来缓存位置数据,因为这是冗余的,应该移除。
使用
FusedLocationProvider或LocationManagerAPI 请求位置信息更新时,系统会在位置信息事件回调期间自动触发设备唤醒。请改为将位置事件存储在内存或存储空间中,并使用WorkManager定期处理位置事件。
远程消息传递
本部分讨论了涉及远程消息传递的场景,在这些场景中,应用可能需要保持连接或对来自其他设备的事件做出反应,这可能会影响唤醒锁的使用。常见用例包括:
- 需要监控通过本地网络连接的外部设备上发生的事件的视频或声音监控配套应用。
- 与桌面版保持网络套接字连接的即时通讯应用。
在这些远程消息传递场景中,大多数唤醒都是内核唤醒锁定。由于内核唤醒锁未归因于应用,因此此处没有要列出的关联唤醒锁名称。
建议
- 如果网络事件可以在服务器端处理,请使用 FCM 在客户端接收信息。如果需要对 FCM 数据进行额外处理,您可以选择安排加速工作器。
- 如果必须在客户端使用套接字连接处理事件,则无需唤醒锁定来监听事件中断。当数据包到达 Wi-Fi 或移动网络无线装置时,无线装置硬件会以内核唤醒锁的形式触发中断。然后,您可以选择安排工作器或获取唤醒锁定来处理数据。
- 例如,如果您使用
ktor-network在网络套接字上监听数据包,则只有在数据包已传递到客户端时,您才应获取唤醒锁。
WorkManager
WorkManager worker 在后台执行任务时会获取唤醒锁定。唤醒锁归因于创建工作线程的应用。
唤醒锁定名称
WorkManager 获取的唤醒锁名称取决于其运行的 Android 系统版本。
Android 15 及更低版本
WorkManager 任务会创建唤醒锁定,其名称遵循以下模式:
*job*/<package_name>/androidx.work.impl.background.systemjob.SystemJobService
Android 16 QPR2 及更高版本
加急任务会创建名称遵循以下格式的唤醒锁:
*job*e/#<trace_tag>#/<package_name>/androidx.work.impl.background.systemjob.SystemJobService
常规任务遵循以下模式:
*job*r/#<trace_tag>#/<package_name>/androidx.work.impl.background.systemjob.SystemJobService
默认情况下,<trace_tag> 是工作器的名称。
示例
假设有一个名为 BackupFileWorker 的加急工作器。软件包名称为 com.example.app。
在搭载 Android 15 或更低版本的设备上,唤醒锁的名称为:
*job*/com.example.app/androidx.work.impl.background.systemjob.SystemJobService
在搭载 Android 16 QPR2 或更高版本且使用 WorkManager 2.10.0+ 的设备上,唤醒锁的名称将为:
*job*e/#BackupFileWorker#/com.example.app/androidx.work.impl.background.systemjob.SystemJobService
建议
- 将 WorkManager 版本升级到最新稳定版,以便在 Android 16 QPR2 或更高版本上提供更详细的唤醒锁定标记。
- 审核 WorkManager 工作器的使用情况。特别是,验证它是否遵循了我们关于优化任务调度 API 的电池使用的指南。如需在 Android 16 QPR2 或更高版本上使唤醒锁定标记更详细,请使用工作器上的
setTraceTag方法添加更多调试信息,例如哪个类调度了工作器。 - 如果您发现 WorkManager 创建的唤醒锁具有较高的唤醒锁使用率,可能是因为您错误地配置了工作器,导致其在某些情况下无法完成。请考虑分析工作器停止原因,尤其是在
STOP_REASON_TIMEOUT出现频率较高时。 - 除了记录工作器停止原因之外,您还可以参阅有关调试工作器的文档。此外,还可以考虑收集和分析系统轨迹,以了解何时获取和释放唤醒锁定。
_UNKNOWN
如果调试工具认为唤醒锁定名称包含个人身份信息 (PII),则不会显示实际的唤醒锁定名称。而是将唤醒锁定标记为 _UNKNOWN。例如,如果唤醒锁名称包含电子邮件地址,工具可能会执行此操作。
建议
遵循唤醒锁定命名最佳实践,避免在唤醒锁定名称中使用个人身份信息。如果您发现归因于应用的唤醒锁定名为 _UNKNOWN,请尝试确定该唤醒锁定是哪个,并为其指定其他名称。