Android Doze低电耗休眠模式 与 WorkManager

1. Doze模式下,WorkManager setInitialDelay设置小于15分钟,被系统强制到15分钟执行,怎么办 ?

Android 拥有两项省电功能,通过管理设备未连接电源时应用的行为来延长用户电池续航时间:低电耗模式 (Doze) 和应用待机模式 (App Standby)。 低电耗模式 通过延迟设备长时间未使用时应用的后台 CPU 和网络活动来降低电池消耗。 应用待机模式 延迟没有近期用户活动的应用的后台网络活动。

设备处于低电耗模式时,应用对某些耗电资源的访问会被延迟,直到维护窗口。 具体限制列在电量管理限制中。

低电耗模式和应用待机模式管理在 Android 6.0 或更高版本上运行的所有应用的行为,无论它们是否专门针对 API 级别 23。为了帮助确保为用户提供最佳体验,请在低电耗模式和应用待机模式下测试您的应用,并对您的代码进行任何必要的调整。以下部分提供详细信息。

2. 了解低电耗模式(Doze)

如果用户将设备拔下电源并长时间静置,且屏幕关闭,设备就会进入低电耗模式。在低电耗模式下,系统会尝试通过限制应用对网络和 CPU 密集型服务的访问来节省电池电量。它还会阻止应用访问网络,并延迟其作业、同步和标准闹钟。

系统会定期短暂退出低电耗模式,让应用完成其延迟的活动。在此 维护窗口 期间,系统会运行所有待处理的同步、作业和闹钟,并允许应用访问网络。
在这里插入图片描述
维护窗口结束后,系统会再次进入低电耗模式,暂停网络访问并延迟作业、同步和闹钟。随着时间的推移,系统安排维护窗口的频率会降低,有助于在设备未充电且长时间不活动的情况下减少电池消耗。

当用户通过移动设备、打开屏幕或连接充电器来唤醒设备时,系统会退出低电耗模式,所有应用都会恢复正常活动。

3. 低电耗模式限制

设备处于低电耗模式时,系统会对您的应用施加以下限制:

  • 暂停网络访问。
  • 忽略唤醒锁。
  • 将标准 AlarmManager 闹钟(包括 setExact() 和 setWindow())延迟到下一个维护窗口。
    • 如果您需要在低电耗模式下触发闹钟,请使用 setAndAllowWhileIdle() 或 setExactAndAllowWhileIdle()。
    • 通过 setAlarmClock() 设置的闹钟会正常触发。系统会在这些闹钟触发前不久退出低电耗模式。
  • 不执行 Wi-Fi 扫描。
  • 不允许同步适配器运行。
  • 不允许 JobScheduler 运行。

⚠️ WorkManager 内部使用 JobScheduler,因此 WorkManager 任务不会运行。

具体详见 Android Developer | doze-standby

4. Doze模式下,WorkManager 为何无法精确时间执行 ?

通过上文,我们可以知道,在Doze模式下,WorkManager 任务不会运行,只有在两个Doze间隔期间,系统会定期短暂退出低电耗模式,让应用完成其延迟的活动。在此 维护窗口 期间,系统会运行所有待处理的同步、作业和闹钟,并允许应用访问网络。 这个时候WorkManager的任务才会被执行。但是两个Doze之间休眠时间的间隔是不确定的,所以Doze模式下,WorkManager无法精确时间被执行。

且如果WorkManager.setInitialDelay设置的时间小于15分钟,会被系统强制替换为15分钟。
那如果我就想10分钟后执行,需要怎么办呢 ?

5. Doze模式下,如何精确时间执行 ?

这个时候,就需要使用AlarmManager的setExactAndAllowWhileIdle方法了。 (虽然WorkManager在Android低版本上也是用的AlarmManager,但是并没有使用AlarmManager的setExactAndAllowWhileIdle方法)

那么如何使用呢 ?

5.1 ​​声明权限​

<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />

5.2 调用前需验证是否已授权

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);if (!alarmManager.canScheduleExactAlarms()) {// 引导用户前往设置页授权Intent intent = new Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM);intent.setData(Uri.parse("package:" + getPackageName()));startActivity(intent);return;}
}

5.3 创建 BroadcastReceiver​ : ​​接收闹钟触发事件

public class AlarmReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {// 执行任务逻辑(如启动服务、发送通知)Log.d("Alarm", "Triggered at exact time!");}
}

别忘了注册 Receiver​

<receiver android:name=".AlarmReceiver" android:exported="false"/>

5.4 设置精确闹钟​

// 获取 AlarmManager
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);// 创建 Intent 指向 BroadcastReceiver
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
);// 设置触发时间(例如 10 分钟后)
long triggerTime = System.currentTimeMillis() + 10 * 60 * 1000;// 根据版本选择方法
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, // 使用 UTC 时间并唤醒设备triggerTime, pendingIntent);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {alarmManager.setExact(AlarmManager.RTC_WAKEUP, triggerTime, pendingIntent);
} else {alarmManager.set(AlarmManager.RTC_WAKEUP, triggerTime, pendingIntent);
}

5.5 设置了AlarmManager,如果系统时间变更了,是不是闹钟在现实世界响起的时间也会变 ?

  • 若用户将系统时间​​调快 1 小时​​(从 9:00 改为 10:00),闹钟会​​立即触发​​(因为系统时间已达到目标值)。
  • 若将系统时间​​调慢 1 小时​​(从 10:00 改为 9:00),闹钟会​​延迟 1 小时触发​​(需等待系统时间再次达到 10:00)

可以监听系统时间变化的广播,然后更改闹钟

// 在 onResume() 中注册
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
registerReceiver(timeChangeReceiver, filter);// 在 onPause() 中注销
unregisterReceiver(timeChangeReceiver);

5.6 STATE_DOZE和STATE_DOZE_SUSPEND,有什么区别 ?

在 Android 电源管理机制中,STATE_DOZESTATE_DOZE_SUSPEND 是两种不同的休眠状态,其核心区别在于系统资源限制的严格程度CPU活动状态。以下是两者的详细对比:

6. STATE_DOZE 和 STATE_DOZE_SUSPEND

  • STATE_DOZE(Doze 模式)

    • 首次引入于 Android 6.0(Marshmallow),目的是在设备闲置时(未充电、屏幕关闭、静止状态)减少后台活动。
    • 状态描述:系统进入低功耗状态,但CPU仍保持部分活动,周期性唤醒处理任务。
  • STATE_DOZE_SUSPEND(Doze 挂起模式)

    • 强化版省电机制,于 Android 9.0(Pie) 引入,作为 Doze 的深度扩展。
    • 状态描述:系统进入更深度的休眠CPU 完全停止运行,仅保留最低限度的硬件唤醒能力(如传感器)。

6.1 CPU 与任务执行机制**

  • STATE_DOZE

    • CPU 未完全停止,而是周期性唤醒(维护窗口)。
    • 维护窗口间隔:初始为每 30 分钟唤醒一次,随后间隔逐渐延长(如 1 小时、2 小时)。
    • 任务处理:在维护窗口内,系统允许应用执行延迟的任务(如同步、AlarmManager 闹钟)。
  • STATE_DOZE_SUSPEND

    • CPU 完全挂起,无周期性唤醒。
    • 任务冻结:所有后台进程被强制暂停(通过 Linux cgroup 的 freezer 子系统),不再分配 CPU 时间片。
    • 唤醒条件:仅通过外部事件触发(如用户操作、高优先级闹钟 setAlarmClock())。

6.2 网络与后台资源访问

  • STATE_DOZE

    • 网络限制:禁止后台应用访问网络,仅维护窗口内开放。
    • 部分豁免:高优先级 GCM 消息、短信/电话可临时唤醒网络。
  • STATE_DOZE_SUSPEND

    • 完全断网:所有网络访问被禁止,包括 GCM 和短信(仅保留基础通信服务如通话)。
    • 硬件限制:Wi-Fi/GPS 扫描、传感器数据采集均暂停。

6.3 闹钟与任务调度行为

  • STATE_DOZE

    • 标准闹钟延迟setExact()setWindow() 的闹钟被推迟至下一个维护窗口。
    • 豁免闹钟setAndAllowWhileIdle()setExactAndAllowWhileIdle() 可在 Doze 下触发(但受每分钟 1 次的频率限制)。
  • STATE_DOZE_SUSPEND

    • 所有闹钟冻结:包括 AllowWhileIdle 类型的闹钟,仅 setAlarmClock()(用户可见的闹钟)可唤醒设备。
    • 任务调度失效:JobScheduler 和 WorkManager 任务被无限期推迟,直至退出 SUSPEND 状态。

6.4 Wakelock 处理

  • STATE_DOZE

    • 部分屏蔽:普通 WakeLock 被忽略(如 PARTIAL_WAKE_LOCK),但高优先级服务(如媒体播放)可能被豁免。
  • STATE_DOZE_SUSPEND

    • 完全无效:所有 WakeLock 被强制释放,无法阻止 CPU 挂起。

6.5 持续时间与退出机制

  • STATE_DOZE

    • 动态维护窗口:窗口间隔随闲置时间延长而增加(30 分钟 → 1 小时 → 数小时)。
    • 退出条件:屏幕点亮、设备移动或充电。
  • STATE_DOZE_SUSPEND

    • 持续挂起:无周期性窗口,直至外部事件唤醒。
    • 退出条件更严格:仅用户交互(如按键)、setAlarmClock() 闹钟或充电可唤醒。

6.6 对比总结

特性STATE_DOZESTATE_DOZE_SUSPEND
CPU 状态周期性唤醒(维护窗口)完全停止
网络访问仅维护窗口开放完全禁止
闹钟执行允许 AllowWhileIdle 类型setAlarmClock() 有效
任务调度维护窗口内执行完全冻结
Wakelock 有效性部分豁免全部释放
退出条件移动/亮屏/充电仅用户操作或高优先级闹钟
省电强度中度极端

6.7 适配建议

  1. 后台任务
    • 使用 WorkManagerJobScheduler,其任务在 STATE_DOZE 的维护窗口自动执行,但 STATE_DOZE_SUSPEND 中仍会被冻结。
  2. 实时性需求
    • 关键任务(如闹钟)优先用 setAlarmClock()(用户可见),或引导用户将应用加入电池优化白名单。
  3. 网络依赖
    • STATE_DOZE_SUSPEND 下网络完全不可用,需通过高优先级 GCM 消息或短信唤醒设备(系统服务如电话/SMS 始终豁免)。
  4. 状态检测
    • 通过 PowerManager.isDeviceIdleMode() 检测 Doze 状态,但无法直接区分 SUSPEND(需依赖行为推断)。

📌 核心结论
STATE_DOZE周期性唤醒的轻度休眠,适合延迟容忍的任务;
STATE_DOZE_SUSPENDCPU 完全停止的深度冻结,仅响应极高优先级事件。
开发者需针对两者设计降级策略,确保关键功能在极端省电下仍可工作。

7. STATE_DOZE_SUSPEND状态下设置setExactAndAllowWhileIdle有效吗

在 Android 的 STATE_DOZE_SUSPEND(深度挂起模式)状态下,setExactAndAllowWhileIdle() 是无效的。以下是具体原因和机制分析:


7.1 STATE_DOZE_SUSPEND 的特性

  • CPU 完全冻结
    此状态下系统进入深度休眠,CPU 完全停止运行,所有后台进程被强制暂停,仅保留基础硬件唤醒能力(如高优先级闹钟或物理按键)。
  • 网络与任务冻结
    所有网络访问被禁止,JobSchedulerWorkManager 等后台任务被无限期推迟,标准闹钟和 AllowWhileIdle 类闹钟均被冻结。

7.2 setExactAndAllowWhileIdle() 的限制

  • 仅适用于普通 Doze 模式
    setExactAndAllowWhileIdle() 设计用于 STATE_DOZE(普通休眠),可在维护窗口外触发(但受每分钟 1 次的频率限制)。但在 STATE_DOZE_SUSPEND 下,系统无周期性唤醒机制,导致该方法失效。
  • 深度省电下的唤醒条件
    仅以下事件可唤醒 STATE_DOZE_SUSPEND
    • 用户主动操作(如点亮屏幕)
    • 高优先级闹钟 setAlarmClock()(系统会提前退出休眠并显示通知)
    • 设备充电。

7.3 替代方案

若需在 STATE_DOZE_SUSPEND 下可靠触发任务,需采用以下策略:

  1. setAlarmClock()
    • 用于用户可见的精确闹钟(如闹钟应用),系统会强制退出休眠并显示通知栏图标。
    • 无需特殊权限,但用户感知明显。
  2. 引导用户加入白名单
    • 用户手动在 设置→电池优化 中将应用设为“未优化”,可部分豁免限制(非完全保障,厂商兼容性差异大)。
  3. 前台服务(Foreground Service)
    • 通过持续通知栏服务维持进程活跃性,但需合理说明用途以避免被系统限制或用户关闭。

7.4 总结:不同闹钟方法在 Doze 模式下的有效性

闹钟方法STATE_DOZE(普通休眠)STATE_DOZE_SUSPEND(深度挂起)
setExact() / setWindow()❌ 延迟至维护窗口❌ 完全冻结
setAndAllowWhileIdle()✅ 可触发(精度低)❌ 无效
setExactAndAllowWhileIdle()✅ 可触发(秒级误差)❌ 无效
setAlarmClock()✅ 立即触发✅ 强制唤醒(需用户可见通知)

结论
STATE_DOZE_SUSPEND 下,setExactAndAllowWhileIdle() 无法触发。若需极端省电模式下的可靠性,应优先使用 setAlarmClock() 或引导用户设置白名单)。

8. 更多内容

有关WorkManager基础的概念和使用,详见 : Android WorkManager的概念和使用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/923612.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/923612.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

iOS 能耗监控与电池优化实战:如何查看App耗电量、分析CPU、GPU内存使用、(uni-app iOS开发性能调试指南)

在 iOS 应用开发中&#xff0c;能耗与电池消耗是用户最直观的体验指标。 即便功能完善&#xff0c;如果 App 存在以下问题&#xff1a; 电池掉电快、设备发热严重&#xff1b;后台任务执行过多&#xff1b;页面渲染与文件操作引发 CPU/GPU 过载&#xff1b;日志或缓存导致频繁 …

Git 本地分支推送多个远程分支

方法一&#xff1a;一次性推送命令 命令格式&#xff1a; git push <远程仓库名> <本地分支引用>:<远程分支名1> <本地分支引用>:<远程分支名2> ...具体步骤&#xff1a; 确保你的代码修改已经提交到了本地分支 git add . git commit -m "你…

抖音私信评论互动消息通知监听自动获取,通过qq机器人转发到qq来通知

抖音私信评论互动消息通知监听自动获取&#xff0c;通过qq机器人转发到qq来通知 如果不是抖音平台&#xff0c;其他平台也类似的&#xff0c;也可以实现&#xff0c;只是目前懒得写了 本期视频点赞过10个就开源代码 有需要的人可以在视频底下留言 需求反馈多的我可以实现

UVM验证工具--gvim

目录 gvim语法高亮 gvim支持git Linux环境自带gvim工具&#xff0c;我们需要做如下设置&#xff1a; 支持UVM、SystemVerilog、verilog语法高亮支持git&#xff08;实时显示对文件的修改&#xff09; gvim语法高亮 gvim支持git

MyBatis 从入门到精通(第二篇)—— 核心架构、配置解析与 Mapper 代理开发

在第一篇博客中&#xff0c;我们掌握了 MyBatis 的基础概念与环境搭建&#xff0c;成功通过简单查询实现了数据持久化。但要真正用好 MyBatis&#xff0c;还需深入理解其 “内部工作原理” 与 “企业级开发规范”。本篇将聚焦三大核心&#xff1a;MyBatis 架构与核心类、全局配…

uniapp+<script setup lang=“ts“>单个时间格式转换(format)

有问题的时间&#xff08;只示例&#xff0c;不是真实数据&#xff09;修改后的时间展示&#xff08;只示例&#xff0c;不是真实数据&#xff09;原代码<view v-else-if"item?.payTime" class"order-info-item">支付时间&#xff1a;item?.payTim…

运维安全05,iptables规则保存与恢复

一&#xff1a;网络安全1.1、昨日功能优化配置后引发的问题&#xff1a;配置iptables后防火墙起到了防护作用&#xff0c;但使用127.0.0.1访问不了数据库了[rootlocalhost /]# mysql -u admin -p -h 127.0.0.1 Enter password:思考&#xff1a;如果使用localhost可以访问吗&…

线性代数 · 矩阵 | 秩 / 行秩 / 列秩 / 计算方法

注&#xff1a;本文为 “线性代数 矩阵 | 秩” 相关合辑。 图片清晰度受引文原图所限。 略作重排&#xff0c;未全校去重。 如有内容异常&#xff0c;请看原文。 矩阵的秩及其应用 一、矩阵秩的基本概念 &#xff08;一&#xff09;k 阶子式 设矩阵 A(aij)mnA (a_{ij})_{m…

Ajax-day2(图书管理)-弹框显示和隐藏

Bootstrap 弹框图书管理-Bootsrap 弹框&#xff08;一&#xff09;属性控制一、模板代码二、弹框模板三、bootsrap 的显示弹框属性完整代码&#xff08;二&#xff09;JS 控制一、模板代码二、步骤图书管理-Bootsrap 弹框 Bootstrap 框架渲染列表&#xff08;查&#xff09;新…

【Linux网络】认识https

认识https一&#xff0c;概念铺垫1.1 什么是加密&#xff1f;1.2 为什么要加密&#xff1f;1.3 加密的方式1.4 数据摘要&数据指纹二&#xff0c;认识https2.1 方案1-只使用对称加密2.2 方案2-只使用非对称加密2.3 方案3-双方都使用非对称加密2.4 方案4-非对称加密对称加密2…

OC-AFNetworking

文章目录AFNetworking简介问题&#x1f914;优化策略解决AFNetworking局限性使用单例进行网络请求的优势使用单例进行网络请求的风险最优使用使用参数讲解POST请求AFNetworking 简介 这篇文章旨在实现使用AFNetworking设置一个集中的单通道网络对象&#xff0c;该对象与MVC组建…

【数据结构】跳表

目录 1.什么是跳表-skiplist 2.skiplist的效率如何保证&#xff1f; 3.skiplist的实现 3.1节点和成员设计 3.2查找实现 3.3前置节点查找 3.4插入实现 3.5删除实现 3.6随机层数 3.7完整代码 4.skiplist跟平衡搜索树和哈希表的对比 1.什么是跳表-skiplist skiplist是由…

html实现右上角有个图标,鼠标移动到该位置出现手型,点击会弹出登录窗口。

写了一段html代码实现的效果&#xff1a;实现右上角有个图标&#xff0c;鼠标移动到该位置出现手型&#xff0c;点击会弹出登录窗口。功能实现前端&#xff0c;没有实现后端。<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF…

STM32G4 电流环闭环(二) 霍尔有感运行

目录一、STM32G4 电流环闭环(二) 霍尔有感运行2. 霍尔有感运行附学习参考网址欢迎大家有问题评论交流 (* ^ ω ^)一、STM32G4 电流环闭环(二) 霍尔有感运行 2. 霍尔有感运行 文章使用的BLDC在定子侧以互差120电角度的位置安装三个霍尔元件Ha&#xff0c;Hb&#xff0c;Hc。当…

展示框选择

好的&#xff0c;非常感谢您提供更详细的项目情况。这是一个非常典型的父子组件通信场景。 根据您的新需求&#xff0c;我将对代码进行重构&#xff1a; FaultSelect.vue (子组件): 这个组件现在将变得更加“纯粹”。它只负责自身的下拉框逻辑&#xff0c;不关心外部按钮&#…

第5课:上下文管理与状态持久化

第5课:上下文管理与状态持久化 课程目标 掌握上下文存储和检索策略 学习会话状态管理 了解数据持久化方案 实践实现上下文管理系统 课程内容 5.1 上下文管理基础 什么是上下文管理? 上下文管理是Agent系统中维护和利用历史信息的能力,包括: 对话历史:用户与Agent的交互…

计算机毕业设计 基于大数据技术的医疗数据分析与研究 Python 大数据毕业设计 Hadoop毕业设计选题【附源码+文档报告+安装调试】

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python、大数据、人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&…

K8S集群管理(2)

目录 1.什么是Pod的根容器&#xff1f; 2.解释Pod的生命周期。 3.Init类型容器有什么特点&#xff0c;主要用途&#xff1f; 4.Sidecar类型容器和Init容器的区别在哪&#xff1f; 5.什么是静态Pod&#xff1f; 6.说明K8s控制器的作用&#xff1f; 7.什么是ReplicaSet&#xff0…

视频全模态referring分割:Ref-AVS: Refer and Segment Objects in Audio-Visual Scenes

一、TL&#xff1b;DR 为什么要做&#xff1a;传统的referring分割无法使用音频模态&#xff0c;本文提出Reference audio-visual Segmentation本文怎么做&#xff1a;构建首个 Ref-AVS 基准数据集通过充分利用多模态提示&#xff0c;将音频信息通过和文本融合作为载体&#x…

A股大盘数据-20250916分析

&#x1f4ca; 一、大盘数据深度分析1.1 &#x1f9ee; 市场活跃度与资金流向总成交额&#xff1a;沪深京合计约 2.37万亿元&#xff0c;市场交投活跃&#xff0c;深市成交&#xff08;13516.4亿&#xff09;明显高于沪市&#xff08;9897.9亿&#xff09;&#xff0c;显示中小…