移动互联网的大潮到来以后,咱们都变身好男人:“用智能手机的男人都是好男人,由于晚上必须回家充电。”一句笑言,但也能够看得出来目前使用智能设备电量方面的问题。javascript
而开发者在电量消耗方面也起到了推波助澜的做用:相比于卡顿、内存泄漏等问题,开发者对电量消耗的重视程度极低;html
然而开发者的不关注并不表明用户的忽视,Android设备用户会广泛装载管家类App,经过这些管家App,用户能够轻松找到那些“电池杀手”应用,而后就是删除————》差评————》转向竞争对手应用一条龙。所以对于开发者而言要尽可能少用电量,合理使用电池。本节就来一块儿探索既能够省电,又不影响用户体验的方法。java
Android4.1版本以后在系统增长了battery info模块,记录必定时间周期内整机及单个App的电量消耗。android
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
registerReceiver(filter,receiver);复制代码
而后就能够获取电池电量、充电状态、电池状态等信息。具体参考BatteryManager。
缺点:github
最强大、最推荐的工具:Battery Historian是Android5.0以后Google开源的一款用于检测与电池有关的信息和事件的工具,从设备中收集电池数据,而后使用Battery Historian能够可视化分析相关指标如耗电比例、Wifi、蜂窝数据量、WakeLock唤醒次数。随着Android6.0更新了Battery Historian 2.0加入引发手机状态变化的应用。shell
经过Battery Historian能够方便的看到各耗电模块随着时间的耗电状况:包含操做类型、执行时间、对应App等;还能够进行筛选特定的App,给出一个总结性的说明,包括:Network Information、 Syncs、WakeLock、Services、Process info、Scheduled Job、Sensor Use等,查看每个模块的总结,能够看出来每一项的耗时以及执行次数。当发现异常的时候能够针对性的进行排查。总之:Battery Historian真的很强大。性能优化
adb命令导出电量信息:服务器
adb shell dumpsys batterystats --reset(Android4.1到4.3 adb shell dumpsys batteryinfo)
adb bugreport > bugreport.txt(Android7.0以上 adb bugreport bugreport.zip)复制代码
安装Battery Historian后打开:http: //localhost:9999/, 上传bugreport.txt文件开始分析,下图分析360手机助手为例;微信
悄悄的告诉你:360手机助手相比于通常应用耗电的场景更多哦,固然对于一个超级App,也不能过多要求。
安装过程能够参考Github:battery-historian。备注:我使用Docker的方式并无执行成功,经过Go的方式完成的。
Android系统上App的电量消耗主要由cpu、wakelock、数据传输(流量和wifi)、wifi运行、gps、other senior组成,而耗电异常也是因为这几个模块的使用不当。
当检测到CPU时间片消耗异常时,须要使用TraceView,获取进程执行信息,定位CPU占用率异常的问题,关于CPU的使用能够参照《Android性能优化(一)之启动加速35%
》一文。
Full power: 能量最高的状态,移动网络链接被激活,容许设备以最大的传输速率进行操做。
Low power: 一种中间状态,对电量的消耗差很少是Full power状态下的50%。
Standby: 最低的状态,没有数据链接须要传输,电量消耗最少。
经过数据压缩等方式缩减传输时间,下降电量消耗,此章节能够参考《Android 性能优化(八)之网络优化》。
虽然3G芯片比Wifi芯片耗电低,但Wifi的速率可让数据在较短期内完成传输,从而下降电量消耗。
分析和统计之类的非重要操做,能够在合适状态(电量充足或Wifi状态)下发送。参见3.6节JobScheduler。
以前在网络优化的文章里写过,网络请求失败以后的重试机制,可是要注意这个重试是在有网状态下的重试。不然无网状态下重试不会请求成功,只会消耗电量。尤为是与AlarmManager或者WakeLock连用的场景下,耗电量会更多。
定位是App中经常使用的功能,可是定位不能千篇一概,不一样的场景以及不一样类型的App对定位更加须要个性化的区分。
Android系统支持多个Location Provider:
GPS_PROVIDER:
GPS定位,利用GPS芯片经过卫星得到本身的位置信息。定位精准度高,通常在10米左右,耗电量大;可是在室内,GPS定位基本没用。
NETWORK_PROVIDER:
网络定位,利用手机基站和WIFI节点的地址来大体定位位置,这种定位方式取决于服务器,即取决于将基站或WIF节点信息翻译成位置信息的服务器的能力。
PASSIVE_PROVIDER:
被动定位,就是用现成的,当其余应用使用定位更新了定位信息,系统会保存下来,该应用接收到消息后直接读取就能够了。好比若是系统中已经安装了百度地图,高德地图(室内能够实现精肯定位),你只要使用它们定位事后,再使用这种方法在你的程序确定是能够拿到比较精确的定位信息。
使用Criteria,设置合适的模式、功耗、海拔、速度等需求,系统会返回合适的Location Provider。
例如你的App只是须要一个粗略的定位那么就不须要使用GPS进行定位,既耗费电量,定位的耗时也久。
在获取到定位以后或者程序处于后台时,注销定位监听,此时监听GPS传感器至关于执行no-op(无操做指令),用户不会有感知可是却耗电。
public void onPause() {
super.onPause();
locationManager.removeListener(locationListener);
}
public void onResume(){
super.onResume();
locationManager.requestLocationUpdates(locationManager.getBestProvider(criteria, true),6000,100,locationListener);
}复制代码
多个模块使用定位,尽可能复用上一次的结果,而不是都从新走定位的过程,节省电量损耗;例如:在应用启动的时候获取一次定位,保存结果,以后再用到定位的地方都直接去取。
Android为了节省电量,会在用户无操做一段时间以后进入休眠状态。Wake Lock是一种锁的机制,只要有人拿着这个锁,系统就没法进入休眠。一些App为了能在后台持续作事情,就会持有一个WakeLock,那么手机就不会进入休眠状态,App要作的事情能作了,可是也更加耗电。
PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK| PowerManager.ON_AFTER_RELEASE,TAG);
wl.acquire(TIMEOUT);// 使用带有超时参数的acquire方法
// ... do work...
wl.release();复制代码
备注:若是只是须要屏幕常亮的话,可使用FLAG_KEEP_SCREEN_ON,无需考虑释放WakeLock的问题。使用传感器,选择合适的采样率,越高的采样率类型则越费电;
SENSOR_DELAY_NOMAL (200000微秒)
SENSOR_DELAY_UI (60000微秒)
SENSOR_DELAY_GAME (20000微秒)
SENSOR_DELAY_FASTEST (0微秒)
在后台时注意及时注销传感器监听;
使用JobScheduler,一些任务经过JobScheduler来触发,例如可推迟的网络请求、下载、GPS等,能够在特定场景:链接Wifi、链接电源等场景触发。既完成了任务,也无需考虑因为一些任务致使的电量消耗。
一直有一种传言:Android系统比较费电,然而真相不是这样,请不要把锅甩给Android系统:
电量优化能够说是开发者和QA最不关注的一个方面了,可是若是任而由之,变成“电量杀手”不只仅是伤害用户的体验,也是对本身的放纵。性能问题不只仅在于发现以后的优化更改,更在平时的防微杜渐。
参考:
欢迎关注微信公众号:按期分享Java、Android干货!