前言:
前面文章介绍了,Android客户端性能:内存、流量、CPU、启动时间的介绍和如何通过adb shell的查取。
详见链接:
这样感觉是不是很不方便?每次想查取都要通过cmd进去敲命令查看,并且要一条条寻找定位。虽然能获取的数据全面,但每次只能读取一次数据。有时只想看某项性能的某个数据,这样我就思考编写java代码同样通过adb shell方式自动同时获取 内存、流量、CPU多次的数据,并将获取到的数据存入Excel表中,保存并方便阅读。
一、了解如何获取客户端性能数据(预备知识)
1、先预备学习上面链接的三篇文章,了解一些性能指标获取的原理
2、本文编写获取方式就是基于adb shell,然后通过字符串截取期望数据。
获取的命令行:
PID : "adb shell pgrep -o " + PackageName
内存:"adb shell dumpsys meminfo " + PackageName
流量:"adb shell cat /proc/" + Pid+ "/net/dev"
CPU:"adb shell dumpsys cpuinfo |grep + PackageName
二、代码获取各项客户端性能
因为Runtime.getRuntime().exec方法可以调用cmd命令
1)先Runtime runtime = Runtime.getRuntime();获取一个Runtime类对象 runtime,用来与运行环境相连接。
2)再Process proc = runtime.exec("adb shell pgrep -o " + PackageName);通过.exec在单独的进程中执行指定的字符串命令,得到一个进程对象proc。
3)再BufferedReader in = new BufferedReader(new InputStreamReader( proc.getInputStream()));获取字符流in,BufferedReader是字符流,InputStream()是字节流,该步就是 获取字节流 然后 通过转换流InputStreamReader 将字节流转换成字符流。
4)再stringBuffer.append(in.readLine() + " ");将 字符流 一行一行读取转换成 字符串变量 stringBuffer。
5)String str1 = stringBuffer.toString();转换为 字符串常量,.trim()去两端的空格。
1、获取PID:
前五步奏后,"adb shell pgrep -o " + PackageName获取的直接仅是PID。所以不需截取,就是PID。
代码:
// 获取进程的pid
private String PID(String PackageName) {
Process proc = null;
String str3 = null;
try {
Runtime runtime = Runtime.getRuntime();
// proc = runtime.exec("adb shell ps |grep -w " + PackageName);
proc = runtime.exec("adb shell pgrep -o " + PackageName);
if (proc.waitFor() != 0) {
System.err.println("exit value = " + proc.exitValue());
}
BufferedReader in = new BufferedReader(new InputStreamReader(
proc.getInputStream()));
StringBuffer stringBuffer = new StringBuffer();
String line = null;
while ((line = in.readLine()) != null) {
stringBuffer.append(line + " ");
}
String str1 = stringBuffer.toString();
// System.out.println(str1);
// String str2 = str1.substring(str1.indexOf(" " + PackageName) -
// 50, str1.indexOf(" " + PackageName));
// System.out.println(str2);
// String PID = str2.substring(0, 5);
String PID = str1;
PID = PID.trim();
str3 = PID;
} catch (Exception e) {
System.err.println(e);
} finally {
try {
proc.destroy();
} catch (Exception e2) {
}
}
return str3;
}
2、获取流量:
前5步获取字符串后,通过关键词:wlan0:。str1.substring(str1.indexOf("wlan0:"), str1.indexOf("wlan0:") + 90);截取期待值。注:流量包含“上传流量”和“下载流量”分别获取后需相加。
代码:
// 获取程序消耗的流量=上传流量+下载流量
public double getFlow(String PackageName) {
double flow = 0;
try {
String Pid = PID(PackageName);
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec("adb shell cat /proc/" + Pid
+ "/net/dev");
try {
if (proc.waitFor() != 0) {
System.err.println("exit value = " + proc.exitValue());
}
BufferedReader in = new BufferedReader(new InputStreamReader(
proc.getInputStream()));
StringBuffer stringBuffer = new StringBuffer();
String line = null;
while ((line = in.readLine()) != null) {
stringBuffer.append(line + " ");
}
String str1 = stringBuffer.toString();
String str2 = str1.substring(str1.indexOf("wlan0:"),
str1.indexOf("wlan0:") + 90);
String str4 = str2.substring(7, 16);
str4 = str4.trim();
String str6 = str2.substring(67, 75);
str6 = str6.trim();
int b = Integer.parseInt(str4);
int a = Integer.parseInt(str6);
double sendFlow = a / 1024;
double revFlow = b / 1024;
flow = sendFlow + revFlow;
} catch (InterruptedException e) {
System.err.println(e);
} finally {
try {
proc.destroy();
} catch (Exception e2) {
}
}
} catch (Exception StringIndexOutOfBoundsException) {
System.out.println("\n流量——请检查设备是否连接");
}
return flow;
}
3、获取内存:
原理同前
代码:
// 获取程序内存的消耗情况
public double getMemory(String PackageName) {
double Heap = 0;
try {
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec("adb shell dumpsys meminfo "
+ PackageName);
try {
if (proc.waitFor() != 0) {
System.err.println("exit value = " + proc.exitValue());
}
BufferedReader in = new BufferedReader(new InputStreamReader(
proc.getInputStream()));
StringBuffer stringBuffer = new StringBuffer();
String line = null;
while ((line = in.readLine()) != null) {
stringBuffer.append(line + " ");
}
String str1 = stringBuffer.toString();
String str2 = str1.substring(str1.indexOf("TOTAL SWAP (KB):"),
str1.indexOf("TOTAL SWAP (KB):") + 30);
String str3 = str2.substring(20, 30);
str3 = str3.trim();
Heap = Double.parseDouble(str3) / 1024;
DecimalFormat df = new DecimalFormat("#.000");
String memory = df.format(Heap);
Heap = Double.parseDouble(memory);
} catch (InterruptedException e) {
System.err.println(e);
} finally {
try {
proc.destroy();
} catch (Exception e2) {
}
}
}
catch (Exception StringIndexOutOfBoundsException) {
System.out.print("\n 内存——请检查设备是否连接");
}
return Heap;
}
4、获取CPU
原理同前
代码:
// 获取程序的cpu占用情况
public double getCPU(String PackageName) {
double Cpu = 0;
try {
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec("adb shell dumpsys cpuinfo |grep "
+ PackageName);
// System.out.println(proc);
try {
if (proc.waitFor() != 0) {
System.err.println("exit value = " + proc.exitValue());
}
BufferedReader in = new BufferedReader(new InputStreamReader(
proc.getInputStream()));
StringBuffer stringBuffer = new StringBuffer();
String line = null;
while ((line = in.readLine()) != null) {
stringBuffer.append(line + " ");
}
String str1 = stringBuffer.toString();
// System.out.println(str1);
// String str3 = str1.substring(str1.indexOf(PackageName) - 43,
// str1.indexOf(PackageName)).trim();
// System.out.println(str1);
String cpu = str1.substring(0, str1.indexOf("%"));
cpu = cpu.trim();
Cpu = Double.parseDouble(cpu);
} catch (InterruptedException e) {
System.err.println(e);
} finally {
try {
proc.destroy();
} catch (Exception e2) {
}
}
} catch (Exception StringIndexOutOfBoundsException) {
System.out.println("\n CPU——请检查设备是否连接");
}
return Cpu;
}
三、写入EXCEL表
1、创建sheet
/**
* 创建sheet
*
* @param title
* sheet的名字
* @param headers
* 表头
* @param dataList
* 正文单元格
*/
private void createSheet(String title, String[] headers,
String[][] dataList, HSSFWorkbook workBook) {
HSSFSheet sheet = workBook.createSheet(title);
// 设置表头和普通单元格的格式
HSSFCellStyle headStyle = setHeaderStyle(workBook);
HSSFCellStyle bodyStyle = setBodyStyle(workBook);
createBody(dataList, sheet, bodyStyle);
createHeader(headers, sheet, headStyle);
}
2、创建表头
/**
* 创建表头
*
* @param headers
* 表头
* @param sheet
* 表
* @param headStyle
* 表头格式
*/
private void createHeader(String[] headers, HSSFSheet sheet,
HSSFCellStyle headStyle) {
HSSFRow row = sheet.createRow(0); // 创建第一行,为表头
for (int i = 0; i < headers.length; i++) {
HSSFCell cell = row.createCell(i);// 这一行的每个列,即单元格
cell.setCellStyle(headStyle); // 设置每个单元格格式
HSSFRichTextString textString = new HSSFRichTextString(headers[i]);// 存放每个单元格的文本
cell.setCellValue(textString); // 放进单元格
sheet.autoSizeColumn((short) i); // 自动设置列的大小
}
}
3、创建正文单元格
/**
* 创建正文单元格
*
* @param dataList
* 数据数组
* @param sheet
* 表
* @param bodyStyle
* 单元格格式
*/
private void createBody(String[][] dataList, HSSFSheet sheet,
HSSFCellStyle bodyStyle) {
for (int a = 0; a < dataList.length; a++) {
HSSFRow row = sheet.createRow(a + 1); // 根据数据条目创建行数
for (int j = 0; j < dataList[a].length; j++) {
HSSFCell cell = row.createCell(j); // 这一行的每个列,即单元格
cell.setCellStyle(bodyStyle); // 设置每个单元格格式
HSSFRichTextString textString = new HSSFRichTextString(
dataList[a][j]);// 存放每个单元格的文本
cell.setCellValue(textString); // 放进单元格
}
}
}
4、设置表头格式
/**
* 设置表头格式
*
* @param workBook
* @return
*/
private HSSFCellStyle setHeaderStyle(HSSFWorkbook workBook) {
HSSFCellStyle style = workBook.createCellStyle(); // 创建表头每个单元格格式
style.setFillForegroundColor(HSSFColor.LIGHT_YELLOW.index);
HSSFFont font = workBook.createFont();
font.setFontName("微软雅黑");
font.setFontHeightInPoints((short) 12);
style.setFont(font);
return style;
}
5、设置正文单元格格式
/**
* 设置正文单元格格式
*
* @param workBook
* @return
*/
private HSSFCellStyle setBodyStyle(HSSFWorkbook workBook) {
HSSFCellStyle style2 = workBook.createCellStyle(); // 创建正文每个单元格格式
style2.setFillForegroundColor(HSSFColor.WHITE.index);
HSSFFont font2 = workBook.createFont();
font2.setFontName("微软雅黑");
style2.setFont(font2);
return style2;
}
四、获取多次数据,隔两秒抓取一次
public static void main(String[] args) {
packagename=com.hundsun.stockwinner.dfzq;
System.out.println("开始运行...");
String pid =PID(packagename);
System.out.println("证券的pid:" + pid );
ArrayList<String> list = new ArrayList<String>();
ArrayList<ArrayList<String>> lists = new ArrayList<ArrayList<String>>();
String[][] array = new String[10][3];
for (int i = 1; i < 11; i++) {
array[i - 1][0] = Double.toString(getMemory(packagename));
array[i - 1][1] = Double.toString(getCPU(packagename));
array[i - 1][2] = Double.toString(getFlow(packagename));
list.add(array[i - 1][0]);
list.add(array[i - 1][1]);
list.add(array[i - 1][2]);
lists.add(list);
System.out.println("证券性能" + i + ": " + list);
list.clear();
try {
Thread.sleep(2000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
System.out.println("运行结束");
try {
OutputStream os = new FileOutputStream("D:/java_workspace"
+ "/手机客户端性能测试表.xls");
String[] headers = { "内存", "CPU", "流量" };
exporteExcel("性能表", headers, array, os);
os.close();
System.out.println("写入成功");
} catch (FileNotFoundException e1) {
System.out.println("无法找到文件");
} catch (IOException e1) {
System.out.println("写入文件失败");
}
}
五、运行结果: