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 中设置边距 - 不起作用