217 lines
7.7 KiB
Markdown
217 lines
7.7 KiB
Markdown
#python
|
||
#安卓
|
||
|
||
如果要通过python的形式,检测安卓的cpu占用率,是需要通过adb调试的形式,一般是连线安卓实体机;
|
||
在执行上述操作之前,需要确认的是,安卓的adb调试,是已经配置完成和可用的,参考[[设置adb环境变量]],还有python 3的环境变量,也是需要的,可参考[[python设置环境变量]],配置完成:
|
||
|
||
![[Pasted image 20250411151801.png]]
|
||
|
||
其中,安卓的bundleid包名,是`com.DefaultCompany.LGCollecter`
|
||
|
||
![[Pasted image 20250411152113.png]]
|
||
|
||
这是考虑了cpu多核情况的python脚本,1秒的时间间隔,采集cpu时间,可以直接执行:
|
||
|
||
## cpu.py
|
||
|
||
``` py
|
||
import subprocess
|
||
import time
|
||
|
||
PACKAGE = "com.DefaultCompany.LGCollecter"
|
||
INTERVAL = 1.0
|
||
|
||
def get_cpu_cores():
|
||
"""获取CPU核心数"""
|
||
try:
|
||
output = subprocess.check_output(
|
||
"adb shell grep -c processor /proc/cpuinfo",
|
||
stderr=subprocess.STDOUT,
|
||
shell=True
|
||
)
|
||
return int(output.strip())
|
||
except:
|
||
return 1
|
||
|
||
def get_pid():
|
||
"""持续获取进程ID"""
|
||
while True:
|
||
try:
|
||
output = subprocess.check_output(
|
||
f"adb shell pidof {PACKAGE}",
|
||
stderr=subprocess.STDOUT,
|
||
shell=True
|
||
)
|
||
pid = output.decode().strip()
|
||
if pid:
|
||
return int(pid)
|
||
except subprocess.CalledProcessError:
|
||
pass
|
||
print("等待应用启动...")
|
||
time.sleep(2)
|
||
|
||
def read_proc_stat():
|
||
"""读取系统CPU总时间"""
|
||
output = subprocess.check_output(
|
||
"adb shell head -n1 /proc/stat",
|
||
stderr=subprocess.STDOUT,
|
||
shell=True
|
||
).decode()
|
||
parts = output.strip().split()[1:8]
|
||
return sum(map(int, parts))
|
||
|
||
def read_process_cpu(pid):
|
||
"""读取进程CPU时间"""
|
||
output = subprocess.check_output(
|
||
f"adb shell cat /proc/{pid}/stat",
|
||
stderr=subprocess.STDOUT,
|
||
shell=True
|
||
).decode()
|
||
parts = output.strip().split()
|
||
utime = int(parts[13])
|
||
stime = int(parts[14])
|
||
return utime + stime
|
||
|
||
def main():
|
||
cores = get_cpu_cores()
|
||
pid = get_pid()
|
||
print(f"监控开始 (PID: {pid}, CPU核心: {cores})")
|
||
|
||
prev_proc_time = read_process_cpu(pid)
|
||
prev_total_time = read_proc_stat()
|
||
|
||
while True:
|
||
time.sleep(INTERVAL)
|
||
|
||
curr_proc_time = read_process_cpu(pid)
|
||
curr_total_time = read_proc_stat()
|
||
|
||
proc_diff = curr_proc_time - prev_proc_time
|
||
total_diff = curr_total_time - prev_total_time
|
||
|
||
if total_diff == 0:
|
||
usage = 0.0
|
||
else:
|
||
# 计算实际CPU使用率(考虑多核)
|
||
usage = 100.0 * proc_diff / total_diff
|
||
# 转换为多核百分比(可选)
|
||
# usage = usage * 100.0 / cores
|
||
|
||
print(f"{time.strftime('%H:%M:%S')} CPU使用率: {usage:.1f}%")
|
||
|
||
prev_proc_time = curr_proc_time
|
||
prev_total_time = curr_total_time
|
||
|
||
if __name__ == "__main__":
|
||
try:
|
||
main()
|
||
except KeyboardInterrupt:
|
||
print("\n监控已停止")
|
||
except Exception as e:
|
||
print(f"发生错误: {str(e)}")
|
||
```
|
||
|
||
安卓相关的,java逻辑,也可以实现,cpu占用率的测算,但是这个不是非常准确,另外安卓相关的,如果要获取,系统总的cpu频率等数据相关,也就是`/proc/stat`系统级别的信息,一般是不开放这个接口权限的,所以不够adb方式的,python脚本获取的数据准确;
|
||
|
||
需先申请权限,参考一下,权限申请:
|
||
|
||
## AndroidManifest.xml
|
||
|
||
``` xml
|
||
<manifest
|
||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||
xmlns:tools="http://schemas.android.com/tools">
|
||
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
|
||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||
<uses-permission android:name="android.permission.READ_PROC_STATE" />
|
||
<uses-permission android:name="android.permission.INTERNET" />
|
||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||
<application>
|
||
<activity android:name="com.unity3d.player.UnityPlayerActivity"
|
||
android:theme="@style/UnityThemeSelector">
|
||
<intent-filter>
|
||
<action android:name="android.intent.action.MAIN" />
|
||
<category android:name="android.intent.category.LAUNCHER" />
|
||
</intent-filter>
|
||
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
|
||
</activity>
|
||
</application>
|
||
</manifest>
|
||
```
|
||
|
||
## Sys.java
|
||
|
||
``` java
|
||
public static float getProcessCPUUsageOnce() {
|
||
try {
|
||
// 第一次采样
|
||
BufferedReader br1 = new BufferedReader(new FileReader("/proc/self/stat"));
|
||
String line1 = br1.readLine();
|
||
String[] parts1 = line1.split("\\s+");
|
||
long utime1 = Long.parseLong(parts1[13]);
|
||
long stime1 = Long.parseLong(parts1[14]);
|
||
long cpuTime1 = utime1 + stime1;
|
||
|
||
// 等待1秒
|
||
Thread.sleep(1000);
|
||
|
||
// 第二次采样
|
||
BufferedReader br2 = new BufferedReader(new FileReader("/proc/self/stat"));
|
||
String line2 = br2.readLine();
|
||
String[] parts2 = line2.split("\\s+");
|
||
long utime2 = Long.parseLong(parts2[13]);
|
||
long stime2 = Long.parseLong(parts2[14]);
|
||
long cpuTime2 = utime2 + stime2;
|
||
|
||
// 计算使用率
|
||
int hz = getSystemClockTicks();
|
||
float usage = ((cpuTime2 - cpuTime1) / (float) hz) * 100f;
|
||
// 新增日志输出
|
||
Log.d("CPUUsage", "系统CPU使用率: " + String.format("%.2f", usage) + "%");
|
||
return Math.max(0, Math.min(usage, 100));
|
||
|
||
} catch (Exception e) {
|
||
Log.e("CPUUsage", "获取CPU使用率失败", e);
|
||
e.printStackTrace();
|
||
}
|
||
return -1f;
|
||
}
|
||
|
||
// 新增帮助方法 获取CPU时钟频率Hz
|
||
private static int getSystemClockTicks() {
|
||
try {
|
||
// 方法1:通过系统属性获取(需要API 21+)
|
||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||
int hz = (int) android.system.Os.sysconf(android.system.OsConstants._SC_CLK_TCK);
|
||
if (hz > 0) {
|
||
return hz;
|
||
}
|
||
}
|
||
|
||
// 方法2:通过/proc文件系统动态计算
|
||
// 读取进程启动时间和系统运行时间
|
||
BufferedReader statBr = new BufferedReader(new FileReader("/proc/self/stat"));
|
||
String[] stat = statBr.readLine().split("\\s+");
|
||
long startTime = Long.parseLong(stat[21]); // 启动时间(jiffies)
|
||
long utime = Long.parseLong(stat[13]); // 用户态时间
|
||
|
||
BufferedReader uptimeBr = new BufferedReader(new FileReader("/proc/uptime"));
|
||
String uptimeStr = uptimeBr.readLine().split("\\s+")[0];
|
||
float uptime = Float.parseFloat(uptimeStr); // 系统运行时间(秒)
|
||
|
||
// 计算HZ:startTime的单位是jiffies,uptime的单位是秒
|
||
// HZ = startTime / (uptime - (process_start_time_seconds))
|
||
long processStartSeconds = startTime / 100; // 假设初始HZ=100进行估算
|
||
float actualHz = startTime / (uptime - processStartSeconds);
|
||
|
||
// 取整并限制合理范围
|
||
int hz = Math.max(100, Math.min(1000, (int)actualHz));
|
||
Log.d("ClockTicks", "Calculated HZ: " + hz);
|
||
return hz;
|
||
|
||
} catch (Exception e) {
|
||
Log.e("ClockTicks", "Error calculating HZ, using default 100", e);
|
||
return 100; // 保底返回值
|
||
}
|
||
}
|
||
``` |