冲天香阵透长安,满城尽带黄金甲。这篇文章主要讲述Android电量优化相关的知识,希望能为你提供帮助。
最近领导老是反映说我们的APP耗电要比以前厉害一些,排在耗电量的首位,上黑名单了,需要进行电量优化!经过一段时间的研究,自己做了一部分的总结!
电量优化的工具battery-historien battery-historien是google开源的电量检测分析的工具,由于很多APP开发者对电量这快关注不是那么多,star数并不是特别多!
链接:https://github.com/google/battery-historian上面有具体环境搭建步骤!
环境搭建步骤
我使用的是方法二,步骤如下:
1.下载go,安装,
指定path路径
2.下载python,
安装,
指定path
3.下载git,安装
4.下载java,
安装,
指定path
5.下载源码
go get -d -u github.com/google/battery-historian/…
6.运行源码,
下载依赖
cd $GOPATH/src/github.com/google/battery-historian
go run setup.go
发现下载不下来,
手动下载closure-library,
closure-compiler,
flot-axislabels
分别解压到third_party下面7.运行监听
go run cmd/battery-historian/battery-historian.go
2017/04/16 18:23:02 Listening on port:99998.检验运行情况
http://localhost:9999
2017/04/16 18:23:09 Trace starting analysisServer processing for: GET
2017/04/16 18:23:09 Trace finished analysisServer processing for: GET
导出电量文件与分析 导出文件
导出文件使用ADB命令来生成文件:
adb kill-server
adb start-server
// 打开电池数据获取
adb shell dumpsys batterystats --enable full-wake-history
// 电池数据重置
adb shell dumpsys batterystats --reset
// 生成电量数据到文件
adb bugreport >
bugreport.txt
分析文件:
分析文件有两种方式:
上传文件分析 一是上传文件到服务器进行分析,但是不知道什么原因,失败了!
在battery-historian目录下打开GUI bash,执行:
go run cmd/battery-historian/battery-historian.go
historian.py
浏览器打开:http://localhost:9999/
但是并没有什么卵用!
生成的txt文件是无法上传进行分析的,
可能是因为不兼容
文章图片
选择生成的文件之后就没有后文了!表示很伤心!果断使用第二种!
转换为html文件分析
使用python脚本进行分析,下载脚本到相应目录
文章图片
使用命令将txt生成html文件:
python historian.py -a bugreport.txt >
battery.htmlWARNING: Visualizer disabled. If you see this message, download the HTML then open it.需要翻墙
打开html文件就可以看到电量消耗情况:
文章图片
文章图片
字段分析
plugged 充电状态
top 那个app运行在最上面
sync 跟后台同步
wake_lock cpu的唤醒锁
job 服务,
后台任务
running
connection
wifi
mobile_ratio 蜂窝信号
主要耗电的地方:屏幕亮屏,蜂窝移动数据(3G,4G),WIFI,CPU/GPU工作,我们需要特别关注这些方面!
优化策略 电量优化策略:
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数据下操作!
//判断网络连接 private boolean isNetWorkConnected() {
ConnectivityManager connectivityManager =
(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo =
connectivityManager.getActiveNetworkInfo();
return (activeNetworkInfo!=
null&
&
activeNetworkInfo.isConnected());
}
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一次就可以解除了
使用WEAK_LOCK:
// 注册权限
<
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是成对出现的。
需要注意
1.唤醒CPU频率
唤醒CPU的频率也不能太高,
不然可能会出现一些问题,
比如小米手机做了同步心跳(
心跳对齐)
,
如果超出了这个心跳的频率,
就会被
屏蔽或者降频!
2.使用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);
}
【Android电量优化】3.保持屏幕常量
在屏幕关闭之后,系统休眠,一些任务可能会被暂停(Timer、Handler、Thread、Service),但是某些情况下我们需要保持屏幕常量,或者不需要屏幕常量但是需要CPU一直执行,直到任务的执行完成,那么我们可以手动设置屏幕常亮!
//在Acitivty里面使用Flag
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
FLAG_KEEP_SCREEN_ON的好处是使用方便,不要额外的权限!
推荐阅读
- 奔腾G5400配啥主板好?奔腾G5400主板搭配攻略
- 在Android Studio中查看Sqlite的方法
- android 关闭应用
- 组队APP功能点定点NABCD分析
- Android开发之《ffmpeg解码mjpeg视频流》
- Android深入四大组件Service的启动过程
- android4.4上全屏界面实现禁止状态栏下拉
- [Android] 在WebView的页面中直接使用res中的图片
- AutoMapper实际项目运用