2010-06-25 5 views
54

Есть ли какой-либо API, с помощью которого мы можем использовать процессор или память для Android?Получить использование памяти в Android

Я попробовал один код, как показано ниже:

package com.infostretch.mainactivity; 

import java.io.BufferedReader; 
import java.io.FileInputStream; 
import java.io.IOException; 
import java.io.InputStreamReader; 

public class CPULoad 
{ 
    long total = 0; 
    long idle = 0; 

    float usage = 0; 

    public CPULoad() 
    { 
     readUsage(); 
    } 

    public float getUsage() 
    { 
     readUsage(); 
     return usage; 
    } 

    private void readUsage() 
    { 
     try 
     { 
      BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("/proc/stat")), 1000); 
      String load = reader.readLine(); 
      reader.close(); 

      String[] toks = load.split(" "); 

      long currTotal = Long.parseLong(toks[2]) + Long.parseLong(toks[3]) + Long.parseLong(toks[4]); 
      long currIdle = Long.parseLong(toks[5]); 

      this.usage = (currTotal - total) * 100.0f/(currTotal - total + currIdle - idle); 
      this.total = currTotal; 
      this.idle = currIdle; 
     } 
     catch(IOException ex) 
     { 
      ex.printStackTrace(); 
     } 
    } 
} 

Является ли это правильный способ сделать это?

+1

Может быть, один вы будете принимать ответ ... – JPM

+0

о/р, что я получаю не правильный ... все время o/p находится в диапазоне от 0,825699 до 1,0, на моем телефоне Android работает только одно приложение. Я загружаю бесплатное приложение из игры Google для проверки использования процессора, но оба типа o/p отличаются друг от друга. Можете ли вы сказать мне, что я/получаю от телевизора.setText ("" + readCPUUsage()); –

+0

У студии Android теперь есть вкладка памяти, в которой вы получите всю информацию о приложении. – JPM

ответ

73

Я использую эту функцию для вычисления использования процессора. Надеюсь, это может вам помочь.

private float readUsage() { 
    try { 
     RandomAccessFile reader = new RandomAccessFile("/proc/stat", "r"); 
     String load = reader.readLine(); 

     String[] toks = load.split(" +"); // Split on one or more spaces 

     long idle1 = Long.parseLong(toks[4]); 
     long cpu1 = Long.parseLong(toks[2]) + Long.parseLong(toks[3]) + Long.parseLong(toks[5]) 
       + Long.parseLong(toks[6]) + Long.parseLong(toks[7]) + Long.parseLong(toks[8]); 

     try { 
      Thread.sleep(360); 
     } catch (Exception e) {} 

     reader.seek(0); 
     load = reader.readLine(); 
     reader.close(); 

     toks = load.split(" +"); 

     long idle2 = Long.parseLong(toks[4]); 
     long cpu2 = Long.parseLong(toks[2]) + Long.parseLong(toks[3]) + Long.parseLong(toks[5]) 
      + Long.parseLong(toks[6]) + Long.parseLong(toks[7]) + Long.parseLong(toks[8]); 

     return (float)(cpu2 - cpu1)/((cpu2 + idle2) - (cpu1 + idle1)); 

    } catch (IOException ex) { 
     ex.printStackTrace(); 
    } 

    return 0; 
} 
+0

Что произойдет, если у вас только 1 процессор? – ajacian81

+5

Что? Этот код работает для любого количества процессоров и дает использование процессора для всех процессоров. – Thalur

+0

Это довольно насмешки, но я получаю 1.0, который, как я полагаю, составляет 100% большую часть времени, хотя на устройстве нет приложений ... – TacB0sS

2

Проверьте класс Debug. http://developer.android.com/reference/android/os/Debug.html i.e Debug.getNativeHeapAllocatedSize()

У этого есть методы, чтобы получить использованную кучу родной, которая, например, используется внешними растровыми изображениями в вашем приложении. Для кучи, которую приложение использует внутренне, вы можете увидеть это в инструменте DDMS, который поставляется с Android SDK, а также доступен через Eclipse.

Нативная куча + куча, указанная в DDMS, составляет общую кучу, которую выделяет ваше приложение.

Для использования ЦП Я не уверен, есть ли что-либо доступное через API/SDK.

+0

Также см. Http://developer.android.com/intl/de/reference/android/os/Debug.html#getMemoryInfo(android.os.Debug.MemoryInfo) –

+0

Эй, Матиас. Спасибо за ваш вклад, но я обнаружил, что код работает очень хорошо. Я был на стороне и поэтому не мог ответить вам. Пока, прямо сейчас я работаю над точкой использования памяти. Я отправлю его код через день или два. – Badal

+0

Привет, Mathias .. Я хочу найти текущее использование памяти в мобильном телефоне через код приложения, и, следовательно, DDMS не может помочь в этом сценарии. Итак, что я сделал, я использовал команду/proc/meminfo и проанализировал ответ. но он показывает очень мало свободной памяти. Поэтому я просто смущен ответом. , пожалуйста, проверьте мой запрос здесь http://stackoverflow.com/questions/3170691/how-to-get-current-memory-usage-in-android – Badal

38

Простым способом проверки использования ЦП является использование инструмента adb w/top. То есть:

adb shell top -m 10

+0

очень хорошая команда! – ademar111190

+3

Вы не имеете в виду: «adb shell top -n 1»? –

+4

Хотя это верно, мой вопрос касался Android API не о каком-либо инструменте – Badal

11

Поскольку OP вопрос о загрузке процессора и оперативной памяти (принят ответ показывает только технику, чтобы получить использование центрального процессора), я хотел бы рекомендовать класс ActivityManager и конкретно принятый ответ от этого вопроса : How to get current memory usage in android?

17

На основании предыдущих ответов и личного опыта, вот код, который я использую для мониторинга использования ЦП. Код этого класса написан на чистой Java.

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> 
* &#064;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 &gt;= 0.0f) { 
*   _printLine(mOutput, &quot;total&quot;, Float.toString(cpu)); 
*  } 
* 
*  String[] toks = cpuStat1.split(&quot; &quot;); 
*  long cpu1 = linuxUtils.getSystemUptime(toks); 
* 
*  toks = cpuStat2.split(&quot; &quot;); 
*  long cpu2 = linuxUtils.getSystemUptime(toks); 
* 
*  cpu = linuxUtils.getProcessCpuUsage(pidStat1, pidStat2, cpu2 - cpu1); 
*  if (cpu &gt;= 0.0f) { 
*   _printLine(mOutput, &quot;&quot; + pid, Float.toString(cpu)); 
*  } 
* 
*  try { 
*   synchronized (this) { 
*    wait(CPU_REFRESH_RATE); 
*   } 
*  } catch (InterruptedException e) { 
*   e.printStackTrace(); 
*   return; 
*  } 
* } 
* 
* Log.i(&quot;THREAD CPU&quot;, &quot;Finishing&quot;); 
* } 
* </pre> 
*/ 
public final class LinuxUtils { 

    // Warning: there appears to be an issue with the column index with android linux: 
    // it was observed that on most present devices there are actually 
    // two spaces between the 'cpu' of the first column and the value of 
    // the next column with data. The thing is the index of the idle 
    // column should have been 4 and the first column with data should have index 1. 
    // The indexes defined below are coping with the double space situation. 
    // If your file contains only one space then use index 1 and 4 instead of 2 and 5. 
    // A better way to deal with this problem may be to use a split method 
    // not preserving blanks or compute an offset and add it to the indexes 1 and 4. 

    private static final int FIRST_SYS_CPU_COLUMN_INDEX = 2; 

    private static final int IDLE_SYS_CPU_COLUMN_INDEX = 5; 

    /** Return the first line of /proc/stat or null if failed. */ 
    public String readSystemStat() { 

     RandomAccessFile reader = null; 
     String load = null; 

     try { 
      reader = new RandomAccessFile("/proc/stat", "r"); 
      load = reader.readLine(); 
     } catch (IOException ex) { 
      ex.printStackTrace(); 
     } finally { 
      Streams.close(reader); 
     } 

     return load; 
    } 

    /** 
    * Compute and return the total CPU usage, in percent. 
    * 
    * @param start 
    *   first content of /proc/stat. Not null. 
    * @param end 
    *   second content of /proc/stat. Not null. 
    * @return 12.7 for a CPU usage of 12.7% or -1 if the value is not 
    *   available. 
    * @see {@link #readSystemStat()} 
    */ 
    public float getSystemCpuUsage(String start, String end) { 
     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); 

     // don't know how it is possible but we should care about zero and 
     // negative values. 
     float cpu = -1f; 
     if (idle1 >= 0 && up1 >= 0 && idle2 >= 0 && up2 >= 0) { 
      if ((up2 + idle2) > (up1 + idle1) && up2 >= up1) { 
       cpu = (up2 - up1)/(float) ((up2 + idle2) - (up1 + idle1)); 
       cpu *= 100.0f; 
      } 
     } 

     return cpu; 
    } 

    /** 
    * Return the sum of uptimes read from /proc/stat. 
    * 
    * @param stat 
    *   see {@link #readSystemStat()} 
    */ 
    public long getSystemUptime(String[] stat) { 
     /* 
     * (from man/5/proc) /proc/stat kernel/system statistics. Varies with 
     * architecture. Common entries include: cpu 3357 0 4313 1362393 
     * 
     * The amount of time, measured in units of USER_HZ (1/100ths of a 
     * second on most architectures, use sysconf(_SC_CLK_TCK) to obtain the 
     * right value), that the system spent in user mode, user mode with low 
     * priority (nice), system mode, and the idle task, respectively. The 
     * last value should be USER_HZ times the second entry in the uptime 
     * pseudo-file. 
     * 
     * In Linux 2.6 this line includes three additional columns: iowait - 
     * time waiting for I/O to complete (since 2.5.41); irq - time servicing 
     * interrupts (since 2.6.0-test4); softirq - time servicing softirqs 
     * (since 2.6.0-test4). 
     * 
     * Since Linux 2.6.11, there is an eighth column, steal - stolen time, 
     * which is the time spent in other operating systems when running in a 
     * virtualized environment 
     * 
     * Since Linux 2.6.24, there is a ninth column, guest, which is the time 
     * spent running a virtual CPU for guest operating systems under the 
     * control of the Linux kernel. 
     */ 

     // with the following algorithm, we should cope with all versions and 
     // probably new ones. 
     long l = 0L; 

     for (int i = FIRST_SYS_CPU_COLUMN_INDEX; i < stat.length; i++) { 
      if (i != IDLE_SYS_CPU_COLUMN_INDEX) { // bypass any idle mode. There is currently only one. 
       try { 
        l += Long.parseLong(stat[i]); 
       } catch (NumberFormatException ex) { 
        ex.printStackTrace(); 
        return -1L; 
       } 
      } 
     } 

     return l; 
    } 

    /** 
    * Return the sum of idle times read from /proc/stat. 
    * 
    * @param stat 
    *   see {@link #readSystemStat()} 
    */ 
    public long getSystemIdleTime(String[] stat) { 
     try { 
      return Long.parseLong(stat[IDLE_SYS_CPU_COLUMN_INDEX]); 
     } catch (NumberFormatException ex) { 
      ex.printStackTrace(); 
     } 

     return -1L; 
    } 

    /** Return the first line of /proc/pid/stat or null if failed. */ 
    public String readProcessStat(int pid) { 

     RandomAccessFile reader = null; 
     String line = null; 

     try { 
      reader = new RandomAccessFile("/proc/" + pid + "/stat", "r"); 
      line = reader.readLine(); 
     } catch (IOException ex) { 
      ex.printStackTrace(); 
     } finally { 
      Streams.close(reader); 
     } 

     return line; 
    } 

    /** 
    * Compute and return the CPU usage for a process, in percent. 
    * 
    * <p> 
    * The parameters {@code totalCpuTime} is to be the one for the same period 
    * of time delimited by {@code statStart} and {@code statEnd}. 
    * </p> 
    * 
    * @param start 
    *   first content of /proc/pid/stat. Not null. 
    * @param end 
    *   second content of /proc/pid/stat. Not null. 
    * @return the CPU use in percent or -1f if the stats are inverted or on 
    *   error 
    * @param uptime 
    *   sum of user and kernel times for the entire system for the 
    *   same period of time. 
    * @return 12.7 for a cpu usage of 12.7% or -1 if the value is not available 
    *   or an error occurred. 
    * @see {@link #readProcessStat(int)} 
    */ 
    public float getProcessCpuUsage(String start, String end, long uptime) { 

     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; 
    } 

    /** 
    * Decode the fields of the file {@code /proc/pid/stat} and return (utime + 
    * stime) 
    * 
    * @param stat 
    *   obtained with {@link #readProcessStat(int)} 
    */ 
    public long getProcessUptime(String[] stat) { 
     return Long.parseLong(stat[14]) + Long.parseLong(stat[15]); 
    } 

    /** 
    * Decode the fields of the file {@code /proc/pid/stat} and return (cutime + 
    * cstime) 
    * 
    * @param stat 
    *   obtained with {@link #readProcessStat(int)} 
    */ 
    public long getProcessIdleTime(String[] stat) { 
     return Long.parseLong(stat[16]) + Long.parseLong(stat[17]); 
    } 

    /** 
    * Return the total CPU usage, in percent. 
    * <p> 
    * The call is blocking for the time specified by elapse. 
    * </p> 
    * 
    * @param elapse 
    *   the time in milliseconds between reads. 
    * @return 12.7 for a CPU usage of 12.7% or -1 if the value is not 
    *   available. 
    */ 
    public float syncGetSystemCpuUsage(long elapse) { 

     String stat1 = readSystemStat(); 
     if (stat1 == null) { 
      return -1.f; 
     } 

     try { 
      Thread.sleep(elapse); 
     } catch (Exception e) { 
     } 

     String stat2 = readSystemStat(); 
     if (stat2 == null) { 
      return -1.f; 
     } 

     return getSystemCpuUsage(stat1, stat2); 
    } 

    /** 
    * Return the CPU usage of a process, in percent. 
    * <p> 
    * The call is blocking for the time specified by elapse. 
    * </p> 
    * 
    * @param pid 
    * @param elapse 
    *   the time in milliseconds between reads. 
    * @return 6.32 for a CPU usage of 6.32% or -1 if the value is not 
    *   available. 
    */ 
    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(); 
      return -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); 
    } 

} 
-2

введите андроида терминал, а затем вы можете ввести следующие команды: dumpsys CPUInfo

[email protected]:/ $ dumpsys cpuinfo            
Load: 0.8/0.75/1.15 
CPU usage from 69286ms to 9283ms ago with 99% awake: 
    47% 1118/com.wxg.sodproject: 12% user + 35% kernel 
    1.6% 1225/android.process.media: 1% user + 0.6% kernel 
    1.3% 263/mpdecision: 0.1% user + 1.2% kernel 
    0.1% 32747/kworker/u:1: 0% user + 0.1% kernel 
    0.1% 883/com.android.systemui: 0.1% user + 0% kernel 
    0.1% 521/system_server: 0.1% user + 0% kernel/faults: 14 minor 
    0.1% 1826/com.quicinc.trepn: 0.1% user + 0% kernel 
    0.1% 2462/kworker/0:2: 0.1% user + 0% kernel 
    0.1% 32649/kworker/0:0: 0% user + 0.1% kernel 
    0% 118/mmcqd/0: 0% user + 0% kernel 
    0% 179/surfaceflinger: 0% user + 0% kernel 
    0% 46/kinteractiveup: 0% user + 0% kernel 
    0% 141/jbd2/mmcblk0p26: 0% user + 0% kernel 
    0% 239/sdcard: 0% user + 0% kernel 
    0% 1171/com.xiaomi.channel:pushservice: 0% user + 0% kernel/faults: 1 minor 
    0% 1207/com.xiaomi.channel: 0% user + 0% kernel/faults: 1 minor 
    0% 32705/kworker/0:1: 0% user + 0% kernel 
12% TOTAL: 3.2% user + 9.4% kernel + 0% iowait 
+0

Ответчик искал API (Application Programming Interface), чтобы получить эту информацию. –

+0

Может быть вызван только системными приложениями, поэтому он не подходит для звонков в приложении Android по запросу. – tommed

Смежные вопросы