http://nga.178.com/read.php?tid=5602046&rand=0.21673571108840406
本人由于工作关系,长期双枪持有Android和iPhone,同时也在两部手机上做了一些开发工作。
这篇帖子主要是想系统介绍一下Android系统怎样才能有比较好的节电效果,属于训猴的中低端教程吧。
首先介绍一下为什么Android手机普遍有电池不耐用的问题。
作为一个开放系统,Android对于应用程序,特别是后台应用程序几乎完全不加以限制。导致了以下几个比较大的问题:
- 应用程序可以无限制的注册系统事件(broadcastreceiver),在事件发生时刻被唤醒并运行.
这些时刻包括并不仅限于:开机,开关屏幕,信号变化,电话,短信,联系人变化,网络切换,电量变化……等等。
很多无良应用程序大量注册这些系统事件,并且让自己在毫无必要的情况下被唤醒,特别是信号变化和电量变化这类系统事件,几乎每分钟都会被触发。
你想象一下你的猴机每分钟都要唤醒并运行几十个乱七八糟的后台进程,这能不耗电吗?
- 应用程序可以不使用Google推送机制,而是通过自己创建并保持一个后台长连接来监听数据。
在iOS上,应用程序不可能在后台保持一个自己的长链接来监听数据,如果必须这样做(比如voip)就要通过苹果的严格审查然后使用特殊的授权API。
没有得到授权API的应用,只能最多保持10分钟的后台就会被iOS系统干掉。
所以在iOS上,大部分应用程序(比如微信,QQ,微博)都是通过注册苹果的推送API来监听数据的。
这意味着不管有多少应用程序在监听即时消息,iOS基本上只需要保持一个系统自带的推送长链接就可以了,听到消息后,iOS系统会把消息显示在锁屏界面和应用程序图标上,用户可以通过这些提示,自己启动相关的应用程序来查看推送消息,在用户主动查看这些消息之前,应用程序本身不会被启动,只有iOS自带的机制在分发这些消息。
而Android没有任何限制,这导致大量其实可以使用Google推送的应用程序,都是自己在后台开长链接来监听数据的。
在Android系统上,长期开着几十个长链接的“壮观”场面经常可见。保持数据链接都是要耗电的,耗电可想而知。
- 不释放wakelock锁。
Android上有大量的烂应用在干这种事情。
Android使用一个叫做owerManager.WakerLock的类来允许应用程序控制设备电源管理。
Wakerlock分为好几种,烂应用们主要是使用PARTIAL_WAKE_LOCK来干坏事的。
这个锁允许关闭屏幕,但会保持CPU一直运行指定的进程。
这个锁会阻止CPU进入深度休眠模式(deep sleep),带来大量的后台电力消耗。
你有没有遇到过100%电力飞行模式一夜之后就剩个40%?
有没有遇到莫名其妙的猴机待机一上午电池就挂了?
恭喜你,partial wake lock!
先抒发一下自己的怨念,点名批评一个烂应用 - 盛大云中书城。
这个应用自从发布起到现在最新的2.3.2版本从来不释放PARTIAL_WAKE_LOCK锁。
该应用在启动时即持有锁,直到用户显式退出应用后才释放锁(我猜他们根本就没写释放锁的代码,是系统做清理工作时自动释放的)。
保留云中书城在后台半天就能把你的电池干掉。
很难想象像盛大这种级别的公司在推出应用程序前不做一个电池消耗测试。
你们的Android程序员和QA是800块钱包吃包住请来的吗?
另外说一下Google的C2DM推送。
现在已经被最新的GCM(google cloud messaging)推送代替了。
Google推送有一个地方做得非常欠考虑,就是推送必须要有Google帐号支持。
换句话说,如果你的猴机本身没有装Google套件,或者你跳过了注册/登录Google帐号的步骤,Google推送是无法工作的。
我想这也是为什么现在大部分应用都拒绝使用Google推送的原因 - 谁能保证所有的Android机器上都有Google帐号呢?
一些做的比较细致的应用程序会判断一下,如果有Google帐号就使用Google推送,如果没有帐号就自己用tcp长链接来实现推送。
但我观察到几乎所有国产应用程序,包括微信,都是直接使用tcp长链接做推送的,完全不管Google推送是否有效。
对比一下iOS的推送机制,iOS推送并不需要用户注册一个apple id来实现。
所以iOS软件可以放心使用推送机制而不用考虑太多,iOS推送在任何系统版本和任何情况下都能工作(不管你是否有Apple id)。
Android应用程序如果要使用Google推送,就必须检查当前Google account的状态(以确定Google推送是可工作的),并且还必须实现另外一套自己的推送(万一用户没有Google id呢?)。
这无疑增加了软件的复杂性,这也是Google推送当前的使用率很低的原因之一。
希望Google尽早实现不依赖于Google帐号而依赖于设备uuid的推送方式。
也希望Google能够在下一个大版本升级中禁止应用使用自己的后台长链接。
在写优化方案之前先说一句,如果你是一名软件开发者,或者是对进程/线程和Android基础编程有一点点了解,最好用的耗电分析工具就是Google自家的Android调试工具 [ DDMS ]
使用DDMS并不复杂,你只需要用USB连接手机到电脑,打开手机上的usb调试开关,就可以在DDMS上看到非常详细的应用程序信息。
比如用DDMS来监控应用程序是在什么时间通过哪个端口请求网络数据的,可以非常明白的看出哪些应用程序在后台保持着长链接来获得推送数据(并消耗相当的电力)。
这里能看到的信息要比任何Android上的xx大师,xx专家都要丰富,准确得多。
考虑到这是训猴的初级教程,这里就不多介绍DDMS这样的开发者工具了。
接下来介绍一下如何查看/发现烂app们,如何(在一定程度上)限制它们胡乱吃电力的行为。
首先要明确一点:Android自带的电力消耗分析工具是 不准确 的(设定-》电池使用-》排行榜),在它的数据之上,衍生出来的xx电池医生,xxx专家的数据 也是不准确 的。
有的应用在这个排行榜上排名很低,但其实消耗了大量的电力。
它不准确的原因主要有:
[list]
[*]只计算应用程序占用cpu时间,并用这个时间和在这个时间段里cpu/gpu的频率来计算耗电情况。
我可以写一个应用程序,以100ms左右的时间间隔唤醒CPU,然后占用5ms,马上睡眠,等到下一个100ms……
这样的情况下,Android系统统计出来的耗电量是相当小的(因为每次只占用cpu 5ms),但其实这样的做法会使得cpu永远不能进入deep sleep,实际带来很大的耗电开销 - 很多在后台跑着拉广告的国产应用程序就是这么写的。
[*]如果应用程序调用Google backgroud transport等远程服务接口来传输数据,这部分耗电量会计算到Android系统上面去,而不是这个应用程序本身。
这也就是为啥有人贴出的耗电情况,Android系统有时能占用到60%以上。
[*]不计算应用程序使用通信模块的电力消耗。
保持后台数据链接会带来明显的电力消耗,但对cpu/gpu使用却很少。
你把电池充满,不要打开待机模式,放一晚上,一直开着微信(这个应用会长期维持后台数据链接),你看看电力消耗排行,微信是不是很小,小到可以忽略?
明白了吧?(当然坦白的说,单一应用维持后台数据耗电量确实不大,但如果有5个呢?有10个呢?考虑到像百度地图,大众点评,淘宝这样的应用都要不知所谓的保持后台数据链接,总的消耗量就不小了)
[*]在编程上还有其他技巧可以绕开Android电力消耗检测。鉴于这是初级教程,不多说了~
[list]
[*]只计算应用程序占用cpu时间,并用这个时间和在这个时间段里cpu/gpu的频率来计算耗电情况。
我可以写一个应用程序,以100ms左右的时间间隔唤醒CPU,然后占用5ms,马上睡眠,等到下一个100ms……
这样的情况下,Android系统统计出来的耗电量是相当小的(因为每次只占用cpu 5ms),但其实这样的做法会使得cpu永远不能进入deep sleep,实际带来很大的耗电开销 - 很多在后台跑着拉广告的国产应用程序就是这么写的。
[*]如果应用程序调用Google backgroud transport等远程服务接口来传输数据,这部分耗电量会计算到Android系统上面去,而不是这个应用程序本身。
这也就是为啥有人贴出的耗电情况,Android系统有时能占用到60%以上。
[*]不计算应用程序使用通信模块的电力消耗。
保持后台数据链接会带来明显的电力消耗,但对cpu/gpu使用却很少。
你把电池充满,不要打开待机模式,放一晚上,一直开着微信(这个应用会长期维持后台数据链接),你看看电力消耗排行,微信是不是很小,小到可以忽略?
明白了吧?(当然坦白的说,单一应用维持后台数据耗电量确实不大,但如果有5个呢?有10个呢?考虑到像百度地图,大众点评,淘宝这样的应用都要不知所谓的保持后台数据链接,总的消耗量就不小了)
[*]在编程上还有其他技巧可以绕开Android电力消耗检测。鉴于这是初级教程,不多说了~
根据上面所说的情况,总结一下我们调教猴机的主要工作应该是:
- 发现耗电应用程序 工具:betterbatterystats, cpu spy,DDMS(这个属于高级教程,暂时不涉及)
- 限制耗电应用:
工具:钛备份 ,autostarts, LBE安全大师,Droidwall - 后台定期扫除耗电应用:
工具:advanced task manager, Juice Defender(很好用的工具,功能众多,但几句话真说不清楚。还是放到以后的高级教程里面吧)
节电教程第一步,干掉应用程序后台自动启动
几乎所有的应用程序都不需要通过监听系统事件自动启动。有同学要问,我要是禁止短信程序自动启动,是不是就收不到短信了?
答案是No,因为这不是通过监听系统事件(BroadcastReceiver)实现的。
如果一个应用是某种intent的默认应用,Android UI线程会通过发intent的方式直接把应用调起来。
禁用软件自启如何实现的?其实就是修改应用程序注册到broadcast事件的钩子。
大家可以写一段代码就知道了,被禁用自启的应用程序是收不到相应的系统广播的。
所以请放心的禁用应用程序的自启动吧。
工具是autostarts和LBE安全大师。
LBE安全大师更简单直观,合适初学者,并且它可以阻止你禁用不应该被禁用的系统应用,比如calendar storage(该系统应用为输入法进程提供服务),可以防止初学者干傻事儿把Android系统搞出问题来。
作为初级教程,我推荐大家使用LBE的“自启管家”功能。
可以允许自启动的系统应用有两个:日程存储和Download manager,其他的可以统统放心禁用。不会出事儿的。
当然,作为国产应用的非常典型的特点,LBE自带了很多花哨的垃圾功能,比如病毒检测,通信拦截一类的。
建议除了自启管家和主动防御之外的功能全部关掉。主动防御也很好用,但不属于这个教程我就不多说了。
autostarts的设置要丰富很多,可以选择阻止特定应用听到特定类型的broadcast,但太细的设置我认为没有必要.
同时autostarts没有防呆功能,你可能把Android系统的关键服务也禁掉,不适合咱入门教材的定位。
一般可以运行自动启动的软件有:
- 桌面类软件(我用小米桌面)
- 通信拨号类软件(QQ通信录,触宝拨号这样的)
- 你需要随时获得推送的软件(QQ,微信这样的)
- 系统配置软件(LBE,setcpu,autostarts,droidwall)
节电第二步,寻找电池杀手
电池杀手尤其指两种应用程序:不释放wake lock的应用和长期保持后台数据连接的应用。
对于后者,一些国产应用软件尤其恶劣,看过大量国内软件市场上的国产软件注册network stat的广播,一旦有网络可用就打开数据连接去网上取广告。
寻找第一种电池杀手的最简单方法是安装betterbatterystats。这个软件可以检查所有类型的wake lock持有情况(被哪个软件持有,持有了多长时间)。在驯猴时应该重点关注PARTIAL_WAKE_LOCK。对于初级驯猴员来说,可以按照这样的步骤走:
- 安装betterbatterystats
- 确保它在允许自动启动的名单里(如果你已经用LBE或者autostarts驯猴的话)
- 重启一次手机。
- 打开所有你常用的应用。
- 手机关闭屏幕放几分钟。
- 打开屏幕,打开betterbatterystats,选择"since boot",选择PARTIAL_WAKE_LOCK。
- 正常应用可能会很短时间(几秒到1分钟左右)持有PARTIAL_WAKE_LOCK,比如你正在通过google play下载应用程序,关闭屏幕后google play就会持有该锁直到下载完成。
- 2B应用例如云中书城就会一直持有该锁直到把手机电池耗光为止。
这个google自己弄出来bug会导致锁屏音效应用不释放wake lock从而大量消耗电力。
遇到此情况需要升级到4.0.4 或者在设置里面关闭锁屏声音。
节电第三步,干掉电池杀手
有时候比较尴尬的情况是,你不得不依赖某些有缺陷的应用软件。
把所有2b程序全部卸载掉可能不是最好的选择,所以我们需要蹲在地上好好想一想这个问题。
对大部分应用来说,耗电问题主要是跑在后台和待机的情况下特别突出。
跑在前台其实是无所谓的 - 对于前台应用来讲,屏幕是耗电大头,程序代码写差点无所谓,Google虚拟机优化得很不错,甭说你800块钱包吃住,300块钱包吃住写出来的代码也扛得住。
我的解决方案是使用advanced task manager。
这个任务管理器有两大特点:第一,支持白名单。第二,支持条件触发:关屏后延时1分钟(可设定)清理后台应用程序。
第二点对我来说实在太好用了 - 关屏一分钟以后干掉后台应用,这不就是iOS了么亲!
我推荐这样设置advanced task manager:
- 设置一个白名单,把需要在关屏后保留在后台的应用程式放入白名单。
对于我来说,主要是桌面(小米桌面),拨号器(触宝),浏览器(系统自带和UC),IM即时通信(微信),音乐程序(QQ音乐)和邮件推送(系统自带)。
其他应用可以在需要时再开启,没必要常驻后台。
这个名单每个人可能都不一样,大家根据自己需要设定。 - 设置advanced task manager,关屏后延时1分钟清理所有非白名单应用。
为什么要延时一分钟?因为我不想正在用"云中书城"看书,不小心按了下电源键关屏,赶紧打开屏幕却发现它已经被干掉了。
你可以调节这个值到30秒,或者5分钟,或者10分钟,丰俭由人。