Исходя из предыдущих ответов и личного опыта, вот код, который я использую для мониторинга использования процессора.Код этого класса написан на чистом Java.
<code>import java.io.IOException;
import java.io.RandomAccessFile;
/**
* Utilities available only on Linux Operating System.
*
* <p>
* A typical use is to assign a thread to CPU monitoring:
* </p>
*
* <pre>
* @Override
* public void run() {
* while (CpuUtil.monitorCpu) {
*
* LinuxUtils linuxUtils = new LinuxUtils();
*
* int pid = android.os.Process.myPid();
* String cpuStat1 = linuxUtils.readSystemStat();
* String pidStat1 = linuxUtils.readProcessStat(pid);
*
* try {
* Thread.sleep(CPU_WINDOW);
* } catch (Exception e) {
* }
*
* String cpuStat2 = linuxUtils.readSystemStat();
* String pidStat2 = linuxUtils.readProcessStat(pid);
*
* float cpu = linuxUtils.getSystemCpuUsage(cpuStat1, cpuStat2);
* if (cpu >= 0.0f) {
* _printLine(mOutput, "total", Float.toString(cpu));
* }
*
* String[] toks = cpuStat1.split(" ");
* long cpu1 = linuxUtils.getSystemUptime(toks);
*
* toks = cpuStat2.split(" ");
* long cpu2 = linuxUtils.getSystemUptime(toks);
*
* cpu = linuxUtils.getProcessCpuUsage(pidStat1, pidStat2, cpu2 - cpu1);
* if (cpu >= 0.0f) {
* _printLine(mOutput, "" + pid, Float.toString(cpu));
* }
*
* try {
* synchronized (this) {
* wait(CPU_REFRESH_RATE);
* }
* } catch (InterruptedException e) {
* e.printStackTrace();
* return;
* }
* }
*
* Log.i("THREAD CPU", "Finishing");
* }
*
* / public final class LinuxUtils {// Предупреждение: существует проблема с индексом столбца в android linux: // было замечено, что на большинствеВ настоящее время у устройств фактически есть // два пробела между «процессором» первого столбца и значением // следующего столбца с данными.Дело в том, что индекс столбца idle // должен быть равен 4, а первый столбец с данными должен иметь индекс 1. // Определенные ниже индексы справляются с ситуацией двойного пробела.// Если ваш файл содержит только один пробел, тогда используйте индексы 1 и 4 вместо 2 и 5. // Лучшим способом решения этой проблемы может быть использование метода split // без сохранения пробелов или вычисления смещения и его добавленияк индексам 1 и 4. приватная статическая final int FIRST_SYS_CPU_COLUMN_INDEX = 2;private static final int IDLE_SYS_CPU_COLUMN_INDEX = 5;/ ** Вернуть первую строку / proc / stat или null, если не удалось.* / public String readSystemStat () {RandomAccessFile reader = null;Нагрузка на строку = ноль;try {reader = new RandomAccessFile ("/ proc / stat", "r");load = reader.readLine ();} catch (IOException ex) {ex.printStackTrace ();} finally {Streams.close (читатель);} возврат нагрузки;} / ** * Вычисляет и возвращает общее использование процессора в процентах.* * @param start * первое содержимое / proc / stat.Ненулевой.* @param end * второй контент / proc / stat.Ненулевой.* @return 12,7 для использования ЦП 12,7% или -1, если значение * недоступно.* @see {@link #readSystemStat ()} * / public float getSystemCpuUsage (начало строки, конец строки) {String [] stat = start.split ("\\ s");long idle1 = getSystemIdleTime (stat);long up1 = getSystemUptime (stat);stat = end.split ("\\ s");long idle2 = getSystemIdleTime (stat);long up2 = getSystemUptime (stat);// не знаю, как это возможно, но мы должны заботиться о нулевых и // отрицательных значениях.число с плавающей запятой = -1f;if (idle1> = 0 && up1> = 0 && idle2> = 0 && up2> = 0) {if ((up2 + idle2)> (up1 + idle1) && up2> = up1) {cpu = (up2 - up1)/ (плавать) ((up2 + idle2) - (up1 + idle1));процессор * = 100,0f;}} return cpu;} / ** * Возвращает сумму времени простоя, прочитанного из / proc / stat.* * @param stat * see {@link #readSystemStat ()} * / public long getSystemUptime (String [] stat) {/ * * (из man / 5 / proc) / proc / stat ядро / системная статистика.Зависит от * архитектуры.Общие записи включают в себя: процессор 3357 0 4313 1362393 * * Количество времени, измеренное в единицах USER_HZ (1/100-ые * секунды на большинстве архитектур, используйте sysconf (_SC_CLK_TCK) для получения * правильного значения), которое система потратилав пользовательском режиме, пользовательском режиме с низким * приоритетом (приятно), системном режиме и задаче ожидания, соответственно.* Последнее значение должно быть USER_HZ, умноженное на вторую запись в псевдофайле uptime *.* * В Linux 2.6 эта строка включает три дополнительных столбца: iowait - * время ожидания завершения ввода / вывода (с 2.5.41);irq - время обслуживания * прерываний (начиная с 2.6.0-test4);softirq - время обслуживания softirqs * (начиная с 2.6.0-test4).* * Начиная с Linux 2.6.11, существует восьмой столбец, «украденное - украденное время», * который представляет собой время, проведенное в других операционных системах при работе в * виртуализированной среде * * Начиная с Linux 2.6.24, существует девятый столбец,гость, который время* потратил на запуск виртуального процессора для гостевых операционных систем под * контролем ядра Linux.* / // со следующим алгоритмом, мы должны справиться со всеми версиями и // возможно новыми.длинный l = 0L;for (int i = FIRST_SYS_CPU_COLUMN_INDEX; i * Параметры {@code totalCpuTime} должны быть такими же для того же периода времени *, разделенного {@code statStart} и {@code statEnd}.* * * @param start * первое содержимое / proc / pid / stat.Ненулевой.* @param end * второй контент / proc / pid / stat.Ненулевой.* @return использование ЦП в процентах или -1f, если статистика инвертирована или включена * error * @param uptime * сумма времени пользователя и ядра для всей системы за * тот же период времени.* @return 12,7 для использования ЦП 12,7% или -1, если значение недоступно * или произошла ошибка.* @see {@link #readProcessStat (int)} * / public float getProcessCpuUsage (начало строки, конец строки, длительное время работы) {String [] stat = start.split ("\\ s");long up1 = getProcessUptime (stat);stat = end.split ("\\ s");long up2 = getProcessUptime (stat);float ret = -1f;if (up1> = 0 && up2> = up1 && uptime> 0.) {ret = 100.f * (up2 - up1) / (float) uptime;} return ret;} / ** * Расшифровать поля файла {@code / proc / pid / stat} и вернуть (utime + * stime) * * @param stat *, полученное с помощью {@link #readProcessStat (int)} * / public longgetProcessUptime (String [] stat) {return Long.parseLong (stat [14]) + Long.parseLong (stat [15]);} / ** * Декодировать поля файла {@code / proc / pid / stat} и вернуть (cutime + * cstime) * * @param stat *, полученного с помощью {@link #readProcessStat (int)} * / public longgetProcessIdleTime (String [] stat) {return Long.parseLong (stat [16]) + Long.parseLong (stat [17]);} / ** * Возвращает общее использование процессора в процентах.*
* Вызов блокируется на время, указанное в elapse.*
* * @param elapse * время в миллисекундах между чтениями.* @return 12,7 для использования ЦП 12,7% или -1, если значение * недоступно.* / public float syncGetSystemCpuUsage (long elapse) {String stat1 = readSystemStat ();if (stat1 == null) {return -1.f;} пытаться {Thread.sleep (Elapse);} catch (Exception e) {} String stat2 = readSystemStat ();if (stat2 == null) {return -1.f;} return getSystemCpuUsage (stat1, stat2);} / ** * Возвращает использование процессора процессом в процентах.*
* Вызов блокируется на время, указанное в elapse.*
* * @param pid * @param elapse * время в миллисекундах между считываниями.* @return 6.32 для использования ЦП 6.32% или -1, если значение * недоступно.* / public float syncGetProcessCpuUsage (int pid, long elapse) {String pidStat1 = readProcessStat (pid);String totalStat1 = readSystemStat ();if (pidStat1 == null || totalStat1 == null) {return -1.f;} try {Thread.sleep (elapse);} catch (Exception e) {e.printStackTrace ();возврат -1.f;} String pidStat2 = readProcessStat (pid);String totalStat2 = readSystemStat ();if (pidStat2 == null || totalStat2 == null) {return -1.f;} String [] toks = totalStat1.split ("\\ s");long cpu1 = getSystemUptime (toks);toks = totalStat2.split ("\\ s");long cpu2 = getSystemUptime (toks);return getProcessCpuUsage (pidStat1, pidStat2, cpu2 - cpu1);}}
Существует несколько способов использования этого класса.Вы можете позвонить либо syncGetSystemCpuUsage
, либо syncGetProcessCpuUsage
, но каждый из них блокирует вызывающий поток.Поскольку общая проблема состоит в том, чтобы контролировать общее использование ЦП и использование ЦП текущего процесса одновременно, я разработал класс, вычисляющий оба из них.Этот класс содержит специальный поток.Управление выводом зависит от реализации, и вам нужно написать собственный код.
Класс можно настроить несколькими способами.Константа CPU_WINDOW
определяет глубину чтения, то есть количество миллисекунд между считыванием и вычислением соответствующей загрузки ЦП.CPU_REFRESH_RATE
- это время между каждым измерением загрузки процессора.Не устанавливайте CPU_REFRESH_RATE
в 0, потому что он приостановит поток после первого чтения.
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import android.app.Application;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import my.app.LinuxUtils;
import my.app.Streams;
import my.app.TestReport;
import my.app.Utils;
public final class CpuUtil {
private static final int CPU_WINDOW = 1000;
private static final int CPU_REFRESH_RATE = 100; // Warning: anything but > 0
private static HandlerThread handlerThread;
private static TestReport output;
static {
output = new TestReport();
output.setDateFormat(Utils.getDateFormat(Utils.DATE_FORMAT_ENGLISH));
}
private static boolean monitorCpu;
/**
* Construct the class singleton. This method should be called in
* {@link Application#onCreate()}
*
* @param dir
* the parent directory
* @param append
* mode
*/
public static void setOutput(File dir, boolean append) {
try {
File file = new File(dir, "cpu.txt");
output.setOutputStream(new FileOutputStream(file, append));
if (!append) {
output.println(file.getAbsolutePath());
output.newLine(1);
// print header
_printLine(output, "Process", "CPU%");
output.flush();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
/** Start CPU monitoring */
public static boolean startCpuMonitoring() {
CpuUtil.monitorCpu = true;
handlerThread = new HandlerThread("CPU monitoring"); //$NON-NLS-1$
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper());
handler.post(new Runnable() {
@Override
public void run() {
while (CpuUtil.monitorCpu) {
LinuxUtils linuxUtils = new LinuxUtils();
int pid = android.os.Process.myPid();
String cpuStat1 = linuxUtils.readSystemStat();
String pidStat1 = linuxUtils.readProcessStat(pid);
try {
Thread.sleep(CPU_WINDOW);
} catch (Exception e) {
}
String cpuStat2 = linuxUtils.readSystemStat();
String pidStat2 = linuxUtils.readProcessStat(pid);
float cpu = linuxUtils
.getSystemCpuUsage(cpuStat1, cpuStat2);
if (cpu >= 0.0f) {
_printLine(output, "total", Float.toString(cpu));
}
String[] toks = cpuStat1.split(" ");
long cpu1 = linuxUtils.getSystemUptime(toks);
toks = cpuStat2.split(" ");
long cpu2 = linuxUtils.getSystemUptime(toks);
cpu = linuxUtils.getProcessCpuUsage(pidStat1, pidStat2,
cpu2 - cpu1);
if (cpu >= 0.0f) {
_printLine(output, "" + pid, Float.toString(cpu));
}
try {
synchronized (this) {
wait(CPU_REFRESH_RATE);
}
} catch (InterruptedException e) {
e.printStackTrace();
return;
}
}
Log.i("THREAD CPU", "Finishing");
}
});
return CpuUtil.monitorCpu;
}
/** Stop CPU monitoring */
public static void stopCpuMonitoring() {
if (handlerThread != null) {
monitorCpu = false;
handlerThread.quit();
handlerThread = null;
}
}
/** Dispose of the object and release the resources allocated for it */
public void dispose() {
monitorCpu = false;
if (output != null) {
OutputStream os = output.getOutputStream();
if (os != null) {
Streams.close(os);
output.setOutputStream(null);
}
output = null;
}
}
private static void _printLine(TestReport output, String process, String cpu) {
output.stampln(process + ";" + cpu);
}
}