2012-04-09 18 views
6

私の人生の間、私のアプリケーションはsuシェル内からbusyboxを呼び出すプロセスからの応答を得ることができません。Androidアプリ内のbusyboxコマンドから出力を取得する

私は3つの方法を試してみましたが、3つの方法を組み合わせて試してみましたが、残りのコマンドはbusyboxを使って何も出力できません。

具体的には、 "ls/data"や "cat suchandsuch.file"のようなコマンドを返すことができますが、 "busybox"(つまりビジーボックスマウント、ビジーボックスフリー)で始まるものは何も表示しません。

これは私のために最も近いを得た方法であった、このコードは、「LS /データ」で動作しますが、ない「busyboxの自由」

この1つは(大部分)コマンドを実行します、とリターン無限ループの代わりに入力ストリームから空の文字列。

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

ボトム付近のトーストは、 "ls/data"のすべてを表示しますが、ビジーボックスの場合は空白またはヌルに変更されます。

私もこれらの両方を試しましたが、それらの方々が働いていました。 (私はコマンドを実行した後にプロセスを渡していました)

メソッドのボタンを押すと、これらの両方がアプリをフリーズすることになります。

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は動作するためのスタックトレースがないので、少し詰まってしまいます。

以下に提案するコードで編集しました.D 簡単なトラブルシューティングとテストのために、1回の実行で問題なく動作するように少し変更しました。

これは入力ストリームを読み込もうとするとフリーズし、ストリームを読み込もうとする前にstdin.writeBytes( "exit \ n")を呼び出すと、ターミナルを閉じて空の答えを返しますその後、それは無限にループする。

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

それは、その最初の行(あなたがコマンドを呼び出すたびに取得するbusyboxの情報ライン)をスキップし、データの残りの部分をキャッチないように思えます。誰のは、この上でいくつかの洞察力を持っている場合/

、私は大いにapreciativeだろう:)

答えて

1

私はこのための回避策のようなものを見つけた:アイブ氏は、私は考えることができるすべてのバリエーションは、この作業権利を取得しようとしました。

まず、私の場合、busyboxにリンクされたコマンドを実行しても、どのメソッドを試しても、そのInputStreamを通じて結果を返すことはありませんでした。

これは私が私ができることがわかったものです。ちょっと退屈で、完全な出力は得られませんが、もしコマンドが正しく発動されたかどうかに頼るものがあれば(私の場合、私のアプリはうまく動作しません。)

あなたは、プロセスからの入力を取得カントが、あなたは、あなたが右のそれを作業する場合:)これはあなたに大きなファイルに猫を使用してのような複雑な応答を(与えるdoesntの何のために働く終了値を取得することができます)

両者の違いは、例えば、見つけるのは簡単です:

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

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

これは私が簡単に動作するように設定する方法です。 MasterJBによって提供される方法を使用して、通常のようにコマンドを実行します。

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

は、私もそれが簡単に何が起こったかを返すように「0または1」メソッドを作成することが判明、この例ではそのトーストとして解雇しました。 1つのインスタンスがls/sysである場合、これはsu端末を通過するときに空白の終了値を返します。あなただけなきゃ右それらをキャプチャ、ちょうど適切な応答を持つ任意の終了値について一致させることができ、研究の少し付)

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

:)

これらのメソッドは、コマンドが(0)走っただけかどうかを返しますが、ダブルまたはトリプルchar終了コードを取得した場合、最後の数字は失敗したとき(つまり終了値が10のとき)に0になる可能性があるため、ほとんどの場合は機能しますが、ダブル値とトリプル値を取得する必要があります。

3

ここには簡単な解決策があります。これは私のために作成したユーティリティクラスです。ネイティブシェル、デバイスがルートされている場合はルートシェル、またはカスタムシェルを設定できます。どうぞ。

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

+0

これは金であります!ありがとうございました! –

関連する問題