安卓性能监控(APM)之CPU使用率监控
2020-06-06 本文已影响0人
蓝不蓝编程
目标
监控app的CPU使用率.
方案
- 对于8.0以上版本,执行top命令,从结果里直接提取出当前app占用CPU比例.
- 对于8.0以下版本,通过读取“/proc/stat”和“/proc/App进程ID/stat”两个文件,计算出app进程占用的CPU比例.
- 完整代码:
package com.mb.roamdriver.myapm.cpu
import android.os.Build
import android.text.TextUtils
import java.io.BufferedReader
import java.io.IOException
import java.io.InputStreamReader
import java.io.RandomAccessFile
object CpuUtil {
private var mProcStatFile: RandomAccessFile? = null
private var mAppStatFile: RandomAccessFile? = null
private var mLastCpuTime: Long? = null
private var mLastAppCpuTime: Long? = null
/**
* 获取cpu使用率
*/
fun getCpuUsage(): Float {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
getCpuUsageForHigherVersion()
} else {
getCpuUsageForLowerVersion()
}
}
/**
* 安卓8.0以上版本获取cpu使用率
*/
private fun getCpuUsageForHigherVersion(): Float {
var process: Process? = null
try {
process = Runtime.getRuntime().exec("top -n 1")
val reader = BufferedReader(InputStreamReader(process.inputStream))
var line: String
var cpuIndex = -1
while (reader.readLine().also { line = it } != null) {
line = line.trim { it <= ' ' }
if (TextUtils.isEmpty(line)) {
continue
}
val tempIndex = getCPUIndex(line)
if (tempIndex != -1) {
cpuIndex = tempIndex
continue
}
if (line.startsWith(android.os.Process.myPid().toString())) {
if (cpuIndex == -1) {
continue
}
val param = line.split("\\s+".toRegex()).toTypedArray()
if (param.size <= cpuIndex) {
continue
}
var cpu = param[cpuIndex]
if (cpu.endsWith("%")) {
cpu = cpu.substring(0, cpu.lastIndexOf("%"))
}
return cpu.toFloat() / Runtime.getRuntime().availableProcessors()
}
}
} catch (e: IOException) {
e.printStackTrace()
} finally {
process?.destroy()
}
return 0F
}
/**
* 安卓8.0以下版本获取cpu使用率
*/
private fun getCpuUsageForLowerVersion(): Float {
val cpuTime: Long
val appTime: Long
var value = 0.0f
try {
if (mProcStatFile == null || mAppStatFile == null) {
mProcStatFile = RandomAccessFile("/proc/stat", "r")
mAppStatFile = RandomAccessFile("/proc/" + android.os.Process.myPid() + "/stat", "r")
} else {
mProcStatFile!!.seek(0L)
mAppStatFile!!.seek(0L)
}
val procStatString = mProcStatFile!!.readLine()
val appStatString = mAppStatFile!!.readLine()
val procStats = procStatString.split(" ".toRegex()).toTypedArray()
val appStats = appStatString.split(" ".toRegex()).toTypedArray()
cpuTime = procStats[2].toLong() + procStats[3].toLong() + procStats[4].toLong() + procStats[5].toLong() + procStats[6].toLong() + procStats[7].toLong() + procStats[8].toLong()
appTime = appStats[13].toLong() + appStats[14].toLong()
if (mLastCpuTime == null && mLastAppCpuTime == null) {
mLastCpuTime = cpuTime
mLastAppCpuTime = appTime
return value
}
value = (appTime - mLastAppCpuTime!!).toFloat() / (cpuTime - mLastCpuTime!!).toFloat() * 100f
mLastCpuTime = cpuTime
mLastAppCpuTime = appTime
} catch (e: Exception) {
e.printStackTrace()
}
return value
}
private fun getCPUIndex(line: String): Int {
if (line.contains("CPU")) {
val titles = line.split("\\s+".toRegex()).toTypedArray()
for (i in titles.indices) {
if (titles[i].contains("CPU")) {
return i
}
}
}
return -1
}
}
- 调用样例:
Log.d("MyApm-CPU使用率", CpuUtil.getCpuUsage().toString())