Android系统CPU使用率获取(附java代码)
2017-03-18 20:02
781 查看
若想直接看有效方法,请阅读方法二,第一条。
最近因为一个需求,需要记录下当前的CPU使用率,在翻遍了API后,发现系统并没有给予一个方法,能够简单的获取相关CPU信息,没办法,只能自己写一个了。
在网上查阅了相关方法后,获取CPU使用率主要有两种方法。一个是利用adb top命令;另一个就是读取/proc/stat文件,然后解析相关参数,自己去计算。
方法一、解析top命令结果
这是执行adb shell top命令后的结果。
![](https://oscdn.geek-share.com/Uploads/Images/Content/202006/10/fcbbe9d0cd9da365f2e9d0bdc3627e58)
从图中可知,top命令的执行结果显示,在第一个非空白行上有各部分的CPU占用率,我们只要稍微整理下就行。
先上代码:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202006/10/9c038c97cb0b14bb30e937eb9bd482ef)
然而得到的结果显然不对,以下是从输入流中打印出来的命令执行结果:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202006/10/ded4ec0df73a21f0ccf2aa7d511cf6cc)
显然,系统对于这个top命令动态的进行了修改,防止信息被App获取。正确的执行权限只留给了adbshell。
至此,此方法失效。
方法二、解析/proc/stat文件
/proc/stat文件动态记录所有CPU活动的信息,该文件中的所有值都是从系统启动开始累计到当前时刻。所以,计算系统当前的CPU占用率的方法就是,计算在间隔较短(ms级)的时间内,cpu的各活动信息的变化量,作为当前的实时CPU占用率。
下图是执行shell命令,获取文件的内容。
![](https://oscdn.geek-share.com/Uploads/Images/Content/202006/10/24e792d3d1351cde2b236a99ef6232fc)
其中,以CPU开头的两行表示的信息就是,当前该CPI的一个总的使用情况,后面各个数值的单位为jiffies,可以简单理解为Linux中操作系统进程调度的最小时间片。具体含义如下(以CPU0为例):
user(181596)从系统启动开始累计到当前时刻,处于用户态的运行时间,不包含 nice值为负进程。;
nice(85733)从系统启动开始累计到当前时刻,nice值为负的进程所占用的CPU时间;
system (197165)从系统启动开始累计到当前时刻,处于核心态的运行时间;
idle (1328127)从系统启动开始累计到当前时刻,除IO等待时间以外的其它等待时间;
iowait(11679)从系统启动开始累计到当前时刻,IO等待时间;
irq (5)从系统启动开始累计到当前时刻,硬中断时间;
softirq (5138)从系统启动开始累计到当前时刻,软中断时间。
这里,我们只需关心“idle”,它表示了系统的空闲时间,以及各项数值之和就是CPU的总消耗。
因此,我们以totalJiffies1表示第一次CPU总消耗,totalIdle1表示第一次的CPU空闲时间,同理,totalJiffies2、totalIdle2表示第二次的相关信息,则cpu的占用率如下:
double cpuRate=1.0*((totalIdle2-totalJiffies2)-(totalIdle1-totalJiffies1))/( totalIdle2- totalIdle1);
以下是根据这个思想实现的代码:
思考:上述方法中,为了获取两次CPU信息,强制线程休眠了50ms,若实际文件内容的修改要比这个时间多怎么办?这样两次读取的信息就相同了;如果少于50ms,则白等了这么久。因此引入了FileObserve,当文件被修改时,系统回调相应的方法通知我们去读取新的内容,这样就可以避免上述问题。
方法很简单,就不全贴了,就附上变化的部分:
1、继承FileObserver类,并实现onEvent(int event, String path)方法,在执行该类的startWatching()方法后,系统会回调onEvent方法,告知该文件发生变化的情况,当判定为文件被修改时,就唤醒读取文件的线程,继续工作。
![](https://oscdn.geek-share.com/Uploads/Images/Content/202006/10/e7e1409b0ff9878c7dae85c56a5a9d64)
2、当第一次读取到文件输入流后,启动文件监听。
![](https://oscdn.geek-share.com/Uploads/Images/Content/202006/10/ab33b358eb7904587a19005b0f6419cd)
3、当第一次读取解析文件结束后,不再是执行sleep方法,而是执行wait方法,等待接收到系统的回调。
![](https://oscdn.geek-share.com/Uploads/Images/Content/202006/10/35f0bc69e323c19e8a643ea93759c3e1)
结果:第二次文件读取一直未进行。
通过日志发现,接收到的文件变化事件只有三类:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202006/10/d1221ebd415d862d9381b9d7116f4fd1)
即:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202006/10/8cfdac6c02556d9dd6c5077d9f062a5f)
即,文件只发生过访问数据、打开文件、关闭文件这三种操作。
这明显不可能,文件的内容一直在动态变化着!
通过上网查找资料发现:/proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间。它以文件系统的方式为内核与进程提供通信的接口。用户和应用程序可以通过/proc得到系统的信息,并可以改变内核的某些参数。由于系统的信息,如进程,是动态改变的,所以用户或应用程序读取/proc目录中的文件时,proc文件系统是动态从系统内核读出所需信息并提交的。
也就是说,这是一个特殊的文件,是收不到文件修改事件的,想通过文件观察对象进行监督文件的修改情况的方法也就失效了。
总结:获取CPU使用率信息,目前相对最可靠的方式就是两次获取并/proc/stat文件内容,然后计算。
最近因为一个需求,需要记录下当前的CPU使用率,在翻遍了API后,发现系统并没有给予一个方法,能够简单的获取相关CPU信息,没办法,只能自己写一个了。
在网上查阅了相关方法后,获取CPU使用率主要有两种方法。一个是利用adb top命令;另一个就是读取/proc/stat文件,然后解析相关参数,自己去计算。
方法一、解析top命令结果
这是执行adb shell top命令后的结果。
从图中可知,top命令的执行结果显示,在第一个非空白行上有各部分的CPU占用率,我们只要稍微整理下就行。
先上代码:
然而得到的结果显然不对,以下是从输入流中打印出来的命令执行结果:
显然,系统对于这个top命令动态的进行了修改,防止信息被App获取。正确的执行权限只留给了adbshell。
至此,此方法失效。
方法二、解析/proc/stat文件
/proc/stat文件动态记录所有CPU活动的信息,该文件中的所有值都是从系统启动开始累计到当前时刻。所以,计算系统当前的CPU占用率的方法就是,计算在间隔较短(ms级)的时间内,cpu的各活动信息的变化量,作为当前的实时CPU占用率。
下图是执行shell命令,获取文件的内容。
其中,以CPU开头的两行表示的信息就是,当前该CPI的一个总的使用情况,后面各个数值的单位为jiffies,可以简单理解为Linux中操作系统进程调度的最小时间片。具体含义如下(以CPU0为例):
user(181596)从系统启动开始累计到当前时刻,处于用户态的运行时间,不包含 nice值为负进程。;
nice(85733)从系统启动开始累计到当前时刻,nice值为负的进程所占用的CPU时间;
system (197165)从系统启动开始累计到当前时刻,处于核心态的运行时间;
idle (1328127)从系统启动开始累计到当前时刻,除IO等待时间以外的其它等待时间;
iowait(11679)从系统启动开始累计到当前时刻,IO等待时间;
irq (5)从系统启动开始累计到当前时刻,硬中断时间;
softirq (5138)从系统启动开始累计到当前时刻,软中断时间。
这里,我们只需关心“idle”,它表示了系统的空闲时间,以及各项数值之和就是CPU的总消耗。
因此,我们以totalJiffies1表示第一次CPU总消耗,totalIdle1表示第一次的CPU空闲时间,同理,totalJiffies2、totalIdle2表示第二次的相关信息,则cpu的占用率如下:
double cpuRate=1.0*((totalIdle2-totalJiffies2)-(totalIdle1-totalJiffies1))/( totalIdle2- totalIdle1);
以下是根据这个思想实现的代码:
/**获取当前CPU占比 * 在实际测试中发现,有的手机会隐藏CPU状态,不会完全显示所有CPU信息,例如MX5,所有建议只做参考 * @return */ public static String getCPURateDesc(){ String path = "/proc/stat";// 系统CPU信息文件 long totalJiffies[]=new long[2]; long totalIdle[]=new long[2]; int firstCPUNum=0;//设置这个参数,这要是防止两次读取文件获知的CPU数量不同,导致不能计算。这里统一以第一次的CPU数量为基准 FileReader fileReader = null; BufferedReader bufferedReader = null; Pattern pattern=Pattern.compile(" [0-9]+"); for(int i=0;i<2;i++) { totalJiffies[i]=0; totalIdle[i]=0; try { fileReader = new FileReader(path); bufferedReader = new BufferedReader(fileReader, 8192); int currentCPUNum=0; String str; while ((str = bufferedReader.readLine()) != null&&(i==0||currentCPUNum<firstCPUNum)) { if (str.toLowerCase().startsWith("cpu")) { currentCPUNum++; int index = 0; Matcher matcher = pattern.matcher(str); while (matcher.find()) { try { long tempJiffies = Long.parseLong(matcher.group(0).trim()); totalJiffies[i] += tempJiffies; if (index == 3) {//空闲时间为该行第4条栏目 totalIdle[i] += tempJiffies; } index++; } catch (NumberFormatException e) { e.printStackTrace(); } } } if(i==0){ firstCPUNum=currentCPUNum; try {//暂停50毫秒,等待系统更新信息。 Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { if (bufferedReader != null) { try { bufferedReader.close(); } catch (IOException e) { e.printStackTrace(); } } } } double rate=-1; if (totalJiffies[0]>0&&totalJiffies[1]>0&&totalJiffies[0]!=totalJiffies[1]){ rate=1.0*((totalJiffies[1]-totalIdle[1])-(totalJiffies[0]-totalIdle[0]))/(totalJiffies[1]-totalJiffies[0]); } return String.format("cpu:%.2f",rate); }
思考:上述方法中,为了获取两次CPU信息,强制线程休眠了50ms,若实际文件内容的修改要比这个时间多怎么办?这样两次读取的信息就相同了;如果少于50ms,则白等了这么久。因此引入了FileObserve,当文件被修改时,系统回调相应的方法通知我们去读取新的内容,这样就可以避免上述问题。
方法很简单,就不全贴了,就附上变化的部分:
1、继承FileObserver类,并实现onEvent(int event, String path)方法,在执行该类的startWatching()方法后,系统会回调onEvent方法,告知该文件发生变化的情况,当判定为文件被修改时,就唤醒读取文件的线程,继续工作。
2、当第一次读取到文件输入流后,启动文件监听。
3、当第一次读取解析文件结束后,不再是执行sleep方法,而是执行wait方法,等待接收到系统的回调。
结果:第二次文件读取一直未进行。
通过日志发现,接收到的文件变化事件只有三类:
即:
即,文件只发生过访问数据、打开文件、关闭文件这三种操作。
这明显不可能,文件的内容一直在动态变化着!
通过上网查找资料发现:/proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间。它以文件系统的方式为内核与进程提供通信的接口。用户和应用程序可以通过/proc得到系统的信息,并可以改变内核的某些参数。由于系统的信息,如进程,是动态改变的,所以用户或应用程序读取/proc目录中的文件时,proc文件系统是动态从系统内核读出所需信息并提交的。
也就是说,这是一个特殊的文件,是收不到文件修改事件的,想通过文件观察对象进行监督文件的修改情况的方法也就失效了。
总结:获取CPU使用率信息,目前相对最可靠的方式就是两次获取并/proc/stat文件内容,然后计算。
相关文章推荐
- Android系统CPU使用率获取(附java代码)%25
- Android开发之java代码中获取当前系统的时间工具类
- [置顶] Android开发之java代码中获取当前系统的时间工具类
- Android开发之java代码中获取当前系统的时间工具类
- 使用Java代码在应用层获取Android系统属性
- java获取http:图片下载代码——android基础编
- 【java代码获取系统时间和执行定时任务】
- android 系统重启与关机:java 代码实现
- android 系统重启与关机:java 代码实现
- [小代码]获取Android系统的唯一识别码
- 【java代码获取系统时间和执行定时任务】
- Android中用Java代码模拟鼠标指针(可显示于整个系统界面之上)
- Java代码获取所有系统属性
- Android各代码层获取系统时间的方法
- Android 系统的名字 及 版本和api基本对应关系 及 代码获取
- java代码获取系统时间和执行定时任务
- Android APK反编译方法(可以获取APK xml和android Manifest,java代码等内容)
- 获取系统时间java代码
- [代码]Android编程获取手机型号,本机电话号码等系统信息
- android 系统重启与关机:java 代码实现