本文主要是介绍android 6.0的DozeMode低功耗模式 及 引起的进程保活问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
一、问题的来源
由于Android的开放特性,加上国内app开发者的觉悟普遍不高的情况下,越来越多的app开始利用安卓的系统特性甚至可以称为漏洞,故意让app退出后仍然占用大量的硬件资源。 越来越多的应用会在后台运行时“假死”,即不进入真正的Sleep,而是不断在后台轮询搜集用户行为或者保持某些长链接来保障数据的实时性。而Android系统自身并未出台对应的策略来约束或者限制这类应用行为,当这类应用越来越多,就会导致用户的Android设备电量消耗越来越高、手机越来越烫、流量偷跑、话费超标等情况。 这种不好的用户体验慢慢积累总有一天会爆发,冰冻三尺非一日寒,直到某一天这类问题影响到系统口碑 而被某个 新型移动端操作超载的时将悔之晚已。 想想当年的诺基亚是何等风光,我上大学的第一款手机就是 若基亚5380,现在呢,被安卓干趴了,google当然不希望这样的事发生在安卓上。
二、解决方案
google也已经意识到这个问题,并且从Android M(即6.0)开始引入 Doze Mode,中文翻译为“打旽模式”,但专业术语的翻译为“低电耗模式”和“应用待机模式”,android系统的这两个模式都是采用 Doze Mode 来实现的。
doze 这个单词的中文翻译为“打瞌睡”,“打瞌睡”的意思就是稍微休息一下,例如我们长时间工作时,可能会觉得疲倦,这时我们会趴在桌子上眯几分钟,但是我们的思想状态是可以随时进入工作状态的,比如领导随时可能给你安排一项紧急的工作,这时你可以立即进入工作状态。
那么对于 安卓系统而言,系统在锁屏后也会选择一个合适的时机休息片刻,一旦用户再次解锁屏,系统又能立即进入工作状态。
三、Doze Mode介绍
关于Doze Mode的介绍,我们可以看看 android官网上的说明,链接:安卓官网Doze Mode,这链接可能需要一些特殊技巧才能访问(原因你懂的)。我从官网摘录一下基本的概念供墙内的同学阅读:
从 Android 6.0(API 级别 23)开始,Android 引入了两个省电功能,可通过管理应用在设备未连接至电源时的行为方式为用户延长电池寿命。低电耗模式通过在设备长时间处于闲置状态时推迟应用的后台 CPU 和网络 Activity 来减少电池消耗。应用待机模式可推迟用户近期未与之交互的应用的后台网络 Activity。
低电耗模式和应用待机模式管理在 Android 6.0 或更高版本上运行的所有应用的行为,无论它们是否特别针对 API 级别 23。 为确保用户获得最佳体验,请在低电耗模式和应用待机模式下测试您的应用并对代码进行必要的调整。
需要注意的几点:
1、Doze Mode会限制后台应用的cpu、网络。
在安卓早期,当内存不够用时,安卓系统会回收后台应用的进程,这仅仅是从 内存占用 层面来限制后台应用。那么现在 系统会进一步限制后台应用的 cpu、网络
2、不论app的targetApi是否23(即安卓6.0),只要用户的手机是基于android 6.0,那么你的应用也将受到Doze Mode的限制。
在早期的安卓版本适配时,可能由于时间关系,我们并不会立即适配6.0的权限系统,但为了让应用在6.0上也能正常运行,我们会将app的targetApi 设置5.0,这样app在6.0上运行的效果和在5.0上完全一致。 但这套方式对于Doze Mode不再适用了,可能是google为了回快android新版本的更新速度吧。 毕竟国内开发者的大环境就这样,总要有个鞭子放在脑壳驱动你,你才会去更新。
四、Doze Mode的两个具体应用:低电耗模式、应用待机模式
这两个模式都是通过 Doze Mode 来实现,那么至些我们可以认为 Doze Mode 只是一种技术手段的名词。
a、低电耗模式:
如果用户设备未插接电源、处于静止状态一段时间且屏幕关闭,设备会进入低电耗模式。 在低电耗模式下,系统会尝试通过限制应用对网络和 CPU 密集型服务的访问来节省电量。 这还可以阻止应用访问网络并推迟其作业、同步和标准闹铃。
系统会定期退出低电耗模式一会儿,好让应用完成其已推迟的 Activity。在此维护时段内,系统会运行所有待定同步、作业和闹铃并允许应用访问网络。
b、应用待机模式:
系统判定应用在用户未主动使用的进程,都认为此进程处于空闲状态。
当用户将设备插入电源时,系统将从待机状态释放应用,也就不会使用Doze Mode来限制后台进程的硬件资源。
Doze和App Standby的区别:
Doze模式需要屏幕关闭(通常晚上睡觉或长时间屏幕关闭才会进入),而App Standby不需要屏幕关闭,App进入后台一段时间也会受到连接网络等限制。
五、国内rom对Doze Mode做的修改
以上所说的 Doze Mode 在 原生安卓系统中能完好的运行,而且google还规定所有google play中上架的应用:除非应用的核心功能受到不利影响,否则 Google Play 政策禁止应用请求直接豁免 Android 6.0+ 中的电源管理功能(低电耗模式和应用待机模式)。 这样的规定肯定是有利于用户体验的。
具体来说 Doze Mode实现了两个功能,一个是“低电耗模式”,它能让你的手机在很低功耗的情况下运行,设想你正处于户外长途旅行中,不方便随时给手机充电,这个低电耗模式就能起到作用了;另一个是“应用待机模式”,我正在使用应用A,然后切换主页再打开应用B,这时应用A还在后台不断的消耗电量。
那么对于国内的rom呢,国内的rom厂商都在这套doze mode的基础加上了自己的定制。但功能上是大同小异的,只是称呼和细节上有些差异。
以 MIUI 8.2、android 6.0 为例,看看 小米 提供了哪些功能, 在小米手机的 “设置”->"电量和性能"-
5.1 小米对“低电耗模式”的改版
这里我们可以看到,小米将“低电耗模式”换了个名称叫“省电优化”,另外在原生系统中,只要未插电源且静止且锁屏状态,系统就能进入“低电耗模式”。然而小米系统却是自己加了一个开关,将这个权力交给用户选择,你的手机你作主,个人觉得这也是小米系统优化的比较好的地方。
另外小米的“省电模式”里还有个省电设置,如下图,里面有两项:
一是锁屏一段时间后断开数据,即锁屏一段时间后所有app将无法通过流量来通信
二是锁屏一段时间后清理内存,即锁屏一段时间后清理用户内存空间,即你的用户进程都会被杀掉。
注:某些厂商第2点的处理可能略有不同,假设这样的场景,你打开一个音乐播放app,本来你是希望锁屏后一直播放的,结果因为这项设置导致锁屏1分钟后就自己停止了播放,因为内存被清理了。 据我所知 华为meta10 就有这项保护处理,那么这也是个进程保活的手段。
5.2 小米对“应用待机模式” 的改版
在安卓原生 6.0系统中,系统默认对所有应用加了此限制,用户无法修改,而小米又机制的将选择权交给用户了,毕竟“你的手机你作主”,我买的手机都不能按我的意愿运行,我他妈还会买吗?
从下面3张图可以看出,小米手机给出了三种级别,一是不开启待机模式;二是所有应用都开启此模式;三是针对每个应用自己去配置要不要开启。
六、测试这些设置如何影响后台进程
显然Doze Mode 的特性是限制后台应用的存活的,在研究如何保活之前,我们先来看看 Doze Mode在不同场景下是如何 限制后台进程的。
以 小米手机 MIUI 8.2、android 6.0 为例,执行以下测试,并记录测试结果。
1、在手机设置里将此应用设为 “快速尝试冻结所有后台应用”,并且没有重启手机:
a、在充电时后台应用锁屏状态能一直运行。
b、在不充电并水平放置在桌面,且手机静止不动时,锁屏后 后台应用 3-5秒后 停止运行,前台应用 2-10秒后停止运行
c、在不充电,并手动晃动手机时, 锁屏后 后台应用 3-5秒后 停止运行, 前台应用2-6秒后停止运行
2、在手机设置里将此应用设为 “不限制后台应用的功能”,并且没有重启手机: 注:此前应用的状态是“禁止后台运行”(这会不会有影响?)
a、不充电并水平放置,且手机静止不动时, 锁屏后 后台应用 5-10秒后停止运行 ,前台应用 4秒后停止运行
b、在不充电,并手动晃动手机时, 锁屏后 后台应用 5秒后 停止运行, 前台应用2秒后停止运行
3、在手机设置里 “依照应用配置限制后台应用”,同时对应用设置“无限制后台应用”,并且没有重启手机:
a、不充电并水平放置,且手机静止不动时, 锁屏后 后台应用 5秒后停止运行 ,前台应用 2秒后停止运行
b、在不充电,并手动晃动手机时, 锁屏后 后台应用 4秒后 停止运行, 前台应用3秒后停止运行
4、在手机设置里设为 “不限制后台应用的功能”,并且重启手机:
a、不充电并水平放置,且手机静止不动时, 锁屏后 后台应用 50秒后仍在运行,前台应用 70秒后仍在运行
b、在不充电,并手动晃动手机时, 锁屏后 后台应用 45秒后 仍在运行, 前台应用30秒后仍在运行
5、基于第4步后,将设置改为“快速尝试冻结所有后台应用”,同时自定义里设置应用为“无限制”,并且没有重启手机
a、不充电并水平放置,且手机静止不动时, 锁屏后 后台应用 45秒后仍在运行,前台应用 40秒后仍在运行
b、在不充电,并手动晃动手机时, 锁屏后 后台应用 30秒后 仍在运行, 前台应用40秒后仍在运行
6、基于第5步后,在自定义里设置应用为“MIUI智能省电”,并且没有重启手机
a、不充电并水平放置,且手机静止不动时, 锁屏后 后台应用 55秒后仍在运行,前台应用 60秒后仍在运行
7、基于第6步后,在自定义里设置应用为“限制后台功能,但应用不会被关闭”,并且没有重启手机
a、不充电并水平放置,且手机静止不动时, 锁屏后 后台应用 40秒后仍在运行,前台应用 60秒后仍在运行
8、基于第7步后,在自定义里设置应用为“禁止后台运行,应用会被关闭”,并且没有重启手机
a、不充电并水平放置,且手机静止不动时, 锁屏后 后台应用 40秒后仍在运行,前台应用 40秒后仍在运行
9、在第8步后,重启手机,但不修改任何设置,即设置仍然是"快速尝试冻结所有后台应用"&"禁止后台运行,应用会被关闭"
a、不充电并水平放置,且手机静止不动时, 锁屏后 后台应用 40秒后仍在运行,前台应用 40秒后仍在运行
10、手机设置:“锁屏1分钟后清理内存“
a、不充电并水平放置,且手机静止不动时, 锁屏后 58秒 应用进程被杀,不仅是cpu被冻结
注:第7、8、9这三项的测试跟我们的结论是冲突的,猜测原因可能是小米手机在重启手机后需要一段时间的初始化工作,导致我们的设置没有生效。
通过以上验证,我们得出结论:
1、小米系统的这些设置基本上有效。
2、有些可能要重启手机,重启完成后可能还需要等待一段时间才能生效,猜测是可能是系统层有文件记录的处理,重启完成后初始化这些数据还需要一段时间。
七、doze mode 调试技巧
开发者如何测试自己的应用在 doze mode下会受到怎样的影响,可以参考安卓官网: 在低电耗模式和应用待机模式下进行测试 。
对国内开发者来说,厂商可能会修改原生安卓里的规则,这时我们不防用模拟器 来测试 doze mode。
扯完模拟器的坑后,我们继续正题,摘录部分官网的步骤:
一、在低电耗模式下测试您的应用您可按以下步骤测试低电耗模式:
1.使用 Android 6.0(API 级别 23)或更高版本的系统映像配置硬件设备或虚拟设备。
2.将设备连接到开发计算机并安装应用
3.运行应用并使其保持活动状态
4.关闭设备屏幕。(应用保持活动状态。)
5.通过运行以下命令强制系统在低电耗模式之间循环切换:
$ adb shell dumpsys battery unplug
$ adb shell dumpsys deviceidle step
您可能需要多次运行第二个命令。不断地重复,直到设备变为空闲状态。
6.在重新激活设备后观察应用的行为。确保应用在设备退出低电耗模式时正常恢复。
二、在应用待机模式下测试您的应用,要在应用待机模式下测试您的应用,请执行以下操作:
1.使用 Android 6.0(API 级别 23)或更高版本的系统映像配置硬件设备或虚拟设备。
2.将设备连接到开发计算机并安装应用
3.运行应用并使其保持活动状态
4.通过运行以下命令强制应用进入应用待机模式:
$ 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>
观察唤醒后的应用行为。确保应用从待机模式中正常恢复。 特别地,您应检查应用的通知和后台作业是否按预期继续运行
adb shell dumpsys deviceidle -h 可以查看dumpsys提供的调试手段: | ||||||||
命令 | 输出 | |||||||
-h | 显示帮助菜单 | |||||||
step | 每次调用就会进入一次stepIdleStateLocked,从而实现状态机的状态逐步迁移 | |||||||
force-idle | 让Android设备忽视Screen状态以及Cable连接状态,直接开始一轮Doze模式倒计时 | |||||||
disable | 取消对Doze模式的支持 | |||||||
enable | 恢复对Doze模式的支持 | |||||||
enabled | 若支持Doze模式,返回1;否则返回0 | |||||||
whitelist | 终端打印当前的白名单 | |||||||
whitelist +/-[xxxxxx] | 将xxxxxx包加入/移出白名单 | |||||||
tempwhitelist [xxxxxx] | 将xxxxxx包加入临时白名单 |
八、保活的问题
基于以上现象,如何在用户没有主动设置后台保活的情况下(即没有设置 不限制后台活动),提供应用后台存活的概率?
理论上用户没有主动设置的情况下,都会遵守系统的 “应用待机模式”的管理规则,但在此规则之上是否还有其它手段 来让 后台进程 尽可能的保活, 有时间再单独开一篇文章来研究.
在安卓6.0及以后系统上,可以防止 doze mode 让应用进程 进程阻塞挂起状态 的保活方法:
1、启动前台Service
2、自定义锁屏
3、在应用内播放一段无声的音乐
这个方法,实测很有效,系统认为如果你的应用进程在锁屏时存在能被用户感知到的行为,那么系统不会阻塞这个进程,播放音乐就是一个能被用户感觉的行为,只不过我们巧妙的循环播放一个无声音乐来欺骗 系统。
缺点:可能会多消耗一定的电量,但实测并没有多消耗很多, 半个小时也就消耗了2%电量, 实际就算不播放无声音乐半小时系统也会存在一定的消耗。 所以暂时不需要考虑这方面。
4、保持屏幕长亮(只在某些特殊功能场景下适用,如导航软件)。系统不锁屏,就不会进入doze mode
这篇关于android 6.0的DozeMode低功耗模式 及 引起的进程保活问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!