Wie erkenne ich die Speichernutzung meiner Anwendung in Android?

800

Wie kann ich den in meiner Android-Anwendung verwendeten Speicher programmgesteuert finden?

Ich hoffe, es gibt einen Weg, dies zu tun. Und wie bekomme ich auch den freien Speicher des Telefons?

Andrea Baccega
quelle
2
Oder wenn jemand mehr darüber wissen möchte, dann besuchen Sie bitte http://elinux.org/Android_Memory_Usage
1
Verwalten Sie den Speicher Ihrer App. Developer.android.com/topic/performance/memory
Shomu

Antworten:

1008

Beachten Sie, dass die Speichernutzung unter modernen Betriebssystemen wie Linux ein äußerst komplizierter und schwer verständlicher Bereich ist. Tatsächlich ist die Wahrscheinlichkeit, dass Sie die Zahlen, die Sie erhalten, tatsächlich richtig interpretieren, äußerst gering. (Fast jedes Mal, wenn ich mit anderen Ingenieuren die Speichernutzungszahlen betrachte, gibt es eine lange Diskussion darüber, was sie tatsächlich bedeuten, was nur zu einer vagen Schlussfolgerung führt.)

Hinweis: Wir haben jetzt eine viel umfangreichere Dokumentation zum Verwalten des Speichers Ihrer App, die einen Großteil des Materials hier abdeckt und mit dem Status von Android auf dem neuesten Stand ist.

Als erstes sollten Sie wahrscheinlich den letzten Teil dieses Artikels lesen, in dem erläutert wird, wie der Speicher unter Android verwaltet wird:

Änderungen der Service-API ab Android 2.0

Jetzt ActivityManager.getMemoryInfo()ist unsere API auf höchster Ebene für die Betrachtung der gesamten Speichernutzung. Dies dient hauptsächlich dazu, einer Anwendung zu helfen, zu beurteilen, wie nahe das System daran ist, keinen Speicher mehr für Hintergrundprozesse zu haben, und daher damit beginnen muss, benötigte Prozesse wie Dienste zu beenden. Für reine Java-Anwendungen sollte dies wenig nützlich sein, da das Java-Heap-Limit teilweise dazu dient, zu verhindern, dass eine App das System bis zu diesem Punkt belasten kann.

Auf einer niedrigeren Ebene können Sie die Debug-API verwenden, um Informationen auf Kernel-Ebene zur Speichernutzung abzurufen : android.os.Debug.MemoryInfo

Beachten Sie, dass es ab 2.0 auch eine API gibt ActivityManager.getProcessMemoryInfo, um diese Informationen zu einem anderen Prozess abzurufen : ActivityManager.getProcessMemoryInfo (int [])

Dies gibt eine Low-Level-MemoryInfo-Struktur mit all diesen Daten zurück:

    /** The proportional set size for dalvik. */
    public int dalvikPss;
    /** The private dirty pages used by dalvik. */
    public int dalvikPrivateDirty;
    /** The shared dirty pages used by dalvik. */
    public int dalvikSharedDirty;

    /** The proportional set size for the native heap. */
    public int nativePss;
    /** The private dirty pages used by the native heap. */
    public int nativePrivateDirty;
    /** The shared dirty pages used by the native heap. */
    public int nativeSharedDirty;

    /** The proportional set size for everything else. */
    public int otherPss;
    /** The private dirty pages used by everything else. */
    public int otherPrivateDirty;
    /** The shared dirty pages used by everything else. */
    public int otherSharedDirty;

Aber, was ist der Unterschied zwischen Pss, PrivateDirtyund SharedDirty... na ja jetzt beginnt der Spaß.

Viel Speicher in Android (und Linux-Systemen im Allgemeinen) wird tatsächlich von mehreren Prozessen gemeinsam genutzt. Wie viel Speicher ein Prozess verwendet, ist also nicht klar. Fügen Sie zusätzlich dieses Paging auf die Festplatte hinzu (geschweige denn Swap, das wir unter Android nicht verwenden), und es ist noch weniger klar.

Wenn Sie also den gesamten physischen RAM verwenden würden, der tatsächlich jedem Prozess zugeordnet ist, und alle Prozesse addieren würden, würden Sie wahrscheinlich eine Zahl erhalten, die viel größer ist als der tatsächliche Gesamtspeicher.

Die PssAnzahl ist eine vom Kernel berechnete Metrik, die die Speicherfreigabe berücksichtigt. Grundsätzlich wird jede Seite des Arbeitsspeichers in einem Prozess durch ein Verhältnis der Anzahl anderer Prozesse skaliert, die diese Seite ebenfalls verwenden. Auf diese Weise können Sie (theoretisch) das PSS über alle Prozesse hinweg addieren, um den von ihnen verwendeten Gesamtspeicher zu sehen, und das PSS zwischen Prozessen vergleichen, um eine grobe Vorstellung von ihrem relativen Gewicht zu erhalten.

Die andere interessante Metrik hier ist PrivateDirtyim Grunde die Menge an RAM innerhalb des Prozesses, die nicht auf die Festplatte ausgelagert werden kann (sie wird nicht von denselben Daten auf der Festplatte unterstützt) und nicht mit anderen Prozessen gemeinsam genutzt wird. Eine andere Möglichkeit, dies zu betrachten, ist der RAM, der dem System zur Verfügung steht, wenn dieser Prozess unterbrochen wird (und wahrscheinlich schnell in Caches und andere Verwendungen davon zusammengefasst wird).

Das sind so ziemlich die SDK-APIs dafür. Sie können als Entwickler jedoch noch mehr mit Ihrem Gerät tun.

Mit adbkönnen Sie viele Informationen über die Speichernutzung eines laufenden Systems abrufen. Ein häufiger Befehl ist der Befehl, adb shell dumpsys meminfoder eine Reihe von Informationen über die Speichernutzung jedes Java-Prozesses ausspuckt, die die oben genannten Informationen sowie eine Vielzahl anderer Dinge enthalten. Sie können auch den Namen oder die PID eines einzelnen Prozesses eingeben, um beispielsweise adb shell dumpsys meminfo systemden Systemprozess zu sehen:

** MEMINFO in pid 890 [System] **
                    native dalvik andere total
            Größe: 10940 7047 N / A 17987
       zugewiesen: 8943 5516 N / A 14459
            frei: 336 1531 N / A 1867
           (Pss): 4585 9282 11916 25783
  (gemeinsam schmutzig geteilt): 2184 3596 916 6696
    (priv schmutzig): 4504 5956 7456 17916

 Objekte
           Aufrufe: 149 ViewRoots: 4
     AppContexts: 13 Aktivitäten: 0
          Vermögenswerte: 4 AssetManager: 4
   Lokale Ordner: 141 Proxy-Ordner: 158
Todesempfänger: 49
 OpenSSL-Sockets: 0

 SQL
            Heap: 205 dbDateien: 0
       numPagers: 0 inactivePageKB: 0
    activePageKB: 0

Der obere Abschnitt ist die wichtigste, wo sizeist die Gesamtgröße in Adressraum eines bestimmten Haufens, allocatedist die kb Istverrechnungen dass Haufen denken , es hat, freeist der restliche kb des Heap frei für zusätzliche Zuteilungen hat, und pssund priv dirtyist die gleiche wie zuvor speziell für Seiten beschrieben, die jedem der Heaps zugeordnet sind.

Wenn Sie nur die Speichernutzung über alle Prozesse hinweg betrachten möchten, können Sie den Befehl verwenden adb shell procrank. Die Ausgabe auf demselben System sieht folgendermaßen aus:

  PID Vss Rss Pss Uss cmdline
  890 84456K 48668K 25850K 21284K system_server
 1231 50748K 39088K 17587K 13792K com.android.launcher2
  947 34488K 28528K 10834K 9308K com.android.wallpaper
  987 26964K 26956K 8751K 7308K com.google.process.gapps
  954 24300K ​​24296K 6249K 4824K com.android.phone
  948 23020K 23016K 5864K 4748K com.android.inputmethod.latin
  888 25728K 25724K 5774K 3668K Zygote
  977 24100K 24096K 5667K 4340K android.process.acore
...
   59 336K 332K 99K 92K / system / bin / installd
   60 396K 392K 93K 84K / System / Bin / Keystore
   51 280K 276K 74K 68K / System / Behälter / Servicemanager
   54 256K 252K 69K 64K / system / bin / debuggerd

Hier sind die Spalten Vssund Rssim Grunde genommen Rauschen (dies sind der einfache Adressraum und die RAM-Auslastung eines Prozesses. Wenn Sie die RAM-Auslastung prozessübergreifend addieren, erhalten Sie eine lächerlich große Zahl).

Pssist wie wir vorher gesehen haben und Ussist Priv Dirty.

Interessantes zu beachten: Pssund unterscheiden Usssich geringfügig (oder mehr als geringfügig) von dem, was wir gesehen haben meminfo. Warum ist das so? Nun, Procrank verwendet einen anderen Kernel-Mechanismus, um seine Daten zu sammeln als dies der meminfoFall ist, und sie liefern leicht unterschiedliche Ergebnisse. Warum ist das so? Ehrlich gesagt habe ich keine Ahnung. Ich glaube, es procrankmag genauer sein ... aber wirklich, das lässt nur den Punkt: "Nehmen Sie alle Erinnerungsinformationen, die Sie mit einem Salzkorn erhalten; oft ein sehr großes Korn."

Schließlich gibt es den Befehl adb shell cat /proc/meminfo, der eine Zusammenfassung der gesamten Speichernutzung des Systems gibt. Hier gibt es viele Daten, nur die ersten Zahlen, die es wert sind, diskutiert zu werden (und die übrigen, die von wenigen Menschen verstanden werden, und meine Fragen an diese wenigen Menschen, die oft zu widersprüchlichen Erklärungen führen):

MemTotal: 395144 kB
MemFree: 184936 kB
Puffer: 880 kB
Zwischengespeichert: 84104 kB
SwapCached: 0 kB

MemTotal ist die Gesamtmenge an Speicher, die dem Kernel und dem Benutzerbereich zur Verfügung steht (häufig weniger als der tatsächliche physische RAM des Geräts, da ein Teil dieses RAM für das Radio, DMA-Puffer usw. benötigt wird).

MemFreeist die Menge an RAM, die überhaupt nicht verwendet wird. Die Zahl, die Sie hier sehen, ist sehr hoch; Auf einem Android-System sind dies normalerweise nur wenige MB, da wir versuchen, den verfügbaren Speicher zu verwenden, um die Prozesse am Laufen zu halten

Cachedist der RAM, der für Dateisystem-Caches und andere solche Dinge verwendet wird. Typische Systeme benötigen ungefähr 20 MB, um nicht in einen schlechten Paging-Zustand zu geraten. Der Android Out-of-Memory-Killer ist auf ein bestimmtes System abgestimmt, um sicherzustellen, dass Hintergrundprozesse beendet werden, bevor der zwischengespeicherte RAM von ihnen zu stark beansprucht wird, um zu einem solchen Paging zu führen.

Hackbod
quelle
1
Werfen Sie einen Blick auf pixelbeat.org/scripts/ps_mem.py , das die oben genannten Techniken verwendet, um den verwendeten RAM für Programme
anzuzeigen
17
Sehr schön geschrieben! Ich habe hier einen Beitrag über die Speicherverwaltung und die Verwendung verschiedener Tools geschrieben, um Ihre Heap-Nutzung zu überprüfen. Macgyverdev.blogspot.com/2011/11/… falls jemand dies nützlich findet.
Johan Norén
3
Was genau sind die beiden Spalten "dalvik" ein "Eingeborener"?
Dacongy
1
Was genau sind "native" "dalvik" "other"? In meiner App ist "andere" sehr groß? Wie kann ich es reduzieren?
Landry
Ich kann "adb shell dumpsys meminfo" verwenden, aber "adb shell procrank" sagt mir "/ system / bin / sh: procrank: nicht gefunden". Ich habe keine Ahnung. Ich wünschte, Sie können mir helfen.
Hugo
79

Ja, Sie können Speicherinformationen programmgesteuert abrufen und entscheiden, ob Sie speicherintensive Arbeiten ausführen möchten.

Holen Sie sich die VM-Heap-Größe, indem Sie Folgendes aufrufen:

Runtime.getRuntime().totalMemory();

Holen Sie sich den zugewiesenen VM-Speicher, indem Sie Folgendes aufrufen:

Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();

Holen Sie sich das VM Heap Size Limit, indem Sie Folgendes aufrufen:

Runtime.getRuntime().maxMemory()

Holen Sie sich den nativ zugewiesenen Speicher, indem Sie Folgendes aufrufen:

Debug.getNativeHeapAllocatedSize();

Ich habe eine App erstellt, um das Verhalten von OutOfMemoryError herauszufinden und die Speichernutzung zu überwachen.

https://play.google.com/store/apps/details?id=net.coocood.oomresearch

Den Quellcode erhalten Sie unter https://github.com/coocood/oom-research

coocood
quelle
7
Gibt diese Laufzeit die Speichernutzung durch den aktuellen Prozess oder den gesamten Systemheap zurück?
Mahendran
1
@ Mahemadhi aus dem JavaDoc der totalMemory () -Methode "Gibt die Gesamtmenge an Speicher zurück, die dem laufenden Programm zur Verfügung steht"
Alex
Dies ist keine korrekte Antwort auf die Frage. Die Antwort bezieht sich nicht auf eine bestimmte Anwendung.
Amir Rezazadeh
52

Dies ist eine laufende Arbeit, aber das verstehe ich nicht:

ActivityManager activityManager = (ActivityManager) context.getSystemService(ACTIVITY_SERVICE);
MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
activityManager.getMemoryInfo(memoryInfo);

Log.i(TAG, " memoryInfo.availMem " + memoryInfo.availMem + "\n" );
Log.i(TAG, " memoryInfo.lowMemory " + memoryInfo.lowMemory + "\n" );
Log.i(TAG, " memoryInfo.threshold " + memoryInfo.threshold + "\n" );

List<RunningAppProcessInfo> runningAppProcesses = activityManager.getRunningAppProcesses();

Map<Integer, String> pidMap = new TreeMap<Integer, String>();
for (RunningAppProcessInfo runningAppProcessInfo : runningAppProcesses)
{
    pidMap.put(runningAppProcessInfo.pid, runningAppProcessInfo.processName);
}

Collection<Integer> keys = pidMap.keySet();

for(int key : keys)
{
    int pids[] = new int[1];
    pids[0] = key;
    android.os.Debug.MemoryInfo[] memoryInfoArray = activityManager.getProcessMemoryInfo(pids);
    for(android.os.Debug.MemoryInfo pidMemoryInfo: memoryInfoArray)
    {
        Log.i(TAG, String.format("** MEMINFO in pid %d [%s] **\n",pids[0],pidMap.get(pids[0])));
        Log.i(TAG, " pidMemoryInfo.getTotalPrivateDirty(): " + pidMemoryInfo.getTotalPrivateDirty() + "\n");
        Log.i(TAG, " pidMemoryInfo.getTotalPss(): " + pidMemoryInfo.getTotalPss() + "\n");
        Log.i(TAG, " pidMemoryInfo.getTotalSharedDirty(): " + pidMemoryInfo.getTotalSharedDirty() + "\n");
    }
}

Warum wird die PID nicht dem Ergebnis in activityManager.getProcessMemoryInfo () zugeordnet? Natürlich möchten Sie die resultierenden Daten aussagekräftig machen. Warum hat Google es so schwierig gemacht, die Ergebnisse zu korrelieren? Das aktuelle System funktioniert nicht einmal gut, wenn ich die gesamte Speichernutzung verarbeiten möchte, da das zurückgegebene Ergebnis ein Array von android.os.Debug.MemoryInfo-Objekten ist, aber keines dieser Objekte sagt Ihnen tatsächlich, welchen Pids sie zugeordnet sind. Wenn Sie einfach ein Array aller Pids übergeben, können Sie die Ergebnisse nicht verstehen. Soweit ich weiß, ist es sinnlos, mehr als eine PID gleichzeitig zu übergeben. Wenn dies der Fall ist, warum sollte es dann so gemacht werden, dass activityManager.getProcessMemoryInfo () nur ein int-Array akzeptiert?

Ryan Beesley
quelle
2
Sie befinden sich wahrscheinlich in derselben Reihenfolge wie das Eingabearray.
Taer
2
Das scheint eine sehr nicht intuitive Art zu sein, Dinge zu tun. Ja, das ist wahrscheinlich der Fall, aber wie ist das in irgendeiner Weise OOP?
Ryan Beesley
6
Die API wurde auf Effizienz, nicht auf Benutzerfreundlichkeit oder Einfachheit ausgelegt. Dies ist einfach nicht etwas, das 99% der Apps jemals berühren sollten, daher ist Effizienz das wichtigste Designziel.
Hackbod
2
Meinetwegen. Ich versuche, ein internes Tool zu schreiben, um die Speichernutzung für eine oder mehrere der von uns geschriebenen Anwendungen zu verfolgen. Aus diesem Grund suche ich nach einer Möglichkeit, diese Überwachung durchzuführen, während die anderen Prozesse am wenigsten beeinflusst werden, die Ergebnisse jedoch so detailliert wie möglich sind (Nachbearbeitung). Das Durchlaufen der Prozesse und das anschließende Aufrufen der einzelnen Prozesse scheint ineffizient zu sein, vorausgesetzt, für jeden .getProcessMemoryInfo-Aufruf ist ein gewisser Overhead erforderlich. Wenn das zurückgegebene Array garantiert in der gleichen Reihenfolge wie der Aufruf ist, verarbeite ich die Ergebnisse blind und gehe einfach von Parität aus.
Ryan Beesley
5
Dies ist ein kleines Problem, aber für Log ist es nicht erforderlich, einen Zeilenvorschub hinzuzufügen, der für Sie behandelt wird.
ThomasW
24

Hackbod's ist eine der besten Antworten auf Stack Overflow. Es wirft ein Licht auf ein sehr dunkles Thema. Es hat mir sehr geholfen.

Eine weitere wirklich hilfreiche Ressource ist dieses Video, das man gesehen haben muss: Google I / O 2011: Speicherverwaltung für Android Apps


AKTUALISIEREN:

Process Stats, ein Dienst, mit dem Sie herausfinden können , wie Ihre App den Speicher verwaltet, wird im Blogbeitrag erläutert. Process Stats: Verstehen, wie Ihre App RAM verwendet von Dianne Hackborn:

Xavi Gil
quelle
19

Android Studio 0.8.10+ hat ein unglaublich nützliches Tool namens Memory Monitor eingeführt .

Geben Sie hier die Bildbeschreibung ein

Wofür es gut ist:

  • Anzeigen des verfügbaren und verwendeten Speichers in einem Diagramm sowie von Speicherbereinigungsereignissen im Laufe der Zeit.
  • Schnelles Testen, ob die Langsamkeit der App mit übermäßigen Speicherbereinigungsereignissen zusammenhängt.
  • Schnelles Testen, ob App-Abstürze möglicherweise auf Speichermangel zurückzuführen sind.

Geben Sie hier die Bildbeschreibung ein

Abbildung 1. Erzwingen eines GC-Ereignisses (Garbage Collection) auf dem Android Memory Monitor

Mithilfe dieser Funktion können Sie in Echtzeit zahlreiche gute Informationen zum RAM-Verbrauch Ihrer App erhalten.

Machado
quelle
16

1) Ich denke nicht, zumindest nicht von Java.
2)

ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
MemoryInfo mi = new MemoryInfo();
activityManager.getMemoryInfo(mi);
Log.i("memory free", "" + mi.availMem);
yanchenko
quelle
1
Wechseln Sie zu (ActivityManager activityManager = (ActivityManager) getSystemService (ACTIVITY_SERVICE);) anstelle von (ActivityManager activityManager = = (ActivityManager) getSystemService (ACTIVITY_SERVICE);)
Rajkamal
7

Wir haben herausgefunden, dass alle Standardmethoden zum Abrufen des Gesamtspeichers des aktuellen Prozesses einige Probleme aufweisen.

  • Runtime.getRuntime().totalMemory(): Gibt nur JVM-Speicher zurück
  • ActivityManager.getMemoryInfo(), Process.getFreeMemory()Und alles , was basierend auf /proc/meminfo- Renditen Speicher Informationen über alle Prozesse kombiniert (zB android_util_Process.cpp )
  • Debug.getNativeHeapAllocatedSize()- Verwendet, mallinfo()die nur Informationen über Speicherzuweisungen zurückgeben, die von malloc()und verwandten Funktionen ausgeführt werden (siehe android_os_Debug.cpp ).
  • Debug.getMemoryInfo()- macht den Job, aber es ist zu langsam. Auf dem Nexus 6 dauert ein einzelner Anruf etwa 200 ms . Der Leistungsaufwand macht diese Funktion für uns nutzlos, da wir sie regelmäßig aufrufen und jeder Aufruf ziemlich auffällig ist (siehe android_os_Debug.cpp ).
  • ActivityManager.getProcessMemoryInfo(int[])- ruft Debug.getMemoryInfo()intern auf (siehe ActivityManagerService.java )

Schließlich haben wir den folgenden Code verwendet:

const long pageSize = 4 * 1024; //`sysconf(_SC_PAGESIZE)`
string stats = File.ReadAllText("/proc/self/statm");
var statsArr = stats.Split(new [] {' ', '\t', '\n'}, 3);

if( statsArr.Length < 2 )
    throw new Exception("Parsing error of /proc/self/statm: " + stats);

return long.Parse(statsArr[1]) * pageSize;

Es gibt die VmRSS- Metrik zurück. Weitere Details dazu finden Sie hier: eins , zwei und drei .


PS Ich habe festgestellt, dass dem Thema immer noch ein tatsächlicher und einfacher Codeausschnitt fehlt, wie die private Speichernutzung des Prozesses geschätzt werden kann, wenn die Leistung keine kritische Anforderung ist:

Debug.MemoryInfo memInfo = new Debug.MemoryInfo();
Debug.getMemoryInfo(memInfo);
long res = memInfo.getTotalPrivateDirty();

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) 
    res += memInfo.getTotalPrivateClean(); 

return res * 1024L;
Dmitry Shesterkin
quelle
1

Es gibt viele Antworten oben, die Ihnen definitiv helfen werden, aber (nach 2 Tagen des Erschwingens und Nachforschens über ADB-Speicher-Tools) denke ich, dass ich auch mit meiner Meinung helfen kann .

Wie Hackbod sagt: Wenn Sie also den gesamten physischen RAM verwenden würden, der tatsächlich jedem Prozess zugeordnet ist, und alle Prozesse addieren würden, würden Sie wahrscheinlich eine Zahl erhalten, die viel größer ist als der tatsächliche Gesamtspeicher. Es gibt also keine Möglichkeit, die genaue Speichermenge pro Prozess abzurufen.

Aber Sie können sich dem durch eine Logik nähern ... und ich werde sagen, wie ...

Es gibt einige APIs wie android.os.Debug.MemoryInfound ActivityManager.getMemoryInfo()oben erwähnt, über die Sie möglicherweise bereits gelesen und verwendet wurden, aber ich werde auf andere Weise darüber sprechen

Zunächst müssen Sie also ein Root-Benutzer sein, damit es funktioniert. Holen Sie sich in die Konsole mit Root-Rechten, indem Sie suin Prozess ausführen und seine erhalten output and input stream. Dann passieren id\n (Enter) in ouputstream und schreiben Sie es auf Prozessausgang wird Wenn bekommen einen Inputstream enthält uid=0, sind Sie Root - Benutzer.

Hier ist die Logik, die Sie im obigen Prozess verwenden werden

Wenn Sie ouputstream des Prozessdurchlaufs erhalten, befehlen Sie (procrank, dumpsys meminfo etc ...) \nanstelle von id und erhalten Sie seine inputstreamund lesen Sie, speichern Sie den Stream in Bytes [], char [] etc .. verwenden Sie Rohdaten..und Sie sind fertig!!!!!

Genehmigung :

<uses-permission android:name="android.permission.FACTORY_TEST"/>

Überprüfen Sie, ob Sie Root-Benutzer sind:

// su command to get root access
Process process = Runtime.getRuntime().exec("su");         
DataOutputStream dataOutputStream = 
                           new DataOutputStream(process.getOutputStream());
DataInputStream dataInputStream = 
                           new DataInputStream(process.getInputStream());
if (dataInputStream != null && dataOutputStream != null) {
   // write id to console with enter
   dataOutputStream.writeBytes("id\n");                   
   dataOutputStream.flush();
   String Uid = dataInputStream.readLine();
   // read output and check if uid is there
   if (Uid.contains("uid=0")) {                           
      // you are root user
   } 
}

Führen Sie Ihren Befehl mit aus su

Process process = Runtime.getRuntime().exec("su");         
DataOutputStream dataOutputStream = 
                           new DataOutputStream(process.getOutputStream());
if (dataOutputStream != null) {
 // adb command
 dataOutputStream.writeBytes("procrank\n");             
 dataOutputStream.flush();
 BufferedInputStream bufferedInputStream = 
                     new BufferedInputStream(process.getInputStream());
 // this is important as it takes times to return to next line so wait
 // else you with get empty bytes in buffered stream 
 try {
       Thread.sleep(10000);
 } catch (InterruptedException e) {                     
       e.printStackTrace();
 }
 // read buffered stream into byte,char etc.
 byte[] bff = new byte[bufferedInputStream.available()];
 bufferedInputStream.read(bff);
 bufferedInputStream.close();
 }
}

logcat: Ergebnis

Sie erhalten Rohdaten in einer einzelnen Zeichenfolge von der Konsole anstatt in einigen Fällen von einer API, deren Speicherung komplex ist, da Sie sie manuell trennen müssen .

Dies ist nur ein Versuch, bitte schlagen Sie mir vor, wenn ich etwas verpasst habe

Iamat8
quelle