千金一刻莫空度,老大无成空自伤。这篇文章主要讲述Android应用耗电问题排查相关的知识,希望能为你提供帮助。
1 耗电定位工具与方法
1-1 系统提供的battery信息
1-1-1 在android 4.4 KitKat 以前使用
adb shell dumpsys batteryinfo >
d:/batterinfo.log
获取电量日志
1-1-2 在Android 4.4 KitKat 及以后使用
- 获取日志
adb shell dumpsys batterystats >
d:/batterstats.log
获取电量日志可以使用命令清除记录后重新记录
adb shell dumpsys batterystats --enable full-wake-history
adb shell dumpsys batterystats –reset
- 分析
Battery History
电量相关数据的时间序列:
0 (52) RESET:TIME: 2017-08-17-15-29-36
0 (2) 099 status=
discharging health=
good plug=
none temp=
350 volt=
4218 +
running +
wake_lock +
wifi_scan +
screen phone_state=
off brightness=
dim +
wifi_running +
wifi wifi_signal_strength=
4 wifi_suppl=
completed proc=
u0a501:"
com.tencent.mm:push"
0 (2) 099 proc=
u0a49:"
com.huawei.android.remotecontrol"
0 (2) 099 proc=
1000:"
com.huawei.geofence"
0 (2) 099 proc=
1000:"
WebViewLoader-armeabi-v7a"
0 (2) 099 proc=
u0a642:"
com.wukongtv.wukongtv:Global"
0 (2) 099 proc=
1000:"
com.huawei.android.pushagent.PushService"
0 (2) 099 proc=
1000:"
WebViewLoader-arm64-v8a"
0 (2) 099 proc=
u0a642:"
com.wukong.daemon"
0 (2) 099 proc=
1000:"
com.huawei.powergenie"
0 (2) 099 proc=
u0a45:"
com.huawei.android.hwouc:hwbd"
Per-PID Stats
每一个进程执行了多长的时间
PID 0 wake time: +
21s516ms
PID 3438 wake time: +
10m38s598ms
PID 4044 wake time: +
2s286ms
PID 4176 wake time: +
2s682ms
PID 4573 wake time: +
3s825ms
PID 8587 wake time: +
3m49s32ms
PID 4616 wake time: +
12s392ms
Statistics since last charge
上次充电以来的数据记录
System starts: 0, currently on battery: false
Time on battery: 6h 41m 34s 718ms (98.8%) realtime, 2h 39m 54s 65ms (39.3%) uptime
Time on battery screen off: 4h 13m 47s 988ms (62.5%) realtime, 12m 7s 335ms (3.0%) uptime
Total run time: 6h 46m 22s 139ms realtime, 2h 44m 41s 485ms uptime
Start clock time: 2017-08-17-15-29-36
Screen on: 2h 27m 46s 730ms (36.8%) 10x, Interactive: 2h 27m 46s 309ms (36.8%)
Estimated power use (mAh)
目前只能算比较粗略的估计, 不能作为实际消耗数据, 其他google更为精准的数据
Capacity: 3000, Computed drain: 1413, actual drain: 1110-1140
Screen: 561
Uid 1000: 282
Uid u0a643: 240
Uid u0a623: 196
Uid 0: 69.3
Idle: 12.7
Uid u0a642: 11.0
All partial wake locks
所有程序中wakelock, 关注持续时间和数量
Wake lock 1000 ConnectivityService: 3m 20s 310ms (4 times) realtime
Wake lock 1000 dispatcher: 1m 31s 411ms (19 times) realtime
Wake lock u0a501 WakerLock:341975309: 54s 332ms (47 times) realtime
Wake lock 1013 AudioMix: 33s 57ms (18 times) realtime
Wake lock u0a623 PushManager: 21s 960ms (26 times) realtime
Wake lock 1000 *alarm*: 7s 239ms (87 times) realtime
Wake lock 1000 GpsLocationProvider: 7s 2ms (4 times) realtime
Wake lock 1000 AudioMix: 3s 736ms (6 times) realtime
最后是每个应用的详细信息, 包含了Wake lock、Proc 信息、Foreground时间、CPU消耗时间、Service信息等; 分析某个应用的具体运行情况、是否异常, 主要可以参考这项数据;
1001:
Wake lock RILJ: 16ms partial (5 times) realtime
Foreground activities: 1s 566ms realtime (2 times)
Foreground for: 6h 41m 34s 718ms
Proc com.android.server.telecom:
CPU: 60ms usr +
30ms krn ;
0ms fg
Proc com.android.phone:
CPU: 40s 960ms usr +
30s 250ms krn ;
430ms fg
Apk com.android.phone.recorder:
Service com.android.phone.recorder.RecorderServer:
Created for: 0ms uptime
Starts: 0, launches: 1
1-1-3 在Android 5.0以后使用
- 获取日志
adb shell dumpsys batterystats --enable full-wake-history
shell dumpsys batterystats –reset
通过命令获得日志文件, 获取时间较长, 稍等片刻
adb bugreport >
d:/bugreport.txt
- 分析
得到batterstats.log日志后, 这个时候使用我们的battery-historian来生成可视化的html报告, 具体生成方式参考[http://blog.csdn.net/itfootball/article/details/44084159]

文章图片
battery-historian工具也可以分析通过
dumpsys batterystats
方式获得的日志B. Battery Historian 2.0
新版本带来了很多的改进: 更清晰的报告, 每个应用程序的摘要, 更快的执行等等。
安装参考: [http://www.07net01.com/linux/2016/01/1207924.html]
提示: 安装时用go命令无法从github下载的时候可以直接上github手动下载; 使用时也需要翻墙才能分析报告;

文章图片
通过可视化的报告可以更直观清晰的观测到手机的整体使用情况, 各个时间段前台后台应用的使用、手机各项指标以及每个应用程序独立的报告; 从报告可以观测出应用程序的运行情况、消耗、是否有异常行为等
1-2 显示CPU使用情况 CPU Usage data 在开发者选项中, 打开显示CPU使用情况开关
如下图:

文章图片
- 在右边会显示当前运行的进程列表, 排列顺序是按照CPU占用降序排列, 越往上表示消耗CPU越多
- 绿色表示 userspace占用cpu百分比,红色表示kernel 占用cpu百分比,蓝色表示 io interrupt 占用cpu百分比.
- 第一行表示所有进程叠加的占用CPU百分比, 从左到右三个数表示userspace, kernel, io interrupt
1-3 使用Android Monitor监测具体进程 对于debug版的应用程序, 使用Android Studio自带的Android Monitor工具可以观测该应用的某个进程, 如图所示

文章图片
通过检测某个进程的cpu, 网络及gpu, 可以看出静置状态下, 该进程的行为是否异常; 如果异常了, 能观测出异常规律就能回到代码找出异常;
1-4 使用DDMS中的Traceview进行定位 Traceview工具是一个分析器, 记录了应用程序中每个函数的执行时间;
打开DDMS, 然后选择一个进程, 接着点击上面的“Start Method Profiling”按钮( 红色小点变为黑色即开始运行) 。
打开我们怀疑的需要被测试的页面, 静置片刻, 然后点击开始按钮后, 过一段时间后( 时间根据自己需要定) , 再次点击该按钮停止记录, 稍等片刻即可出现下图, 如下:

文章图片
整个界面包括上下两部分, 上面是你测试的进程中每个线程运行的时间线, 下面是每个方法( 包含parent及child) 执行的各个指标的值。通过上图的时间面板可以直观发现, 哪些方法cpu消耗的多。当我们选择上面的一个线程后可以发现下面的性能面板很复杂, 其实这才是TraceView的核心图表, 它主要展示了线程中各个方法的调用信息( CPU使用时间、调用次数等) , 这些信息就是我们分析的核心关注点, 所以我们先看几个重要的属性说明, 如下:
属性名 | 含义 |
---|---|
name | 线程中调运的方法名 |
Incl CPU Time | 当前方法( 包含内部调运的子方法) 执行占用的CPU时间; |
Excl CPU Time | 当前方法( 不包含内部调运的子方法) 执行占用的CPU时间; |
Incl Real Time | 当前方法( 包含内部调运的子方法) 执行的真实时间, ms单位; |
Excl Real Time | 当前方法( 不包含内部调运的子方法) 执行的真实时间, ms单位; |
Calls+ Recur Calls/Total | 当前方法被调运的次数及递归调运占总调运次数百分比; |
CPU Time/Call | 当前方法调运CPU时间与调运次数比, 即当前方法平均执行CPU耗时时间; |
Real Time/Call | 当前方法调运真实时间与调运次数比, 即当前方法平均执行真实耗时时间; ( 重点关注) |
一般Traceview可以定位两类问题:
方法调运一次需要耗费很长时间;
方法调运一次耗时不长, 但被频繁调运导致累计时长多。
在定位耗电异常问题时, 可以打开Traceview然后按照Cpu Time/Call或者Real Time/Call进行降序排列, 然后打开可疑的方法及其child进行分析查看, 然后再回到代码定位检查逻辑优化即可;
PS: Android Studio新版本除过DDMS以外在CPU视图的左侧已经集成了Traceview( start Method Tracing) 功能
.trace文件如下:

文章图片
1-5 基于代码的排查 排查循环方法
搜索代码里面的定时循环执行的方法, 考量该方法的功耗;
包括: Timer、handler.Postdelayed、ScheduledFutureTask、JobService、Animation、AnimationDrawable等
写日志记录
A. 在关键地方及可疑地方打上日志;
B. 将日志按进程以及每小时一个分类存入本地文件中;
比如ProcessA-20161026090520.log、ProcessA-20161026100520.log
这样可以清楚的观测到哪些进程在哪些时间段有活动迹象; 看看有没有循环日志, 或者耗时方法, 再回到代码里去查看
分模块屏蔽
分模块屏蔽, 使用排除法来缩小范围, 最终定位到问题所在
2 实际排查过程中的分析与定位 这里仅限于讨论应用被静置情况下的耗电分析, 应用被操作时的性能优化请参考博文http://blog.csdn.net/yanbober/article/details/48394201
对于一个比较复杂的应用来说, 会有多进程、后台程序、拉活、push等情况, 需要分别从这些维度来分析: ( 启屏状态、灭屏状态) , ( 手机静置、操作) , ( 被测应用在前台、后台) , ( 长时间、短时间)
2-1 灭屏状态-被测应用在后台-手机静置 环境: 在手机屏幕处于关闭状态、被测应用在后台运行( 使用被测应用后正常退出应用, 可以将应用加白防止被系统杀进行测试, 手机处于桌面状态) 、手机静置状态下进行测试, 可以测试短时间也可以把手机放置长时间后再取数据
使用Battery Historian 2.0 + 日志记录方法来定位

文章图片
如上图从报告结果中查看被测应用详细信息, 可以看到应用的基本信息、电量消耗、wake lock、Service、Process等, 主要分析wake lock的次数是否合理、Service的启动次数、运行时长是否合理, 有没有出现没有及时关闭的情况、process的运行时长, 有没有及时关闭等;
结合日志记录, 定位出具体运行的逻辑, 判断这些逻辑是否在灭屏时未及时停止、评估逻辑的复杂度及是否耗电等
2-2 启屏状态-被测应用在后台 环境: 在手机屏幕处于开启状态、被测应用在后台运行( 使用被测应用后正常退出应用) , 可尝试正常使用手机玩其他应用或者停留在某个应用中静置
使用 显示CPU情况 + Traceview 来定位打开显示CPU情况 开关, 在使用手机的过程中, 观察被测应用所有的进程是否存在cpu消耗的情况, 有cpu消耗的会排在前面; 如果某个进程频繁的排在前面, 这个进程就是可疑的, 这时可以使用Traceview对可疑进程进行追踪, 查出哪些方法消耗cpu后进行优化;
2-3 启屏状态-被测应用在前台-静置 环境: 在手机屏幕处于开启状态、使用被测应用、停留在某个页面后静置( 尽量避开banner, 保证页面静置) , 观测该页面( 主要用于测试应用的各页面是否合理, 静置状态下不应该有cpu消耗)
使用 Android Monitor + Traceview 来定位打开Android Monitor, 观察各个进程的cpu、network、内存、gpu曲线; 从曲线中找出波峰规律( 有没有循环操作) 、判断曲线合理度( 是不是合理的逻辑操作) , 不合理的地方使用Traceview对可疑进程进行追踪, 查出哪些方法消耗cpu后进行优化;
被测应用前台静置界面的功耗问题主要考虑两个部分:
- 跟当前界面相关的循环执行逻辑
- 跟当前界面无关的循环执行逻辑( 其他界面没有关掉的逻辑或者后台逻辑)
- 可以先测试桌面状态下的静置耗电( 后台进程耗电) , 把后台进程优化一遍再优化前台进程;
- 确保某界面退出后, 该界面内启用的循环逻辑关掉;
- Timer、handler.Postdelayed、ScheduledFutureTask、JobService、Animation、AnimationDrawable等的开始结束要注意同步问题, 保证循环能停止;
- 实在没办法的情况下, 终极杀招: 分模块屏蔽功能、页面, 使用排除法来定位问题;
推荐阅读
- Android开发之Notification通知
- Android退出app,后台推送的服务也停止了,怎么可以做到不停止后台服务呢?
- [Android Pro]判断Uri对应的ContentProvider所操作的数据库u存在,及DownloadManager的暂停,继续
- Android测试第二节Monkey工具
- android SystemServer.java启动的服务。
- Android-LogCat日志工具
- Android Runtime
- ANDROID STUDIO系列教程二--基本设置与运行
- 我的Android第二课