http://kongqingyun123.blog.163.com/blog/static/6377283520126974730476/
Emmagee工具已开源:https://github.com/NetEase/Emmagee
大家使用过程中有问题欢迎在github中给我们反馈,后续我们会持续跟进。
Emmagee主要实现了监控CPU、内存、流量、以及浮窗实时显示这些数据的功能,具体的功能实现细节以及参考学习的资料如下。
选择并且启动需要监控的应用
参考资料:http://www.cnblogs.com/feng88724/archive/2011/02/21/1961222.html
思路:先找出所有已安装的非系统的应用程序,使用ListView显示,已启动或者已有服务运行的程序显示图标,方便区分
重要的类:ActivityManager,PackageManager
重要代码:
1.获取所有安装的程序(包括系统的程序):PackageManager类下的getInstalledApplications方法
2.获取正在运行的应用程序:ActivityManager下的getRunningAppProcesses方法,与1比较将正在运行的程序的图标显示出来
3.过滤掉系统的程序和程序自身:
if (((appinfo.flags & ApplicationInfo.FLAG_SYSTEM) > 0)|| (appinfo.processName.equals("com.netease.qa.ptt"))) {
continue;
}
4.继承于baseAdapter的ListAdapter(自己写)来输出ListView并显示所有安装的非系统程序
重点:getView(int position, View convertView, ViewGroup parent)方法,里面是ListView的显示
5.getPackageManager.getLaunchIntentForPackage(packageName),返回一个intent,这个intent用来启动这个packageName包中的一个activity的主要口(front-
door),该方法通过获得packageName启动选中的应用程序
6.保证RadioButton按钮在ListView中实现单选功能:
public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {
if (isChecked) {
hasChecked = true;
if (temp != -1) {
RadioButton tempButton = (RadioButton) findViewById(temp);
if (tempButton != null) {
tempButton.setChecked(false);
}
}
if (temp == position) {
holder.rb.setChecked(true);
}
监控应用CPU
参考链接: http://www.blogjava.net/fjzag/articles/317773.html
数据全部都是jiffies为单位的,jiffies是内核中的一个全局变量,用来记录自系统启动一来产生的节拍数,在Linux中,一个节拍大致可理解为操作
系统进程调度的最小时间片,不同linux内核可能值有不同,通常在1ms到10ms之间)
重要的类:RandomAccessFile,BufferWriter,OutputStreamWriter,FileOutputStream
主要代码:RandomAccessFile(File_name, "r");
1.总体CPU监控
原理:由于Android系统是基于Linux内核的,所以系统文件的结构和Linux下一样,系统总体CPU使用信息是放在/proc/stat/文件下,/proc/cpuinfo文件下是
存放CPU的其他信息,包括CPU名称,直接读取即可
![Android性能测试工具实现介绍 - kevinkong - 风之云的足迹](http://img4.ph.126.net/a5TCmhwEZF2dQRw8lYbxjQ==/3075677070535072934.jpg)
user (480826) 从系统启动开始累计到当前时刻,处于用户态的运行时间,不包含 nice值为负进程。
nice (6665) 从系统启动开始累计到当前时刻,nice值为负的进程所占用的CPU时间
system (236914) 从系统启动开始累计到当前时刻,处于核心态的运行时间
idle (7212750) 从系统启动开始累计到当前时刻,除IO等待时间以外的其它等待时间
iowait (211630) 从系统启动开始累计到当前时刻,IO等待时间
irq (39) 从系统启动开始累计到当前时刻,硬中断时间
softirq (1876) 从系统启动开始累计到当前时刻,软中断时间
注意:其中cpu和480003中间有两个空格的,如果用split("")分割则会有一个空字符串
其中toks数组中存放第一行字符串用空格分隔后的字符串
总CPU时间:totalCputime=Long.parseLong(toks[2]) + Long.parseLong(toks[3])+ Long.parseLong(toks[4]) + Long.parseLong(toks[6])
+ Long.parseLong(toks[5]) + Long.parseLong(toks[7])+ Long.parseLong(toks[8])
CPU空闲时间:idle=Long.parseLong(toks[5])
2.单个程序CPU监控
原理:将选中的RadioButton对应程序的PID传入,读取/proc/PID/stat文件信息即可获得该PID对应程序的CPU信息
![Android性能测试工具实现介绍 - kevinkong - 风之云的足迹](http://img8.ph.126.net/5XjHKRBJEO1-svJEcBV6bw==/6597181916842339348.jpg)
PID=15916 程序PID
PackageName=<d.process.acore> 程序包名
utime=1026 该任务在用户态运行的时间
stime=2687 该任务在核心态运行的时间
cutime=0 所有已死线程在用户态运行的时间
cstime=0 所有已死在核心态运行的时间
tok数组中存放该文件中的信息用空格分隔后的字符串
单个程序CPU使用率:threadCpuTime=Long.parseLong(tok[13]) + Long.parseLong(tok[14]) + Long.parseLong(tok[15]) +
Long.parseLong(tok[16])
3.计算方法:
设定一个时间差,比如5s,取出六个值totalCputime1,totalCputime2,idle1,idle2,processCpuTime2,processCpuTime1,其中计算公式如下:
CPU总使用率(%) = 100*((totalCputime2- totalCputime1)-(idle2-idle1))/(totalCputime2-totalCputime1)
单个程序的CPU使用率(%) = 100*(processCpuTime2-processCpuTime1)/(totalCpuTime2-totalCpuTime1)
监控应用消耗流量
重要的类:TrafficStats,RandomAccessFile
首先要获取选中程序的UID,流量文件和API都是需要用到
UID:每个程序只要安装后都会存在一个UID,未运行的也存在,
(1)方法一:直接使用TrafficStats类中的方法获取: (只在Android2.2以及以上版本中在存在此API)
总接受流量TrafficStats.getTotalRxBytes()
总发送流量TrafficStats.getTotalTxBytes())
不包含WIFI的手机GPRS接收量TrafficStats.getMobileRxBytes())
不包含Wifi的手机GPRS发送量TrafficStats.getMobileTxBytes())
某一个进程的总接收量TrafficStats.getUidRxBytes(Uid))
某一个进程的总发送量TrafficStats.getUidTxBytes(Uid))
注意:这些都是从一次开机到一次关机的统计量,所以,做某一个程序的流量统计的时候,一定要注意开关机,和本次开机后是第几次启动本程序。
(2)方法二:同样的,系统自带的也有文件存放整体的流量和针对单个程序的流量统计
/proc/net/dev和/proc/uid_stat/UID下面有tcp_rcv和tcp_snd文件分别存放下行流量和上行流量
监控内存实现原理
参考资料:http://blog.csdn.net/qinjuning/article/details/6978560
http://blog.csdn.net/kieven2008/article/details/6445421
实现原理:
1、获取当前被测应用占用的内存
首先获取到当前被测应用的PID(进程id),然后按照pid调用android的API获取当前被测应用占用的内存。
//生成 ActivityManager 对象
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); // 获得该进程占用的内存
int[] myMempid = new int[]? ?( ?pid );
// 此MemoryInfo位于android.os.Debug.MemoryInfo包中,用来统计进程的内存信息
Debug.MemoryInfo[] memoryInfo = am.getProcessMemoryInfo(myMempid);
// 获取进程占内存用信息 kb单位
memoryInfo[0].getTotalSharedDirty();
//这里使用getTotalPss返回的消耗内存值和其它相应软件做对比是最接近
int memSize = memoryInfo[0].getTotalPss();
关于VSS、RSS、PSS、USS介绍
VSS - Virtual Set Size 虚拟耗用内存(包含共享库占用的内存)
? RSS - Resident Set Size 实际使用物理内存(包含共享库占用的内存)
? PSS - Proportional Set Size 实际使用的物理内存(比例分配共享库占用的内存)
? USS - Unique Set Size 进程独自占用的物理内存(不包含共享库占用的内存)
一般来说内存占用大小有如下规律:VSS >= RSS >= PSS >= USS
2、获取当前设备剩余内存
ActivityManager.MemoryInfo outInfo = new ActivityManager.MemoryInfo();
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
am.getMemoryInfo(outInfo);
long avaliMem = outInfo.availMem;
long avaliKbMem = avaliMem/1024; //转换成KB
3、获取当前设备的内存总数
“/proc/meminfo”文件记录了android手机的一些内存信息,在命令行窗口里输入”adb shell”,进入shell环境,输入”cat /proc/meminfo”即可在命令行
里显示meminfo文件的内容。cat /proc/meminfo
MemTotal: 94096 kB
MemFree: 1684 kB
Buffers: 16 kB
只需要读取这个文件就可以,获取到的MemTotal的值就是内存的总数