移动设备的续航时间无疑是所有用户都非常在意的。我们都希望自己的手机一次充电可以使用更长的时间。但遗憾的是,近几年移动设备的电池元件一直没有重大的技术突破。并且,随着硬件性能的提升却带来了更多的电量消耗。
如果对比近几年的Android和ios手机,我们会发现:通常情况下,Android手机的电池要比同时期的ios电池容量大很多,但是待机方面却没有太大的优势。ios之所以续航优秀,其很大的原因在于对于后台进程的限制。在ios上,后台进程是无法长时间处于活跃状态的。而Android系统正好相反,通过监听广播、添加后台服务等方式,应用程序可以一直在后台保持活跃。太多进程的长时间活跃,显然会导致电量的快速耗尽。而反过来,想要延长电池寿命的重要措施就是尽可能减少后台应用的活跃性。因此,从Android5.0到8.0的功耗改进,一直都是围绕着“后台进程的活跃性”来展开的。
project volta是在Android5上引入的。要延长电池的寿命,首先就得要明确消耗电量的主要因素是什么。在移动设备上,对于电量的消耗最大的是下面三个模块:
除此之外,设备的频繁唤醒也会导致电量消耗过快。系统唤醒1s所消耗的电量约等于两分钟系统待机所消耗的电量。如果系统中安装了大量的应用,每个应用都在不同的时间点将系统唤醒(例如,通过广播或者服务),那么无疑会导致电量很快耗尽。
反过来,假设系统能将应用唤醒系统的频率减低,尽可能将不同应用唤醒系统的步调合并和集中,便能减少电量的消耗。
为了改善电池使用寿命,project volta提供的机制包含以下几个方面:
提供了JobScheduler API
Android5新增了该api,这个api允许开发者定义一些系统在稍后或指定条件下(如设备充电时)以异步方式运行的作业,从而优化电池寿命。下列情形下,这个功能很有用:
参考资料: https://blog.csdn.net/FightFightFight/article/details/86240553
提供工具帮助开发者发现问题
为了帮助开发者分析系统的电池消耗,Android系统内置了Batterystats工具。可以通过下面的命令来使用这个工具:
adb shell dumpsys batterystats
这个命令的输出内容非常长,人工阅读比较困难。所以Google提供了另一款工具,可以将上一步的输出装换成图形的方式方便解读。https://github.com/google/battery-historian
通过这两个工具的组合,可以得到一份图形化的电量信息的报表。
整个过程操作步骤如下:
Project Volta主要是提供了一些api和工具给开发者,让开发者配合来改善电池寿命,所以这个机制的效果很难得到保证。从Android6开始,系统包含了一些自动的省电行为,这些行为对系统上的所有应用都会产生影响,不需要开发者做特殊适配。
从Android6开始,Android引入了两个新的省电功能为用户延长电池寿命。
Doze模式和AppStandBy会影响Android6或更高版本上运行的所有应用,无论它们是否特别设置过api level。
如果用户设备未接入电源、处于静止状态一段时间且屏幕关闭,设备便会进入Doze模式。在Doze模式下,系统会尝试通过限制应用对网络和cpu密集型服务的访问来节省电量。
系统会定期退出Doze模式一会,好让应用完成其已推迟的活动。在此维护时段内,系统会运行所有待定同步、作业和闹钟并允许应用访问网络。在每个维护时段结束后,系统会再次进入Doze模式,暂停网络访问并推迟作业、同步和闹铃。随着时间的推移,系统安排维护时段的次数越来越少,这有助于在设备未连接至充电器的情况下长期处于不活跃状态时降低电池消耗。
一旦用户通过移动设备、打开屏幕或连接到充电器唤醒设备,系统就会立即退出Doze模式,并且所有应用都将返回到正常活动状态。
Android6.0引入了Doze模式,当用户设备未插入电源、处于静止状态且屏幕关闭时,该模式会推迟cpu和网络活动,从而延长电池寿命。而Android7.0则通过在设备未插接电源且屏幕关闭状态下,但不一定要处于静止状态(例如,用户外出时把手持式设备装在口袋里)时应用部分cpu和网络限制,进一步增强了Doze模式。
当设备处于充电状态且屏幕已关闭一定时间后,设备会进入Doze模式并应用第一部分限制:关闭应用网络访问,推迟作业和同步。如果进入Doze模式后设备处于静止状态且达到一定时间,系统则会对PowerManager.WakeLock、AlarmManager闹铃、GPS和WLAN扫描应用余下的Doze模式限制。无论是应用部分还是全部Doze模式限制,系统都会唤醒设备以提供简短的维护时间窗口,在此窗口期间,应用程序可以访问网络并执行任何被推迟的作业/同步。同样,一旦激活屏幕或插接设备电源,系统将退出Doze模式并移除这些处理限制。
App StandBy允许系统判定应用在用户未主动使用它时使其处于空闲状态。当用户有一段时间未触摸应用时,系统便会做出此判定。但是对于以下情况,系统将判定应用退出App StandBy状态,包括:
当用户将设备插入电源时,系统将从App StandBy状态释放应用,从而让它们可以自由访问网络并执行任何特定作业和同步。如果设备长时间处于空闲状态,系统将按每天大约一次的频率允许该应用访问网络。
通过妥善管理网络连接、闹钟、作业和同步并使用FCM高优先级消息,几乎所有应用都应该能够支持Doze模式。对于一小部分用例,这可能还不够。对于此类用例,系统为部分免除Doze模式和App StandBy优化的应用提供了一份可配置的白名单。
在Doze模式和App StandBy期间,加入白名单的应用可以使用网络并保留部分wake locks。不过,正如其他应用一样,其他限制仍然适用于加入白名单的应用。例如,加入白名单的原因的作业和同步将推迟,并且其常规alarmmanager闹铃不会触发。通过调用isIgnoringBatteryOptimizations(),应用可以检查自身当前是否位于白名单中。
用户可以在Settings->Battery->Battery optimization中手动配置该白名单。
另外,系统也为应用提供了编程接口来请求让用户将其加入白名单。
Android6.0和7.0两个版本提供了Project Volta、Doze模式以及App StandBy机制来降低功耗以延长电池寿命。
但实际上Android系统上最令人诟病的“后台问题‘仍然没有得到解决:应用程序很容易通过监听各种广播的方式来启动后台服务,然后长时间在后台保持活跃。这样做无疑会导致电池电量很快耗尽。Android系统的用户对此应该深有体会,通过系统设置中额运行中应用列表,总能看到一大串的服务在后台运行着。
Android是一个多任务的os。例如,用户可以在一个窗口中玩游戏,同时在另一个窗口中浏览网页,并使用第三个应用播放音乐。
同时运行的应用越多,对系统造成的负担越大。如果还有应用或服务在后台运行,会对系统造成更大负担,进而可能导致用户体验下降。例如,音乐应用可能会突然关闭。
为了减低发生这些问题的概率,Android8.0对应用在用户不与其直接交互时可以执行的操作施加了限制。
应用在两个方面受到限制:
后台服务限制:处于空闲状态时,应用可以使用的后台服务存在限制,但这些限制不实施于前台服务,因为前台服务更容易引起用户注意。
广播限制:除了有限的例外情况,应用无法使用AndroidManife.xml注册隐式广播。但它们仍然可以在运行时注册这些广播,并且可以使用AndroidManifest.xml注册专门针对它们的显式广播。
默认情况下,这些限制仅适用于针对8.0的应用。不过,用户可以从Settings屏幕为任意应用启用这些限制,即使应用并不是以8.0为目标平台。
在后台中运行的服务会消耗设备资源,这可能会降低用户体验。为了缓解这一问题,系统对这些服务施加了一些限制。
如果满足以下条件中的任意一个,应用都将被视为处于前台:
如果以上条件均不满足,则应用被视为处于后台。
处于前台时,应用可以自由创建和运行前台服务和后台服务。进入后台时,在一个持续数分钟的时间窗内,应用仍可以创建和使用服务。
在该时间窗结束后,应用将被视为处于空闲状态。此时,系统将停止应用的后台服务,就像应用已经调用服务的stopself()方法。
在下面这些情况下,后台应用将被置于一个临时白名单中并持续数分钟。位于白名单中时,应用可以无限制地启动服务,并且其后台服务也可以运行。
处理对用户可见地任务时,应用将被置于白名单中,例如:
在很多情况下,应用都可以使用JobScheduler来替换后台服务。在Android8.0之前,创建前台服务的方式通常时先创建一个后台服务,然后将该服务推到前台。Android8.0有一项复杂功能:系统不允许后台应用创建后台服务。因此,Android8.0引入了一个权全新的方法,即Context.startForegroundService(),以在前台启动新服务。在系统创建服务后,应用有5s的时间来调用该服务的startForeground方法以显示新服务的用户可见通知。如果应用在此时间限制内未调用该方法,则会报anr的错误。
如果应用注册为接收广播,则在每次发送广播时,应用的接收器都会消耗资源。如果多个应用注册为接收基于系统事件的广播,这会引发问题:触发广播的系统事件会导致所有应用快速地连续消耗资源,从而降低用户体验。
为了缓解这一问题,Android7.0对广播施加了一些限制,而Android8.0让这些限制更为严格。