2011-02-05 12 views
26

私は最初のAndroidアプリケーションを開発しています。特権的なshellコマンドを実行するための「標準的な」方法があるかどうか不思議です。私はsuを実行して、suプロセスのstdinに自分のコマンドを追加することで、それを行う方法を見つけることができました。アンドロイド:Androidアプリケーションでルートアクセスを取得するにはどうすればよいですか?

DataOutputStream pOut = new DataOutputStream(p.getOutputStream()); 
DataInputStream pIn = new DataInputStream(p.getInputStream()); 

String rv = ""; 

// su must exit before its output can be read 
pOut.writeBytes(cmd + "\nexit\n"); 
pOut.flush(); 

p.waitFor(); 

while (pIn.available() > 0) 
    rv += pIn.readLine() + "\n"; 

私はラップについて読んだ特権(superuserJNIに呼び出す:これは可能ですか?もしそうなら、それを達成する方法は?それ以外に、Javaから特権命令を呼び出す方法はありますか?

+2

既存のプロセスの特権を昇格する手段は実際にはありません。新しいプロセスをルートとして実行することを意味します。 suコマンドに実行コマンドが渡された例については、http://stackoverflow.com/questions/4846241/more-than-one-superuser-command-android/4846312 –

+0

を参照してください。@Chris新しいアクティビティ/タスク/ AndroidのJavaアプリ/ etc? –

+3

それはアンドロイドに巨大な変更を必要とするでしょう。あなたは通常アンドロイドのJava実行のためのプロセスを作成するのではなく、アンドロイドに 'zygote'にそのアプリケーションのユーザーIDの下でフォークするように依頼します。ルート・タスクをネイティブの実行可能ファイルまたはシェル・スクリプトとしてアプリケーションに代わって重要な作業を行うように保つ方が簡単です。または、特権システムサービスとして適切なシステムに追加します。多くの場合、最良の方法は、UNIXグループを作成して特定の機能(デバイスファイルへのアクセスなど)にアクセスさせ、そのグループでサービスを実行するか、アンドロイドの許可を得てペアにすることです。 –

答えて

28

私が知る限り、コマンドラインコマンドはroot権限でのみ実行できます。あなたがする必要があるのは、このクラスを拡張し、rootとして実行するコマンドを返すようにgetCommandsToExecuteメソッドをオーバーライドしている http://muzikant-android.blogspot.com/2011/02/how-to-get-root-access-and-execute.html

:あなたはあなたのコードのルートアクセスをラップ私が作ったこのジェネリッククラスを使用することができます。

public abstract class ExecuteAsRootBase 
{ 
    public static boolean canRunRootCommands() 
    { 
     boolean retval = false; 
     Process suProcess; 

     try 
     { 
     suProcess = Runtime.getRuntime().exec("su"); 

     DataOutputStream os = new DataOutputStream(suProcess.getOutputStream()); 
     DataInputStream osRes = new DataInputStream(suProcess.getInputStream()); 

     if (null != os && null != osRes) 
     { 
      // Getting the id of the current user to check if this is root 
      os.writeBytes("id\n"); 
      os.flush(); 

      String currUid = osRes.readLine(); 
      boolean exitSu = false; 
      if (null == currUid) 
      { 
       retval = false; 
       exitSu = false; 
       Log.d("ROOT", "Can't get root access or denied by user"); 
      } 
      else if (true == currUid.contains("uid=0")) 
      { 
       retval = true; 
       exitSu = true; 
       Log.d("ROOT", "Root access granted"); 
      } 
      else 
      { 
       retval = false; 
       exitSu = true; 
       Log.d("ROOT", "Root access rejected: " + currUid); 
      } 

      if (exitSu) 
      { 
       os.writeBytes("exit\n"); 
       os.flush(); 
      } 
     } 
     } 
     catch (Exception e) 
     { 
     // Can't get root ! 
     // Probably broken pipe exception on trying to write to output stream (os) after su failed, meaning that the device is not rooted 

     retval = false; 
     Log.d("ROOT", "Root access rejected [" + e.getClass().getName() + "] : " + e.getMessage()); 
     } 

     return retval; 
    } 

    public final boolean execute() 
    { 
     boolean retval = false; 

     try 
     { 
     ArrayList<String> commands = getCommandsToExecute(); 
     if (null != commands && commands.size() > 0) 
     { 
      Process suProcess = Runtime.getRuntime().exec("su"); 

      DataOutputStream os = new DataOutputStream(suProcess.getOutputStream()); 

      // Execute commands that require root access 
      for (String currCommand : commands) 
      { 
       os.writeBytes(currCommand + "\n"); 
       os.flush(); 
      } 

      os.writeBytes("exit\n"); 
      os.flush(); 

      try 
      { 
       int suProcessRetval = suProcess.waitFor(); 
       if (255 != suProcessRetval) 
       { 
        // Root access granted 
        retval = true; 
       } 
       else 
       { 
        // Root access denied 
        retval = false; 
       } 
      } 
      catch (Exception ex) 
      { 
       Log.e("ROOT", "Error executing root action", ex); 
      } 
     } 
     } 
     catch (IOException ex) 
     { 
     Log.w("ROOT", "Can't get root access", ex); 
     } 
     catch (SecurityException ex) 
     { 
     Log.w("ROOT", "Can't get root access", ex); 
     } 
     catch (Exception ex) 
     { 
     Log.w("ROOT", "Error executing internal operation", ex); 
     } 

     return retval; 
    } 
    protected abstract ArrayList<String> getCommandsToExecute(); 
} 
+0

あなたにはCSSエラーがあるようですコードブロック。常に最後のキャラクターが最初の位置にあるのですか? – dtrunk

+0

@dtrunkアップデートをありがとう。私は自分のブログにエラーを修正しました。 – Muzikant

+0

クラスを共有してくれてありがとう。コマンドをパラメータとして渡す方がより有用であることが分かった。 boolean execute(ArrayList commands){...} – pmont

4

私が知っている可能性のある解決策は、システムとしてアプリケーションに署名することです。これは私が知る限り、ルートとまったく同じではありません。How to sign Android app with system signature?。しかし、これはあなたが望むものではないと思います。

私がやったもう一つのことは、必要な処理を行うネイティブアプリケーションを作成して外部プロセスとして実行することです。しかし、このネイティブアプリケーションに必要な特権とsuidビットを与える必要があります(パーティションがnosuidでない場合)。しかし、これはあなたが必要とするものではありません。

JNIを介して呼び出されるCコードは、同じプロセスでの生活と同じ制限が適用されるはずです。

suバイナリがある場合は、Runtime.getRuntime()。exec( "su -c reboot")のようにjavaからコマンドを実行できます。

私は他の方法を覚えていません。

関連する問題