如何测试Android APP的ios app耗电量测试

【Android】如何测试Android APP的耗电量?_科技_易房网
如何测试Android APP的耗电量?
作者:admin
图中软件叫啥名称,谢谢! 易房网小编为您精选了网友的解决办法,供您参考 ----------------------------------------------------- 网友回答: http://ww
图中软件叫啥名称,谢谢!易房网小编为您精选了网友的解决办法,供您参考-----------------------------------------------------网友回答:
易房网小编为您精选了网友的解决办法,供您参考-----------------------------------------------------网友回答:
你是没用过android吧所以的android都自带的功能设置---&电池/电源管理/
易房网小编为您精选了网友的解决办法,供您参考-----------------------------------------------------网友回答:
之前写了个文章,看下:深入浅出Android App耗电量统计
易房网小编为您精选了网友的解决办法,供您参考-----------------------------------------------------网友回答:
MIUI Android2.3 版本的电量显示
易房网小编为您精选了网友的解决办法,供您参考-----------------------------------------------------网友回答:
有两种方法:
1.通过软件。如MIUI,系统自带的电量消耗查看
2.通过硬件来辅助测试,2比1要精确
易房网小编为您精选了网友的解决办法,供您参考-----------------------------------------------------网友回答:
这在开发中来说还是比较麻烦的,没有现成的API,要用一些非常规手段!
1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将
追究责任;3.作者投稿可能会经我们编辑修改或补充。
李克强:确保妇女享有与男子平等的土地权益
在路上2016:中国青年艺术家作品提名展暨青年批评
清洁西宁:360度无死角刷新颜值
林志玲晒健身照秀好身材 网友:还是18岁
居民报警揪出卖淫女 房间内大尺度激情爱爱呻吟声
【老外谈】印度学者:中国在互联网治理国际对话中
组图:蒋欣也要告别微胖界了?下巴尖了腿细了
谢杏芳聊天记录疑曝光 痛诉“十分痛苦”
友情链接、商务合作QQ:当前位置 & &
& Android手机耗电深度解析!
Android手机耗电深度解析!
01:11:29&&出处:&&作者:
编辑:雪花 &&)
让小伙伴们也看看:
阅读更多:
好文共享:
文章观点支持
当前平均分:0(0 次打分)
[04-04][04-04][04-04][04-04][04-04][04-04][04-04][04-04][04-04][04-04]
登录驱动之家
没有帐号?
用合作网站帐户直接登录2027人阅读
android学习总结(9)
& & 本文针对Android 5.0 以及以版本,对APP耗电量统计的核心函数,processAppUsage 进行解读,代码中增加了大量注释以及笔者个人的理解。
& &&private void processAppUsage(SparseArray&UserHandle& asUsers) {
final boolean forAllUsers = (asUsers.get(UserHandle.USER_ALL) != null);
SensorManager sensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
final int which = mStatsT
final int speedSteps = mPowerProfile.getNumSpeedSteps();
//获取CPU可以运转到在几种频率之下
final double[] powerCpuNormal = new double[speedSteps];
final long[] cpuSpeedStepTimes = new long[speedSteps];
* 根据几种不同的频率,获取每个频率的平均电流值
for (int p = 0; p & speedS p++) {
powerCpuNormal[p] = mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_ACTIVE, p);
final double mobilePowerPerPacket = getMobilePowerPerPacket();
//移动数据流量功耗
final double mobilePowerPerMs = getMobilePowerPerMs();
//数据连通网络时候的功耗
final double wifiPowerPerPacket = getWifiPowerPerPacket();
//Wifi传输功耗
long appWakelockTimeUs = 0;
BatterySipper osApp =
mStatsPeriod = mTypeBatteryR
* SparseArray代替HashMap,效率更高,SpareArray用的是稀疏矩阵的方式
SparseArray&? extends Uid& uidStats = mStats.getUidStats();
//获取每一个uid的数据
final int NU = uidStats.size();
for (int iu = 0; iu & NU; iu++) {
Uid u = uidStats.valueAt(iu);
double power = 0;
double highestDrain = 0;
String packageWithHighestDrain =
Map&String, ? extends BatteryStats.Uid.Proc& processStats = u.getProcessStats();
long cpuTime = 0;
long cpuFgTime = 0;
long wakelockTime = 0;
long gpsTime = 0;
if (processStats.size() & 0) {
// Process CPU time
for (Map.Entry&String, ? extends BatteryStats.Uid.Proc& ent
: processStats.entrySet()) {
Uid.Proc ps = ent.getValue();
* 分别获取该进程,执行User的代码、执行系统级别的代码,以及在前段运行的时间
final long userTime = ps.getUserTime(which);
final long systemTime = ps.getSystemTime(which);
final long foregroundTime = ps.getForegroundTime(which);
cpuFgTime += foregroundTime * 10;
// convert to millis,转化为毫秒
final long tmpCpuTime = (userTime + systemTime) * 10;
// convert to millis
int totalTimeAtSpeeds = 0;
* 根据CPU所可以运行的几种频率,得到每种不同的频率下的改进程所消耗的时间
for (int step = 0; step & speedS step++) {
cpuSpeedStepTimes[step] = ps.getTimeAtCpuSpeedStep(step, which);
totalTimeAtSpeeds += cpuSpeedStepTimes[step];
if (totalTimeAtSpeeds == 0) totalTimeAtSpeeds = 1;
* 计算出每个CPU频率所消耗的时间,占总消耗时间的百分比,为什么要计算百分比?
double processPower = 0;
for (int step = 0; step & speedS step++) {
double ratio = (double) cpuSpeedStepTimes[step] / totalTimeAtS
if (DEBUG && ratio != 0) Log.d(TAG, &UID & + u.getUid() + &: CPU step #&
+ step + & ratio=& + makemAh(ratio) + & power=&
+ makemAh(ratio*tmpCpuTime*powerCpuNormal[step] / (60*60*1000)));
processPower += ratio * tmpCpuTime * powerCpuNormal[step];
cpuTime += tmpCpuT
if (DEBUG && processPower != 0) {
Log.d(TAG, String.format(&process %s, cpu power=%s&,
ent.getKey(), makemAh(processPower / (60*60*1000))));
power += processP
//总电量消耗加上该uid进程的消耗
if (packageWithHighestDrain == null
|| packageWithHighestDrain.startsWith(&*&)) {
highestDrain = processP
packageWithHighestDrain = ent.getKey();
} else if (highestDrain & processPower
&& !ent.getKey().startsWith(&*&)) {
highestDrain = processP
packageWithHighestDrain = ent.getKey();
if (cpuFgTime & cpuTime) {
if (DEBUG && cpuFgTime & cpuTime + 10000) {
Log.d(TAG, &WARNING! Cputime is more than 10 seconds behind Foreground time&);
cpuTime = cpuFgT
// Statistics may not have been gathered yet.数据还没有聚合??
* //该进程CPU所消耗的时间统计结束
* 这里 60*60*1000 是将能量转化为 毫安时,得到的结果是 毫秒*毫安
power /= (60*60*1000);
* // Process wake lock usage
* 该进程所持有的Wakelock而消耗的电量,一个进程可能持有多个Wakelock
Map&String, ? extends BatteryStats.Uid.Wakelock& wakelockStats = u.getWakelockStats();
for (Map.Entry&String, ? extends BatteryStats.Uid.Wakelock& wakelockEntry
: wakelockStats.entrySet()) {
Uid.Wakelock wakelock = wakelockEntry.getValue();
// Only care about partial wake locks since full wake locks
// are canceled when the user turns the screen off.
* 这里只关心Patrial的Wakelock,因为 fullwakelock 在屏幕灭的时候 已经被取消
* 通过该循环,可以得到该进程所持有的所有Wakelock的时间
BatteryStats.Timer timer = wakelock.getWakeTime(BatteryStats.WAKE_TYPE_PARTIAL);
if (timer != null) {
wakelockTime += timer.getTotalTimeLocked(mRawRealtime, which);
appWakelockTimeUs += wakelockT
//得到的结果是微秒的形式
wakelockTime /= 1000;
// convert to millis,转化为毫秒
// Add cost of holding a wake lock
* 计算得到持有Wakelock所消耗的电量,电流值为CPU醒着时候的电流值
p = (wakelockTime
* mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_AWAKE)) / (60*60*1000);
if (DEBUG && p != 0) Log.d(TAG, &UID & + u.getUid() + &: wake &
+ wakelockTime + & power=& + makemAh(p));
// Add cost of mobile traffic
* 计算手机的数据流量,即使用 3G/4G 网络的流量数量
final long mobileRx = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, mStatsType);
final long mobileTx = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, mStatsType);
final long mobileRxB = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, mStatsType);
final long mobileTxB = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, mStatsType);
* 手机连通网络的时间
final long mobileActive = u.getMobileRadioActiveTime(mStatsType);
if (mobileActive & 0) {
// We are tracking when the radio is up, so can use the active time to
// determine power use.
* 当监控的时候,网络已经连通,所以可以直接用网络连通的时间,来确定功耗值
mAppMobileActive += mobileA
p = (mobilePowerPerMs * mobileActive) / 1000;
// We are not tracking when the radio is up, so must approximate power use
// based on the number of packets.
* 监控的时候,手机网络没有连通,那么就用流量值*流量电流 来估算出功耗
p = (mobileRx + mobileTx) * mobilePowerPerP
if (DEBUG && p != 0) Log.d(TAG, &UID & + u.getUid() + &: mobile packets &
+ (mobileRx+mobileTx) + & active time & + mobileActive
+ & power=& + makemAh(p));
// Add cost of wifi traffic
* WIFI的数据流量功耗,与计算手机数据流量的方式类似
final long wifiRx = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, mStatsType);
final long wifiTx = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, mStatsType);
final long wifiRxB = u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, mStatsType);
final long wifiTxB = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, mStatsType);
p = (wifiRx + wifiTx) * wifiPowerPerP
if (DEBUG && p != 0) Log.d(TAG, &UID & + u.getUid() + &: wifi packets &
+ (mobileRx+mobileTx) + & power=& + makemAh(p));
// Add cost of keeping WIFI running.
* WIFI打开时候的功耗,打开WIFI,WIFI并没有其他运作
long wifiRunningTimeMs = u.getWifiRunningTime(mRawRealtime, which) / 1000;
mAppWifiRunning += wifiRunningTimeMs;
p = (wifiRunningTimeMs
* mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_ON)) / (60*60*1000);
if (DEBUG && p != 0) Log.d(TAG, &UID & + u.getUid() + &: wifi running &
+ wifiRunningTimeMs + & power=& + makemAh(p));
// Add cost of WIFI scans
* WIFI扫描时候的功耗
long wifiScanTimeMs = u.getWifiScanTime(mRawRealtime, which) / 1000;
p = (wifiScanTimeMs
* mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_SCAN)) / (60*60*1000);
if (DEBUG) Log.d(TAG, &UID & + u.getUid() + &: wifi scan & + wifiScanTimeMs
+ & power=& + makemAh(p));
* WIFI 批量扫描模式所造成的功耗
for (int bin = 0; bin & BatteryStats.Uid.NUM_WIFI_BATCHED_SCAN_BINS; bin++) {
long batchScanTimeMs = u.getWifiBatchedScanTime(bin, mRawRealtime, which) / 1000;
p = ((batchScanTimeMs
* mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_BATCHED_SCAN, bin))
) / (60*60*1000);
if (DEBUG && p != 0) Log.d(TAG, &UID & + u.getUid() + &: wifi batched scan # & + bin
+ & time=& + batchScanTimeMs + & power=& + makemAh(p));
// Process Sensor usage
* 进程使用传感器造成的功耗
* 这里用SpareArray来存储
SparseArray&? extends BatteryStats.Uid.Sensor& sensorStats = u.getSensorStats();
int NSE = sensorStats.size();
for (int ise=0; ise&NSE; ise++) {
Uid.Sensor sensor = sensorStats.valueAt(ise);
//获取Sensor类型所对应的实体
int sensorHandle = sensorStats.keyAt(ise);
//获取Sensor的类型
* 该Sensor所消耗的时间
BatteryStats.Timer timer = sensor.getSensorTime();
long sensorTime = timer.getTotalTimeLocked(mRawRealtime, which) / 1000;
* 对GPS区别对待,貌似GPS的平均电流值,可以在PowerProfile中得到,而其他Sensor的平均
* 电流值,通过SensorManager获取,每个Sensor的型号功能不同,其电流值应该是做在驱动层
double multiplier = 0;
switch (sensorHandle) {
case Uid.Sensor.GPS:
multiplier = mPowerProfile.getAveragePower(PowerProfile.POWER_GPS_ON);
gpsTime = sensorT
List&Sensor& sensorList = sensorManager.getSensorList(
android.hardware.Sensor.TYPE_ALL);
for (android.hardware.Sensor s : sensorList) {
if (s.getHandle() == sensorHandle) {
multiplier = s.getPower();
p = (multiplier * sensorTime) / (60*60*1000);
if (DEBUG && p != 0) Log.d(TAG, &UID & + u.getUid() + &: sensor #& + sensorHandle
+ & time=& + sensorTime + & power=& + makemAh(p));
if (DEBUG && power != 0) Log.d(TAG, String.format(&UID %d: total power=%s&,
u.getUid(), makemAh(power)));
// Add the app to the list if it is consuming power
* 如果该应用消耗的电量,就把它增加到列表中
final int userId = UserHandle.getUserId(u.getUid());
if (power != 0 || u.getUid() == 0) {
BatterySipper app = new BatterySipper(BatterySipper.DrainType.APP, u,
new double[] {power});
app.cpuTime = cpuT
app.gpsTime = gpsT
app.wifiRunningTime = wifiRunningTimeMs;
app.cpuFgTime = cpuFgT
app.wakeLockTime = wakelockT
app.mobileRxPackets = mobileRx;
app.mobileTxPackets = mobileTx;
app.mobileActive = mobileActive / 1000;
app.mobileActiveCount = u.getMobileRadioActiveCount(mStatsType);
app.wifiRxPackets = wifiRx;
app.wifiTxPackets = wifiTx;
app.mobileRxBytes = mobileRxB;
app.mobileTxBytes = mobileTxB;
app.wifiRxBytes = wifiRxB;
app.wifiTxBytes = wifiTxB;
app.packageWithHighestDrain = packageWithHighestD
* 对 WIFI 支持进程 和 蓝牙服务进程 区别对待,加入相应的列表中
if (u.getUid() == Process.WIFI_UID) {
//wifi 支持进程
mWifiSippers.add(app);
mWifiPower +=
} else if (u.getUid() == Process.BLUETOOTH_UID) {
//蓝牙服务进程
mBluetoothSippers.add(app);
mBluetoothPower +=
* Android 5.0 以后是多用户系统,这里要对用户做一些判别操作
else if (!forAllUsers && asUsers.get(userId) == null
&& UserHandle.getAppId(u.getUid()) &= Process.FIRST_APPLICATION_UID) {
List&BatterySipper& list = mUserSippers.get(userId);
* 不同用户,拥有不同的app列表,要根据userId获取到应用列表,如果没有列表则新建,
* 然后在此用户下的应用列表中添加app
if (list == null) {
list = new ArrayList&BatterySipper&();
mUserSippers.put(userId, list);
list.add(app);
在对不同用户的所在的app消耗的功耗进行统计
if (power != 0) {
Double userPower = mUserPower.get(userId);
if (userPower == null) {
userPower =
userPower +=
mUserPower.put(userId, userPower);
* 不区分用户的情况,则直接相加
mUsageList.add(app);
if (power & mMaxPower) mMaxPower =
if (power & mMaxRealPower) mMaxRealPower =
mComputedPower +=
if (u.getUid() == 0) {
//Android 的系统 app
// The device has probably been awake for longer than the screen on
// time and application wake lock time would account for.
// this remainder to the OS, if possible.
* 设备在灭屏之后,可能也依旧处于唤醒状态,所以设备的实际唤醒时间要比屏幕亮着的总体时间要长
* 这个原因就是Wakelock引起的,笔者根据代码理解,应该是将释放Wakelock的时间归结为系统所消耗
* 的时间,这部分时间算在系统头上
if (osApp != null) {
long wakeTimeMillis = mBatteryUptime / 1000;
* wakeTimeMillis的值查阅源代码的 英文翻译过来是 当前电池正在运行的时间
* 电池所运行的时间,减去应用占据Wakelock的时间 再减去屏幕亮起的时间
* 剩下的时间,就是要额外计算的,就是不算app所持有的Wakelock时间,且发生在灭屏后的,那
* 应该就是 释放Wakelock 所消耗的时间,这里是笔者的推测
wakeTimeMillis -= (appWakelockTimeUs / 1000)
+ (mStats.getScreenOnTime(mRawRealtime, which) / 1000);
//如果存在这样的时间
if (wakeTimeMillis & 0) {
double power = (wakeTimeMillis
* mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_AWAKE))
(60*60*1000);
if (DEBUG) Log.d(TAG, &OS wakeLockTime & + wakeTimeMillis + & power &
+ makemAh(power));
* 补偿进去每一项的值
osApp.wakeLockTime += wakeTimeM
osApp.value +=
osApp.values[0] +=
* 更新最大消耗电量的值
if (osApp.value & mMaxPower) mMaxPower = osApp.
if (osApp.value & mMaxRealPower) mMaxRealPower = osApp.
mComputedPower +=
//总消耗值
& & 比Android4.4 相比起来,耗电统计精细了一点,两者的大致流程一样,主要是通过得到每个app占据CPU的时间(CPU分为不同的频率,不同频率的时间也要计算出来)、Wakelock的时间、数据流量的时间、WIFI的时间(包括WIFI的打开,工作,扫描,批量扫描几种不同的时间)以及各个传感器(GPS、光线,三轴加速,陀螺仪等)所消耗的时间,根据PowerProfile中已经存储的已知电流值,计算出其消耗的电量,并将单位转换为毫安时(mAh)
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:252916次
积分:3485
积分:3485
排名:第7197名
原创:73篇
转载:10篇
评论:228条
(1)(1)(2)(4)(1)(1)(1)(2)(3)(1)(3)(1)(1)(3)(3)(7)(13)(2)(2)(3)(1)(2)(3)(5)(3)(1)(1)(2)(4)(1)(5)

我要回帖

更多关于 android app耗电量 的文章

 

随机推荐