执行代码(显而易见)
数据传输(上传和下载,使用WiFi,2G,3G,4G)
定位
传感器
渲染图像
唤醒任务
adb kill-server
adb devices
adb shell dumpsys batterystats --reset
上面的操作执行完毕后,拔掉手机,操作你的App,操作完成后,重新连接手机,执行下面的命令,收集Battery数据:
adb shell dumpsys batterystats > batterystats.txt
得到这些数据后,这个时候使用我们的battery-historian来生成我们可见HTML报告:
Python historian.py batterystats.txt > batterystats.html
Battery Historian
最强大、最推荐的工具:Battery Historian是Android5.0之后Google开源的一款用于检测与电池有关的信息和事件的工具,从设备中收集电池数据,然后使用Battery Historian可以可视化分析相关指标如耗电比例、Wifi、蜂窝数据量、WakeLock唤醒次数。随着Android6.0更新了Battery Historian 2.0加入引起手机状态变化的应用。
通过Battery Historian可以方便的看到各耗电模块随着时间的耗电情况:包含操作类型、执行时间、对应App等;还可以进行筛选特定的App,给出一个总结性的说明,包括:Network Information、 Syncs、WakeLock、Services、Process info、Scheduled Job、Sensor Use等,查看每一个模块的总结,可以看出来每一项的耗时以及执行次数。当发现异常的时候可以针对性的进行排查。总之:Battery Historian真的很强大
http://duanqz.github.io/2015-07-21-batterystats-part1
1.CPU时间片优化
1.充电进行某些操作
某些不需要及时与用户进行交互的操作,可以放到充电后再进行,比如拍照后图片处理,360手机助手在手机充电后才自动清理
垃圾,联系人数据上传到云端等等。。。
监听电池充电操作
IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batteryStatus = this.registerReceiver(null, filter);
//几种充电方式:直流充电,USB充电,无线充电
int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
boolean usbCharge = (chargePlug == BatteryManager.BATTERY_PLUGGED_USB);
boolean acCharge = (chargePlug == BatteryManager.BATTERY_PLUGGED_AC);
boolean wirelessCharge = false;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
wirelessCharge = (chargePlug == BatteryManager.BATTERY_PLUGGED_WIRELESS);
}
return (usbCharge || acCharge || wirelessCharge);
}
2.WIFI状态下进行操作
我们知道在蜂窝无线网络状态下会比WIFI状态下耗电的多,所以尽量减少移动网络下的数据传输,多在WIFI数据下操作!
//判断网络连接
3.网络请求设置超时
在网络请求时,如果网络很差,请求需要很长时间,我们需要设置超时时间,减少网络消耗!
4.任务集中处理JobScheduler
使用JobScheduler来处理一些特定的操作
JobScheduler jobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
for (int i = 0; i < 10; i++) {
JobInfo jobInfo = new JobInfo.Builder(i,componentname)
.setMinimumLatency(10000)//最小延时
.setOverrideDeadline(60000)//最多执行时间
// .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)//免费的网络(wifi/蓝牙/USB),满足该条件才去执行
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)//任意网络---wifi
.build();
jobScheduler.schedule(jobInfo);
}
// 任务处理
public class JobServiceTest extends JobService {}
缺点就是有API限制
5.WEAK_LOCK谨慎使用
WEAK_LOCK主要是用来处理系统休眠的,我们知道系统为了省电一般会在熄屏之后进行休眠,休眠之后所有的操作就会被暂停冷冻了(Timer,Services),
休眠之后一些后台的网络访问操作就会被停止,可能就会导致一些问题,比如即时通讯的心跳包不能及时发出,导致收不到消息,
为了防止这些情况,需要使用WEAK_LOCK来唤醒CPU,权利配合我们的程序执行!
wake_lock:两种锁,一种计数锁(锁一次,释放一次);非计数锁(锁了很多次,只需要release一次就可以解除了
// 注册权限
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"MyWakelockTag");
mWakelock.acquire();//唤醒CPU
mWakelock.release();//释放CPU锁
注意:在使用该类的时候,必须保证acquire和release是成对出现的。
3.3 GPS
定位是App中常用的功能,但是定位不能千篇一律,不同的场景以及不同类型的App对定位更加需要个性化的区分。
3.3.1 选择合适的Location Provider
Android系统支持多个Location Provider:
GPS_PROVIDER:
GPS定位,利用GPS芯片通过卫星获得自己的位置信息。定位精准度高,一般在10米左右,耗电量大;但是在室内,GPS定位基本没用。
NETWORK_PROVIDER:
网络定位,利用手机基站和WIFI节点的地址来大致定位位置,这种定位方式取决于服务器,即取决于将基站或WIF节点信息翻译成位置信息的服务器的能力。
PASSIVE_PROVIDER:
被动定位,就是用现成的,当其他应用使用定位更新了定位信息,系统会保存下来,该应用接收到消息后直接读取就可以了。比如如果系统中已经安装了百度地图,高德地图(室内可以实现精确定位),你只要使用它们定位过后,再使用这种方法在你的程序肯定是可以拿到比较精确的定位信息。
使用Criteria,设置合适的模式、功耗、海拔、速度等需求,系统会返回合适的Location Provider。
例如你的App只是需要一个粗略的定位那么就不需要使用GPS进行定位,既耗费电量,定位的耗时也久。
3.3.2 及时注销定位监听
在获取到定位之后或者程序处于后台时,注销定位监听,此时监听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);
}
3.3.3 多模块使用定位尽量复用
多个模块使用定位,尽量复用上一次的结果,而不是都重新走定位的过程,节省电量损耗;例如:在应用启动的时候获取一次定位,保存结果,之后再用到定位的地方都直接去取。
谨慎使用WakeLock
Android为了节省电量,会在用户无操作一段时间之后进入休眠状态。Wake Lock是一种锁的机制,只要有人拿着这个锁,系统就无法进入休眠。一些App为了能在后台持续做事情,就会持有一个WakeLock,那么手机就不会进入休眠状态,App要做的事情能做了,但是也更加耗电。
App在前台不要申请WakeLock,此时无需申请,申请的话会计算到应用电量消耗;
App在后台由于业务需要必须要申请WakeLock时使用带有超时参数的方法,防止由于忘记或者异常情况下没有释放;
App申请使用WakeLock,任务结束之后及时释放,让系统再次进入休眠状态。
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();
传感器使用
使用传感器,选择合适的采样率,越高的采样率类型则越费电;
SENSOR_DELAY_NOMAL (200000微秒)
SENSOR_DELAY_UI (60000微秒)
SENSOR_DELAY_GAME (20000微秒)
SENSOR_DELAY_FASTEST (0微秒)
在后台时注意及时注销传感器监听
https://juejin.im/post/58fef4771b69e60058aab2d1
https://juejin.im/post/579f251e8ac247005fed1be7
http://www.jianshu.com/p/afd4d8a6dcd6
http://javayhu.me/blog/2017/01/24/how-to-know-your-applications-battery-stats/
http://blog.csdn.net/itfootball/article/details/49004699
http://blog.csdn.net/itfootball/article/details/44084159
http://www.07net01.com/linux/2016/01/1207924.html
http://www.jianshu.com/p/f4b710b13e6d
https://blog.wilddog.com/?p=948
http://hukai.me/android-performance-battery/
http://blog.csdn.net/zhaodecang/article/details/53345861
http://www.jianshu.com/p/5d83d8649c98
https://www.zhihu.com/question/37483907
https://blog.wilddog.com/?cat=67
http://duanqz.github.io/2015-07-21-batterystats-part1
1.使用AlarmManager
AlarmManager是系统的闹钟服务,可以用来唤醒CPU,做一些后台的任务,即使在屏幕熄灭后也能正常的工作(定时任务尽量不要使用Timer、Handler、Thread、Service)
Intent intent = new Intent(context, Service.class);
PendingIntent pi = PendingIntent.getService(context, 1, intent, 0);
AlarmManager alarm = (AlarmManager) getSystemService(Service.ALARM_SERVICE);
if(alarm != null)
{
alarm.cancel(pi);
// 闹钟在系统睡眠状态下会唤醒系统并执行提示功能
alarm.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 1000, 2000, pi);// 确切的时间闹钟//alarm.setExact(…);
//alarm.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), pi);
}
网友评论