Android API 30中HardwarePropertiesManager报错及CPU信息获取方案咨询
Android 11(API 30)下获取CPU温度、使用率及内存信息的替代方案
原代码使用HardwarePropertiesManager触发SecurityException的原因是:从Android 10(API 29)开始,该类的温度查询方法就被严格限制,仅允许设备所有者、持有系统签名级DEVICE_POWER权限的应用,或是当前VrListener调用,普通应用无法直接使用。以下是普通应用可采用的替代方案:
一、获取CPU使用率
通过读取Linux内核提供的/proc/stat文件计算CPU使用率,这是Android平台通用的方式:
public static float getCpuUsage() { try { RandomAccessFile reader = new RandomAccessFile("/proc/stat", "r"); String load = reader.readLine(); String[] toks = load.split(" "); long idle1 = Long.parseLong(toks[5]); long cpu1 = Long.parseLong(toks[2]) + Long.parseLong(toks[3]) + Long.parseLong(toks[4]) + Long.parseLong(toks[6]) + Long.parseLong(toks[7]) + Long.parseLong(toks[8]); // 间隔360ms读取第二次数据,确保差值有效 Thread.sleep(360); reader.seek(0); load = reader.readLine(); reader.close(); toks = load.split(" "); long idle2 = Long.parseLong(toks[5]); long cpu2 = Long.parseLong(toks[2]) + Long.parseLong(toks[3]) + Long.parseLong(toks[4]) + Long.parseLong(toks[6]) + Long.parseLong(toks[7]) + Long.parseLong(toks[8]); // 计算这段时间内的CPU使用率 return (float) (cpu2 - cpu1) / ((cpu2 + idle2) - (cpu1 + idle1)) * 100; } catch (IOException | InterruptedException ex) { ex.printStackTrace(); } return 0; }
说明:/proc/stat存储的是系统启动以来的CPU累计运行时间,必须通过两次读取的差值计算实时使用率。
二、获取CPU温度
普通应用无法通过系统API直接获取CPU温度,可尝试读取sysfs下的温度节点(不同厂商设备路径可能不同):
public static float getCpuTemperature() { // 常见的CPU温度节点路径,需根据设备适配 String[] possiblePaths = { "/sys/class/thermal/thermal_zone0/temp", "/sys/class/thermal/thermal_zone1/temp", "/sys/devices/virtual/thermal/thermal_zone0/temp" }; for (String path : possiblePaths) { try { BufferedReader reader = new BufferedReader(new FileReader(path)); String tempStr = reader.readLine(); reader.close(); if (tempStr != null) { // 读取值为毫摄氏度,转换为摄氏度 return Float.parseFloat(tempStr) / 1000.0f; } } catch (IOException e) { // 路径不存在则尝试下一个 continue; } } // 所有路径读取失败时返回-1 return -1; }
说明:部分厂商可能限制普通应用读取这些节点的权限,此时无法获取CPU温度。
三、获取内存信息
使用系统提供的ActivityManager和MemoryInfo API,普通应用可直接调用:
public static void getMemoryInfo(Context context) { ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo(); activityManager.getMemoryInfo(memoryInfo); long totalMemory = memoryInfo.totalMem; long availableMemory = memoryInfo.availMem; float memoryUsage = (1 - (float) availableMemory / totalMemory) * 100; // 转换为MB单位便于阅读 float totalMemMB = totalMemory / (1024 * 1024); float availableMemMB = availableMemory / (1024 * 1024); Log.d("MemoryInfo", "总内存:" + String.format("%.2f", totalMemMB) + " MB"); Log.d("MemoryInfo", "可用内存:" + String.format("%.2f", availableMemMB) + " MB"); Log.d("MemoryInfo", "内存使用率:" + String.format("%.2f", memoryUsage) + "%"); }
四、获取CPU核心信息
读取/proc/cpuinfo文件获取核心数、型号等信息:
// 获取CPU核心数 public static int getCpuCoreCount() { try { BufferedReader reader = new BufferedReader(new FileReader("/proc/cpuinfo")); String line; int coreCount = 0; while ((line = reader.readLine()) != null) { if (line.startsWith("processor")) { coreCount++; } } reader.close(); return coreCount; } catch (IOException e) { e.printStackTrace(); // 读取失败时返回Runtime统计的可用核心数 return Runtime.getRuntime().availableProcessors(); } } // 获取CPU型号 public static String getCpuModel() { try { BufferedReader reader = new BufferedReader(new FileReader("/proc/cpuinfo")); String line; while ((line = reader.readLine()) != null) { if (line.startsWith("model name")) { return line.split(":")[1].trim(); } } reader.close(); } catch (IOException e) { e.printStackTrace(); } return "Unknown"; }
内容的提问来源于stack exchange,提问作者BePositve
相关产品推荐
相关产品推荐

