Java 从android执行shell命令
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20932102/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
execute shell command from android
提问by Giovanni Mariotti
I'm trying to execute this command from the application emulator terminal (you can find it in google play) in this app i write su
and press enter, so write:
我正在尝试从应用程序模拟器终端(您可以在 google play 中找到它)在我编写su
并按下的应用程序中执行此命令enter,因此请编写:
screenrecord --time-limit 10 /sdcard/MyVideo.mp4
screenrecord --time-limit 10 /sdcard/MyVideo.mp4
and press again enterand start the recording of the screen using the new function of android kitkat.
并再次按下enter并使用android kitkat的新功能开始录屏。
so, i try to execute the same code from java using this:
所以,我尝试使用这个从java执行相同的代码:
Process su = Runtime.getRuntime().exec("su");
Process execute = Runtime.getRuntime().exec("screenrecord --time-limit 10 /sdcard/MyVideo.mp4");
But don't work because the file is not created. obviously i'm running on a rooted device with android kitkat installed. where is the problem? how can i solve? because from terminal emulator works and in Java not?
但不工作,因为文件没有创建。显然,我在安装了 android kitkat 的有根设备上运行。问题出在哪儿?我该如何解决?因为从终端模拟器工作而在 Java 中不是?
采纳答案by Carlo Cannas
You should grab the standard input of the su
process just launched and write down the command there, otherwise you are running the commands with the current UID
.
您应该获取su
刚刚启动的进程的标准输入并在那里写下命令,否则您将使用当前的UID
.
Try something like this:
尝试这样的事情:
try{
Process su = Runtime.getRuntime().exec("su");
DataOutputStream outputStream = new DataOutputStream(su.getOutputStream());
outputStream.writeBytes("screenrecord --time-limit 10 /sdcard/MyVideo.mp4\n");
outputStream.flush();
outputStream.writeBytes("exit\n");
outputStream.flush();
su.waitFor();
}catch(IOException e){
throw new Exception(e);
}catch(InterruptedException e){
throw new Exception(e);
}
回答by 18446744073709551615
A modification of the code by @CarloCannas:
@CarloCannas 对代码的修改:
public static void sudo(String...strings) {
try{
Process su = Runtime.getRuntime().exec("su");
DataOutputStream outputStream = new DataOutputStream(su.getOutputStream());
for (String s : strings) {
outputStream.writeBytes(s+"\n");
outputStream.flush();
}
outputStream.writeBytes("exit\n");
outputStream.flush();
try {
su.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
outputStream.close();
}catch(IOException e){
e.printStackTrace();
}
}
(You are welcome to find a better place for outputStream.close())
(欢迎您为outputStream.close()找到更好的地方)
Usage example:
用法示例:
private static void suMkdirs(String path) {
if (!new File(path).isDirectory()) {
sudo("mkdir -p "+path);
}
}
Update:To get the result (the output to stdout), use:
更新:要获得结果(输出到标准输出),请使用:
public static String sudoForResult(String...strings) {
String res = "";
DataOutputStream outputStream = null;
InputStream response = null;
try{
Process su = Runtime.getRuntime().exec("su");
outputStream = new DataOutputStream(su.getOutputStream());
response = su.getInputStream();
for (String s : strings) {
outputStream.writeBytes(s+"\n");
outputStream.flush();
}
outputStream.writeBytes("exit\n");
outputStream.flush();
try {
su.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
res = readFully(response);
} catch (IOException e){
e.printStackTrace();
} finally {
Closer.closeSilently(outputStream, response);
}
return res;
}
public static String readFully(InputStream is) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length = 0;
while ((length = is.read(buffer)) != -1) {
baos.write(buffer, 0, length);
}
return baos.toString("UTF-8");
}
The utility to silently close a number of Closeables (Soсket may be no Closeable) is:
静默关闭多个 Closeables(Soсket 可能不是 Closeable)的实用程序是:
public class Closer {
// closeAll()
public static void closeSilently(Object... xs) {
// Note: on Android API levels prior to 19 Socket does not implement Closeable
for (Object x : xs) {
if (x != null) {
try {
Log.d("closing: "+x);
if (x instanceof Closeable) {
((Closeable)x).close();
} else if (x instanceof Socket) {
((Socket)x).close();
} else if (x instanceof DatagramSocket) {
((DatagramSocket)x).close();
} else {
Log.d("cannot close: "+x);
throw new RuntimeException("cannot close "+x);
}
} catch (Throwable e) {
Log.x(e);
}
}
}
}
}
回答by Balwinder SIngh
Process p;
StringBuffer output = new StringBuffer();
try {
p = Runtime.getRuntime().exec(params[0]);
BufferedReader reader = new BufferedReader(
new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine()) != null) {
output.append(line + "\n");
p.waitFor();
}
}
catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
String response = output.toString();
return response;