1. 前言
記得剛來公司 4 個多月的時候,公司的一個產品問我:可以獲取 Android cpu 的溫度嗎?我答道:如果別人可以,我們也可以獲取到。其實,我那時確實不知道怎麼獲取,也沒具體去看這個問題。等到最近確實需要這個功能時,實在是找了好多資料,才找到了方案。現在想想,那時回答的實在是很輕率啊。
2. 正文
2.1 兩種可選方案
查詢網上的文章,有兩種方案:
1,通過讀取溫度傳感器的值近似作爲 cpu 的溫度:這個方案在沒有溫度傳感器的手機上行不通;再者,這也是近似的溫度,並不是 cpu 真正的溫度;
2,通過讀取 cpu 內核信息獲取溫度:這個方法直接也準確,但是到底讀取哪些信息呢?資料並不充分。
2.2 採取的方案
本文采取的是第二種方案。
經過查詢資料,有更多的備選可以讀取。可以查看下面的類:
public class CpuUtils {
private CpuUtils() {
//no instance
}
private static final List<String> CPU_TEMP_FILE_PATHS = Arrays.asList(
"/sys/devices/system/cpu/cpu0/cpufreq/cpu_temp",
"/sys/devices/system/cpu/cpu0/cpufreq/FakeShmoo_cpu_temp",
"/sys/class/thermal/thermal_zone0/temp",
"/sys/class/i2c-adapter/i2c-4/4-004c/temperature",
"/sys/devices/platform/tegra-i2c.3/i2c-4/4-004c/temperature",
"/sys/devices/platform/omap/omap_temp_sensor.0/temperature",
"/sys/devices/platform/tegra_tmon/temp1_input",
"/sys/kernel/debug/tegra_thermal/temp_tj",
"/sys/devices/platform/s5p-tmu/temperature",
"/sys/class/thermal/thermal_zone1/temp",
"/sys/class/hwmon/hwmon0/device/temp1_input",
"/sys/devices/virtual/thermal/thermal_zone1/temp",
"/sys/devices/virtual/thermal/thermal_zone0/temp",
"/sys/class/thermal/thermal_zone3/temp",
"/sys/class/thermal/thermal_zone4/temp",
"/sys/class/hwmon/hwmonX/temp1_input",
"/sys/devices/platform/s5p-tmu/curr_temp");
public static final Maybe<CpuTemperatureResult> getCpuTemperatureFinder() {
return Observable
.fromIterable(CPU_TEMP_FILE_PATHS)
.map(new Function<String, CpuTemperatureResult>() {
@Override
public CpuTemperatureResult apply(String path) {
Double temp = readOneLine(new File(path));
String validPath = "";
double currentTemp = 0.0D;
if (isTemperatureValid(temp)) {
validPath = path;
currentTemp = temp;
} else if (isTemperatureValid(temp / (double) 1000)) {
validPath = path;
currentTemp = temp / (double) 1000;
}
return new CpuTemperatureResult(validPath, (int) currentTemp);
}
}).filter(new Predicate<CpuTemperatureResult>() {
@Override
public boolean test(CpuTemperatureResult cpuTemperatureResult) throws Exception {
return !TextUtils.isEmpty(cpuTemperatureResult.getFilePath())
&& (cpuTemperatureResult.getTemp() != 0);
}
}).firstElement();
}
private static double readOneLine(File file) {
FileInputStream fileInputStream = null;
String s = "";
try {
fileInputStream = new FileInputStream(file);
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
s = bufferedReader.readLine();
fileInputStream.close();
inputStreamReader.close();
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
double result = 0;
try {
result = Double.parseDouble(s);
} catch (NumberFormatException ignored) {
}
return result;
}
private static boolean isTemperatureValid(double temp) {
return temp >= -30.0D && temp <= 250.0D;
}
}
上面的代碼用到了 RxJava 的操作符來處理集合的遍歷。思路就是遍歷讀取集合中的文件,獲取到信息;判斷符合條件,就作爲 cpu 的溫度;如果都不符合,那麼就讀取不到 cpu 的溫度。
這個方案也不是兼容所有的手機的,但是確實兼容性比較高。
3. 最後
感謝這個開源項目:https://github.com/kamgurgul/cpu-info,提供了較爲完備的解決方案。