本文最近更新于 2018 年 2 月 19 日「 星期一 」

从 Android 6.0 开始,Android 提供了两种省电功能:Doze 和 App Standby。

简单来说,就是当设备没有连接电源,设备进入 Doze 模式时,系统将通过延迟最近没有被使用的 App 的后台 CPU 运作及网络活动,让 App 处于 App Standby 状态来减少电池消耗。

那么,手机怎样才会进入 Doze 睡眠模式呢?

根据官方的说明,需要满足三个条件:用户不操作设备一段时间,屏幕关闭,设备未连接电源充电。

也就是说,当我们再次移动手机或者打开屏幕将其唤醒,或者连接电源充电时,Android 就会退出 Doze 模式(系统退出休眠,所有的应用程序恢复正常活动)。

在 Doze 模式下,系统会限制 CPU 的密集型服务和网络服务,这样就会推延应用程序的工作、同步和标准的警报。而为了不影响 App 的功能,系统又会定期提供一个短暂的时间段让 App 完成被延迟的工作活动,例如为其唤醒网络,运行在等待的同步、激活被延迟的工作和报警等活动。

Doze 期间具体的限制行为有哪些?

  • 网络连接会被禁止
  • Wake Lock 会被屏蔽
  • AlarmManager 定时任务延迟到下一个 maintenance window 进行处理,除非使用 AlarmManager 提供的方法:setAndAllowWhileIdle() 或者 setExactAndAllowWhileIdle()
  • 系统将不扫描热点 WIFI
  • 同步工作将被禁止
  • 不允许 JobScheduler 进行任务调度

Doze 设计的缺陷和弥补方法:

根据 Doze 的这种设计,很容易发现的两个问题是:

  • AlarmManager 闹钟和定时器管理活动将受到影响

为此,Android 6.0 引入了两个新方法:setAndAllowWhileIdle() 和 setExactAndAllowWhileIdle(),调用这两个方法可以在 Doze 模式下让系统响应定时任务

  • 限制了网络的连接,如果应用程序依赖于实时信息,例如一些聊天 App,毫无疑问这个将影响 App 的体验

针对这一问题,Google 推出了 Google Cloud Messaging(GCM) 谷歌云消息(后面详细讲解)

什么是 App Standby?

当用户不触摸使用应用程序一段时间后,该应用程序处于 App Standby 状态,系统将把该 App 标志为空闲状态。当一个 App 处于 App Standby 状态时,如果触发一下任意条件即退出 Standby 模式:

  • 用户主动启动该 App
  • 该 App 当前有一个前台进程(或包含一个活动的前台服务,或被另一个 activity 或前台 service 使用)
  • App 生成一个用户所能在锁屏或通知托盘看到的 Notification,而当用户设备插入电源时,系统将会释放 App 的待机状态,允许他们自由的连接网络及其执行未完成的工作和同步。如果设备空闲很长一段时间,系统将允许空闲 App 一天一次访问网络

Doze 和 App Standby 的区别:

Doze 模式需要屏幕关闭(通常晚上睡觉或长时间屏幕关闭才会进入),而 App Standby 不需要屏幕关闭,App 进入后台一段时间也会受到连接网络等限制。

什么是GCM?

Google Cloud Messaging(GCM) 是一个云到设备的服务,可以让你支持实时在云端服务和 Android 设备上应用程序之间的消息传递。

GCM 提供了一个持久连接到云端的链接,让所有需要实时消息传递应用程序可以共享此链接。这个共享链接显著优化电池消耗,使其不必让多个应用程序各位维护自己单独的持久链接而使电池迅速耗尽。

由于这个原因,官方建议:如果你的应用需要消息传递与后端服务集成,我们强烈建议尽可能的使用 GCM,而不是单独维护自己的网络链接。

GCM 消息拥有高优先级,不影响 Doze 模式,且不会不影响其他应用程序的状态。这意味着你的应用程序可以使用它们进行通信,同时最大限度地减少电池在整个系统和设备的影响。

以下来 GCM 自官方解释:

一个 GCM 实现包括谷歌连接服务器,在你的环境中通过 HTTP 或 XMPP 协议的连接服务器进行交互的应用程序服务器和客户端应用程序。

除了 GCM,Android 6.0 及更高版本还提供了 Doze 模式白名单列表,通过设置应用程序进入白名单列表(电池优化)可逃脱 Doze 模式的各种限制。

“电池优化”选项在一些非原生的 ROM 中可能会被隐藏掉,例如 MIUI 中。若要更好地利用 doze 模式,就要找到“电池优化”入口并根据个人使用情况进行合适的白名单配置。
扩展阅读:如何找到隐藏的“电池优化”入口?