2012-04-09 7 views
6

Für das Leben von mir kann ich nicht meine App bekommen, die Antwort von einem Prozess zu erhalten, der innerhalb von su-Shell busybox anruft.Ausgabe von Busybox-Befehlen innerhalb der Android-App

Ich habe versucht, drei verschiedene Methoden, sowie eine Kombination der drei, um es zur Arbeit zu bekommen, aber ich kann nie die Ausgabe von irgendetwas mit busybox, nur den Rest der Befehle.

Um genauer zu sein, kann ich es Befehle wie "ls/data" und "cat suchandsuch.file" zurückgeben, aber alles, was mit "busybox" beginnt (dh busybox mount, busybox free) zeigt einfach nichts .

Das war die Methode, die am nächsten bei mir hätte, funktioniert dieser Code mit „ls/data“, aber nicht „busybox frei“

Dieser den Befehl laufen würde (zum größten Teil), und Rückkehr eine leere Zeichenfolge anstelle einer Schleife endlos aus dem Eingangsstrom.

 Process p; 
     try { 
      p = Runtime.getRuntime().exec(new String[]{"su", "-c", "/system/bin/sh"}); 
     DataOutputStream stdin = new DataOutputStream(p.getOutputStream()); 
     stdin.writeBytes("ls /data\n"); 
     DataInputStream stdout = new DataInputStream(p.getInputStream()); 
     byte[] buffer = new byte[4096]; 
     int read = 0; 
     String out = new String(); 
     while(true){ 
      read = stdout.read(buffer); 
      out += new String(buffer, 0, read); 
      if(read<4096){ 
       break; 
      } 
     } 
     Toast.makeText(getApplicationContext(), out, Toast.LENGTH_SHORT).show(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

Der Toast am unteren Rand zeigt alles von „ls/data“, aber wenn sie etwas für Busybox, dessen leer oder null geändert.

Ich habe auch beide versucht, aber keiner von ihnen funktioniert. (Ich habe den Prozess an sie weitergegeben, nachdem der Befehl ausgeführt wurde.)

Beides würde immer dazu führen, dass die App sofort einfriert, wenn Sie den Knopf für die Methoden drücken.

String termReader(Process process){ 
    BufferedReader reader = new BufferedReader(
     new InputStreamReader(process.getInputStream())); 
    try { 

    int i; 
    char[] buffer = new char[4096]; 
    StringBuffer output = new StringBuffer(); 
    while ((i = reader.read(buffer)) > 0) output.append(buffer, 0, i); 
    reader.close(); 
    return output.toString(); 
    } catch (IOException e) { 
    e.printStackTrace(); 
    return e.getMessage(); 
    } 
} 



String processReader(Process process){ 
    InputStream stdout = process.getInputStream(); 
    byte[] buffer = new byte[1024]; 
    int read; 
    String out = new String(); 
    while(true){ 
     try { 
      read = stdout.read(buffer); 
     out += new String(buffer, 0, read); 
     if(read<1024){ 
      break; 
     } 
     } catch (IOException e) { 
      e.printStackTrace(); 

     } 
    } 
    return out; 
} 

Theres keine Stack-Spuren zu arbeiten, so dass ich ein wenig ratlos bin.

Bearbeitet mit dem unten vorgeschlagenen Code, uh, unten: D Ich änderte es um ein kleines bisschen, um es zu einem Oneclick-Lauf-Ding für eine einfachere Fehlersuche und Tests zu machen.

Das friert auch ein, wenn es versucht, den Eingangsstrom zu lesen, und wenn ich stdin.writeBytes ("exit \ n") vor dem Lesen des Streams aufrufen, gibt es mir die leere Antwort vom Schließen des Terminals, wenn ich es anrufe Danach schleift es endlos.

 void Run() { 
       String command = "busybox traceroute\n"; 



     StringBuffer theRun = null; 
     try { 
      Process process = Runtime.getRuntime().exec("su"); 
      DataOutputStream stdin = new DataOutputStream(process.getOutputStream()); 
      stdin.writeBytes(command); 
      BufferedReader reader = new BufferedReader(
        new InputStreamReader(process.getInputStream())); 
      int read; 
      char[] buffer = new char[4096]; 
      StringBuffer output = new StringBuffer(); 
      while ((read = reader.read(buffer)) > 0) { 
       theRun = output.append(buffer, 0, read); 
      } 
      reader.close(); 
      process.waitFor(); 

     } catch (IOException e) { 
      throw new RuntimeException(e); 
     } catch (InterruptedException e) { 
      throw new RuntimeException(e); 
     } 
     Toast.makeText(getApplicationContext(), theRun, Toast.LENGTH_SHORT).show(); 
    } 

Es scheint, wie seine in der ersten Zeile (die Busybox Infozeile Sie jedes Mal wenn Sie den Befehl aufrufen, erhalten) und nicht Überspringen der Rest der Daten zu kontrollieren. Ive versucht, alle Variationen ich denken kann dies zum Laufen zu bringen rechts:/

Wenn jemand auf diese einen Einblick bekam ist, ich stark apreciative würde :)

Antwort

1

ich für diese eine Art einer Vermeidung des Problems gefunden haben .

Zunächst würde die Ausführung von Befehlen, die mit busybox verbunden sind, in meinem Fall niemals ihre Ausgabe über ihren InputStream zurückgeben, egal welche Methode ich versuchte (Und ich habe ALOT lol versucht).

Das ist, was ich herausgefunden habe, konnte ich tun. Es ist ein bisschen langweilig, und gibt Ihnen nicht die volle Leistung, aber wenn Sie wollen, dass etwas darauf verlassen, ob ein Befehl richtig abgefeuert wurde (in meinem Fall würde meine App nicht funktionieren, wenn ich nicht vergleichen könnte, wie alles lief.

)

Sie kann die Eingabe von dem Prozess, aber Sie können die Exit-Wert erhalten, wenn Sie es funktioniert richtig :) dies alles funktioniert, dass Sie eine komplexe Antwort tut geben (wie Katze mit auf einer großen Datei)

der Unterschied zwischen den beiden ist leicht zu finden, zum Beispiel:

command = "cat /sys" // works, exits with 1 

command = "cat /init.rc" doesnt work, exits with 0 

das ist, wie ich es einrichten leicht zu arbeiten. Führen Sie die Befehle als normale Anwendung des Verfahrens von MasterJB bereitgestellt.

  Process p; 
     try { 
      p = Runtime.getRuntime().exec(new String[]{"su", "-c", "/system/bin/sh"}); 
     DataOutputStream stdin = new DataOutputStream(p.getOutputStream()); 
     stdin.writeBytes(command); 
     stdin.writeBytes("echo $?\n"); 

     DataInputStream stdout = new DataInputStream(p.getInputStream()); 
     byte[] buffer = new byte[4096]; 
     int read = 0; 
     String out = new String(); 
     while(true){ 
      read = stdout.read(buffer); 
      out += new String(buffer, 0, read); 
      if(read<4096){ 
       break; 
      } 

        // here is where you catch the error value 

           int len = out.length(); 
     char suExitValue = out.charAt(len-2); 
     Toast.makeText(getApplicationContext(), String.valueOf(suExitValue), Toast.LENGTH_SHORT).show(); 


        return0or1(Integer.valueOf(suExitValue), command); // 0 or 1 Method 

        // end catching exit value        

     } 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

Ich fand es auch einfacher, eine „0 oder 1“ Verfahren machen zurückzukehren, was passiert ist, in diesem Beispiel seine als Toast gebrannt. Sie können auch testen, ob das Zeichen genau eine ganze Zahl ist, da einige Befehle keinen exit-Wert geben (wierd, ich weiß.) Eine Instanz ist ls/sys, die einen leeren Ausgangswert zurückgibt, wenn sie durch ein su-Terminal läuft.

)
String return0or1 (int returnValue, String command){ 
    String message = command + " - Cannot get return value."; 

    if (returnValue == 0){ 
     message = command + " - successful."; 
     return message; 
    } 
    if (returnValue == 1){ 
     message = command + " - failed."; 
     return message; 
    } 
    return message; 
} 

mit ein wenig Forschung können Sie fast jede Exit-Wert mit der richtigen Antworten übereinstimmen, just gotta fangen sie richtig :)

diese Methoden geben nur, ob der Befehl ausgeführt wurde (0), aber Wenn es einen doppelten oder dreifachen Char-Exit-Code erhält, kann die letzte Ziffer 0 sein, wenn sie fehlgeschlagen ist (dh wenn der Exit-Wert 10 ist), dies funktioniert in den meisten Fällen, muss aber erweitert werden, um doppelte und dreifache Werte zu erhalten.

3

Hier ist eine schnelle Lösung ... Es ist eine Utility-Klasse, die ich nur dafür geschaffen habe. Sie können die native Shell, eine Root-Shell, wenn das Gerät gerootet ist, oder eine benutzerdefinierte Shell festlegen. Bitte schön.

https://github.com/jjNford/android-shell

+0

Das ist Gold! Vielen Dank! –

Verwandte Themen