简介
从Android 6.0(API level 23)开始,Android提出了两个延长电池使用时间的省电特性给用户。用户管理可以在没有充电的情况下管理app的行为。当用户一段时间没有使用手机的时候,Doze模式通过延缓app后台的CPU和网络活动减少电量的消耗。App Stanbdy延缓用户最近没有使用app的后台网络活动。
Doze和App Stanbdy管理所有在Android6.0+正在运行app的行为。
理解Doze模式
如果一个用户断开了充电连接,关屏不动手机一段时间之后,设备进入Doze模式。在Doze模式中,系统尝试去通过减少应用的网络访问和CPU敏感的服务来保护电池。它也阻止应用通过访问网络,并且延缓应用的任务、同步和标准alarms。
系统定期退出Doze模式(maintenance window)去让app完成他们被延缓的动作。在maintenance window期间,系统运行所有挂起的同步、任务和alarms,同时也能访问网络。

图一:Doze模式提供一个复发的maintenance window给app去使用网络和处理挂起的操作
在每个maintenance window完结时,系统会再次进入Doze模式,暂停网络接入和延缓操作、同步和alarms。随着时间的过去,当设备没有充电且长时间静止时系统调度maintenance window的次数越来越少,以此帮助减少电池消耗。
只要用户通过移动、点亮屏幕或则插上充电器唤醒设备的时候,系统会退出Doze模式,所有的app退回到正常活动状态。
Doze模式限制
Doze模式中的限制
l 网络接入被暂停
l 系统忽略wake locks
l 标准的AlarmManager alarms(包括setExact()和setWindow())被延缓到下一个maintenance window
n 如果你需要在Doze状态下启动设置的alarms,使用setAndAllowWhileIdle()或者setExactAndAllowWhileIdle()。
n 当有setAlarmClock()的alarms启动时,系统会短暂退出Doze模式
l 系统不会扫描Wi-Fi
l 系统不允许sync adapters运行
l 系统不允许JobScheduler运行
Doze模式下的app适配
Doze模式能不同程度的影响app,这个程度取决于app提供的能力和他们使用到的服务。许多app在没有修改的情况下运行到Doze模式功能正常。在许多情况下,你必须优化app程度管理网络、alarms、任务和同步。App应该能有效地管理在每个maintenance window时的活动。
Doze模式特别容易影响到AlarmManager alarms和timers管理活动,因为当系统进入Doze模式时,不高于Android 5.1 (API level 22)的alarms不会被启动。
为了帮助安排alarms,Android 6.0引进了两个新AlarmManager方法:setAndAllowWhileIdle()和setExactAndAllowWhileIdle()。通过这些方法,你能设置在Doze模式下启动的alarms。
Tips:不论setAndAllowWhileIdle()还是setExactAndAllowWhileIdle(),每个app都只能启动alarms不超过15分钟一次。
Doze模式限制网络接入,很可能影响到app,尤其是即时信息类。如果app需要一个长连接去接收网络消息,你可能应该使用Google Cloud Messaging(GCM)。
你可以使用adb命令强制系统进入/退出Doze模式观察app在Doze模式下的表现是否符合期望。详情请看Doze和App Standby模式测试。
理解App Standby模式
App Stanbdy模式允许系统决定一个app在用户没有使用的时候变成空闲的。当用户没有触摸app在一段时间内并且没有下列条件的情况下,系统会做这个决定。
l 用户没有明确启动这个app
l App当前有一个进程在前台(一个activity或者前台服务,又或者被另一个activity或前台服务使用)
l App关联到一个能够在锁屏或者通知栏看见的一个通知
当用户插上电源时,系统从Stanbdy状态释放app,允许他们自由访问网络,执行挂起的任务和同步。如果这个设备长时间处在idle状态,系统允许idle的app每天访问一次网络。
使用GCM
Google Cloud Messaging (GCM) 是一个cloud-to-device 服务,可以让你支持后台服务和apps在Android设备上的实时下行的消息。GCM提供一个单一的、持久的到云的连接,所有的需要实时消息的app可以共享这个连接。这种共享连接能显著优化电池消耗。因为许多app没有必要维护自己独立持久连接,这种连接能够快速的消耗电池。出于这个原因,如果你的应用程序需要与后端服务的消息集成,如果可能的话,我们强烈建议您使用GCM,而不是维护自己的持久的网络连接。
被优化的GCM在Doze和App Standby空闲模式中通过高优先级的GCM消息的方式工作。GCM高优先级的消息让你可靠地唤醒你的应用程序访问网络,即使用户的设备处于Doze或应用程序是在App Standby模式。在Doze或App Standby模式下,系统传递消息,并给出了应用程序的临时访问网络服务和部分wakelocks,然后返回设备或app到空闲状态。
高优先级GCM消息不会否则影响Doze模式,并不会影响任何其他app的状态。这意味着您的应用程序可以使用它们有效率的沟通,同时最大限度地降低整个系统和设备的电池影响。
作为一般的最佳实践,如果你的应用程序需要下行的消息,它应该使用GCM。如果您的服务器和客户端已经使用GCM,请确保您的服务使用的重要消息的高优先级的消息,因为这将可靠地唤醒app,即使设备处于Doze模式。
其他项支持
几乎所有的应用程序应该能够通过管理网络连接,alarms,工作和同步正常,并使用GCM高优先级的消息,以支持Doze模式。窄范围的使用场景,这可能是不充足的。对于这种情况,系统提供的部分不进入Doze模式和优化的App Standby模式的可配置的应用白名单。
白名单中的app能够在Doze和App Standby模式时使用网络和持有部分wake locks。然而,其他限制任然在白名单应用上生效,和其他应用一样。例如,白名单应用程序的工作,同步被推迟,并定期的AlarmManager alarms不启动。一个应用程序可以检查它是否在当前的白名单中,通过调用isIgnoringBatteryOptimizations()方法。
用户能够在设置>电池>电池优化中进行手动配置白名单。另外,系统提供询问用户添加到白名单的方式给app
l App能够启动带有ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS的intent,引导用户到电量优化界面,让用户添加app到白名单里面
l App拥有REQUEST_IGNORE_BATTERY_OPTIMIZATIONS权限,能够弹出一个系统对话框,让用户选择是否直接添加app到白名单中。这个app启动带有ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS的intent去弹出这个对话框。
l 用户能手动从白名单中移除app
在要求用户添加app到白名单之前,确保应用符合白名单相匹配的可接受的使用情况。
Note:Google应用商店政策禁止app在Android 6.0+(Doze 和 App Standby模式)直接请求电量管理功能,除非应用程序核心功能会有受到不良影响。
Doze和App Standby测试
为了一个良好的用户体验,你应该在Doze和App Standby模式下全面测试你的app。
Doze模式下app测试
测试步骤:
1.配置硬件设备或虚拟机到Android 6.0+
2.连接设备到开发机上,然后安装app
3.运行app,让他活动着
4.关掉屏幕(app依然活动着)
5.强制系统进入Doze模式,使用以下命令
$ adb shell dumpsys battery unplug
$ adb shell dumpsys deviceidle step
你应该至少运行两个命令一次,反复直到设备进入空闲状态。
6.重新激活设备之后观察app的行为。确保当设备退出Doze模式之后app恢复正常
App Standby模式下app测试
测试步骤:
1.配置硬件设备或虚拟机到Android 6.0+
2.连接设备到开发机上,然后安装app
3.运行app,让他活动着
4.强制app进入App Standby模式
$ adb shell dumpsys battery unplug
$ adb shell am set-inactive <packageName> true
5.模拟唤醒应用
$ adb shell am set-inactive <packageName> false
$ adb shell am get-inactive <packageName>
6.唤醒之后观察应用表现。确保应用恢复到正常的Standby模式。特别是,应该检查以下app的通知和后台任务符合预期。
使用白名单例子
下表突出了正在请求或正在对电池优化之外白名单可使用案例。在一般情况下,你的应用程序不应该是在白名单,除非Doze或App Standby模式打破了应用程序的核心功能或者有app存在技术原因不能使用GCM高优先级的消息。
更多信息,请看其他项支持
类型 | 用例 | 是否能使用GCM | 白名单 | 说明 |
即时通讯,聊天,或电话 | 在Doze或App Standby模式需要实时消息给用户的app | 使用GCM | 不能添加到白名单 | 应该使用GCM高优先级的消息来唤醒app和网络访问 |
使用GCM,但是不使用GCM高优先级消息 | ||||
即时通讯,聊天,或电话;企业VoIP apps | 不能使用GCM,因为技术依赖。或者Doze和App Standby模式破坏了程序的核心功能 | 可以添加到白名单 |