Android - 以编程方式执行 su 命令不起作用

Posted

技术标签:

【中文标题】Android - 以编程方式执行 su 命令不起作用【英文标题】:Android- performing su commands programatically does not work 【发布时间】:2015-06-27 07:28:27 【问题描述】:

我需要我的应用程序以编程方式执行一些su 命令(手机已root)。

使用 adb 完成后,这些命令将起作用。

例如: su -c "mkdir /sdcard/testdir" 在 /sdcard 中创建一个名为“testdir”的目录。

当我打电话时:

    p = Runtime.getRuntime().exec("su -c \"mkdir /sdcard/testdir\"");
    p.waitFor();

它只是继续前进,没有发生任何变化。

我尝试读取输入:

DataInputStream dis = new DataInputStream(p.getInputStream());
    while((temp = dis.readLine())!=null)
        Log.d(ctx.TAG,"shell:"+temp);

但它什么也没报告(循环执行 0 次迭代)。

以前有人遇到过这个问题吗?如何解决? 不用说,非 su 命令确实可以通过这种方法以编程方式工作。

注意:我以mkdir 为例(我知道它不一定需要 su)。我需要在su下执行很多不同的命令

谢谢!

编辑:当我以编程方式调用 su -c "id" 时,输出 uid=0。

【问题讨论】:

你解决了这个问题吗?在这里正好面临同样的问题 【参考方案1】:

我可能会在一个问题上卡住几天,而当我鼓起勇气在 *** 上询问它时,它会在几分钟内得到解决。

解决方法是:

    p=Runtime.getRuntime().exec("su");
    DataOutputStream dos = new DataOutputStream(p.getOutputStream());
    dos.writeBytes("mkdir /sdcard/testdir\n");
    dos.writeBytes("exit\n");
    dos.flush();
    dos.close();
    p.waitFor();

不要忘记\n 在您写入DataOutputStream 的每个命令的末尾,因为没有它就无法工作。

【讨论】:

如果我以这种方式启动超级用户对话,我无法点击它 收到错误 java.io.IOException: Cannot run program "su": error=13, Permission denied 我收到“原因:java.io.IOException:无法运行程序“su”:错误=13,权限被拒绝”。如何配置我的模拟器以获得此权限?【参考方案2】:

您写道您“需要在 su 下执行各种命令”。请注意,最著名的 SuperSU 根应用程序的开发者 Chainfire 不鼓励使用“Runtime.exec()”。

使用 Runtime.getRuntime().exec("su -c [command]"); 很诱人,但您应该知道 [command] 应该是单个参数,因此可能需要引用。不幸的是,引用 [command] 参数以及将参数作为单独的变量传递给 Runtime.exec() 或 ProcessBuilder 在所有 android 版本中都不能一致地工作,因此应该完全避免这种结构。正确地做到这一点并非不可能 - 但问题的风险很高。

请参阅How to SU 文档。所以你可能想在这里听从他的建议:

3.2.拨打电话

避免上述已知问题的调用 su 的常用方法是创建交互式 shell 并将命令传递给它。这是通过调用 Runtime.getRuntime().exec("su"); 并从返回的 Process 对象中检索输入和输出流来完成的。这样做是一段相当直接的代码,但包括调试日志和检查,在这里重现有点长。

核心代码位于:[libsuperuser :: Shell.java @ GitHub]。 Shell.run() 是运行 shell 代码的通用调用,以下更具体的(静态)实用程序函数是您最终可能会使用的函数:

List<String> Shell.SH.run(String command)
List<String> Shell.SH.run(List<String> commands)
List<String> Shell.SH.run(String[] commands)

List<String> Shell.SU.run(String command)
List<String> Shell.SU.run(List<String> commands)
List<String> Shell.SU.run(String[] commands)

SH 变体用于非 root shell,而 SU 变体用于 root shell。这些调用返回一个包含 shell 命令输出的列表。如果没有输出,则列表为空,但不为空。仅在发生错误的情况下结果为 null - 包括用户未授予您的应用程序 su 访问权限。这些是阻塞调用。

请注意,在调试编译中,所有 shell STDIN/STDOUT/STDERR 都将记录到 logcat,如果从主线程调用,这些调用将(有意)使您的应用程序崩溃。其原因将在第 4 节中讨论。何时调用 su。

【讨论】:

【参考方案3】:

如果你使用双引号,它会起作用:

su -c ""command with args""

【讨论】:

【参考方案4】:

您可能在主线程中调用Runtime.getRuntime().exec(),而p.waitFor() 使您的主线程等待直到它执行。尝试在另一个线程中调用,如下面的 sn-p。

new Thread()

     @override
     public void run()
        p = Runtime.getRuntime().exec("su -c \"mkdir /sdcard/testdir\"");
        p.waitFor();

     .start();


【讨论】:

感谢 Aswin,但我的程序没有卡住 - p.waitFor() 完成并继续运行。问题是命令没有影响,在/sdcard中也没有创建testdir 你的sdcard挂载了吗?检查路径“/sdcard”。 是的,如果在 adb shell 中执行,su -c "mkdir /sdcard/testdir" 确实可以工作。

以上是关于Android - 以编程方式执行 su 命令不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Android:以编程方式在 FrameLayout 中设置边距 - 不起作用

8实战演练su命令与sudo服务

以编程方式设置边距不起作用

以编程方式更改Chip Widget样式不起作用 - Android

以指定用户执行脚本

以编程方式关闭 Android 手机