2011-02-05 160 views
26

我正在开发我的第一个Android应用程序,我很好奇是否有任何执行特权shell命令的“标准”方法。我只能通过执行su,然后将我的命令追加到su进程的stdin中找到一种方法。ANDROID:如何在Android应用程序中获得root访问权限?

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

我读过有关包装特权(superuser)在JNI调出:这可能吗?如果是这样,一个人将如何去完成它?除此之外,还有其他方式可以调用Java的特权指令吗?

+2

没有任何提升现有进程特权的方法,只意味着启动以root身份运行的新进程。有关su传递要执行的命令的示例,请参阅http://stackoverflow.com/questions/4846241/more-than-one-superuser-command-android/4846312 – 2011-02-05 08:12:18

+0

@Chris关于启动新的活动/任务/ Android的Java应用程序/等? – 2011-02-05 08:35:46

回答

28

据我所知,你只能使用root权限运行命令行命令。你可以使用这个通用类,我做了包装在代码中的root访问权限: http://muzikant-android.blogspot.com/2011/02/how-to-get-root-access-and-execute.html

所有你需要做的是扩展这个类并覆盖getCommandsToExecute方法返回要执行以root的命令。

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

我知道的一个可能的解决方案是将您的应用程序签名为系统,与我所知的系统不完全相同:How to sign Android app with system signature?。但我想这不是你想要的。

我做的另一件事是创建一个本地应用程序,它执行所需的任务,将其作为外部进程运行。但有必要给这个本地应用程序你需要的权限和suid位,只要这个分区不是nosuid。但是,这不是你所需要的,或者我想。

我认为通过JNI调用的C代码应该和生活在同一个过程中一样受到限制。

如果你有可用的su二进制文件,那么你可以用java运行命令,如:Runtime.getRuntime().exec(“su -c reboot”)。

我不记得任何其他方式。

相关问题