ANDROID:如何在 Android 应用程序中获得 root 访问权限?

新手上路,请多包涵

我正在开发我的第一个 Android 应用程序,我很好奇是否有任何“标准”方法来执行特权 shell 命令。我只能通过执行 su ,然后将我的命令附加到 stdinsu

 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 调用特权指令吗?

原文由 Emma 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 905
2 个回答

据我所知,您只能使用 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();
}

原文由 Muzikant 发布,翻译遵循 CC BY-SA 3.0 许可协议

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

我做的另一件事是创建一个本机应用程序来执行所需的操作,并将其作为外部进程运行。但是有必要为这个本机应用程序提供您需要的权限和 suid 位,前提是该分区不是 nosuid。但我想这也不是你需要的。

我想,通过 JNI 调用的 C 代码应该受到与生活在同一进程中相同的限制。

如果您有可用的 su 二进制文件,那么您可以从 java 运行命令,例如: Runtime.getRuntime().exec("su -c reboot")

我不记得任何其他方式。

原文由 Luca Carlon 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题