从 Java 程序执行 ADB 命令
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20922600/
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 ADB command from Java program
提问by s3lph
The program I'm working on uses ADB (Android Debug Bridge) to send files to my phone:
我正在开发的程序使用 ADB(Android 调试桥)将文件发送到我的手机:
for (String s : files)
String cmd = "adb -s 0123456789ABCDEF push " + s + " /mnt/sdcard/" + s;
try {
InputStream is = Runtime.getRuntime().exec(cmd).getInputStream();
while (is.read() != -1) {}
} catch (IOException e) {
e.printStackTrace();
}
I want the program to wait until ADB finished the transmission, but ADB runs as a daemon and therefore never finishes. But the program continues immideately and somehow the files aren't sent to my phone (no exceptions in log). When I run the command from console, it's working without problems.
我希望程序等到 ADB 完成传输,但 ADB 作为守护进程运行,因此永远不会完成。但程序会立即继续,不知何故文件没有发送到我的手机(日志中没有例外)。当我从控制台运行命令时,它可以正常工作。
What am I doing wrong? How do I send files via ADB correctly?
我究竟做错了什么?如何正确通过 ADB 发送文件?
NOTE: the is.read() == -1
won't work, because the ADB daemon writes all outputto the system standard output. I've tried forwarding it into a textfile. It stayed empty and the output was still written to the terminal instead
注意:这is.read() == -1
不会起作用,因为 ADB 守护进程将所有输出写入系统标准输出。我试过将它转发到一个文本文件中。它保持为空,输出仍然写入终端
EDIT: Reading the ErrorStream of the ADB process returned the adb help for each adb push
-command. Again: The exactcommands (copied from Eclipse console) work in a terminal
编辑:读取 ADB 进程的 ErrorStream 返回每个adb push
-command的 adb 帮助。再次:确切的命令(从 Eclipse 控制台复制)在终端中工作
EDIT 2: Using a ProcessBuilder instead of RUntime.getRuntime.exec()
resulted in the following error:
编辑 2:使用 ProcessBuilder 而不是RUntime.getRuntime.exec()
导致以下错误:
java.io.IOException: Cannot run program "adb -s 0123456789ABCDEF push "inputfile "outputfile""": error=2, File or directory not found
at the ProcessBuilder's start()
-method
The same happens when using an absolute path for ADB (/usr/bin/adb
). The inputfile and outputfile Strings are also absolute paths, like /home/sebastian/testfile
and definitely exist. When running the commands from terminal (string "cmd" printed, copy&paste), evreything still works fine.
在 ProcessBuilder 的start()
-method 中使用 ADB ( /usr/bin/adb
)的绝对路径时也会发生同样的情况。inputfile 和 outputfile 字符串也是绝对路径,就像/home/sebastian/testfile
并且肯定存在。从终端运行命令(打印字符串“cmd”,复制和粘贴)时,evreything 仍然可以正常工作。
采纳答案by s3lph
I finally got it working:
我终于让它工作了:
ProcessBuilder pb = new ProcessBuilder("adb", "-s", "0123456789ABCDEF", "push", inputfile, outputfile);
Process pc = pb.start();
pc.waitFor();
System.out.println("Done");
I don't know what problems ProcessBuilder
has with spaces in a string, but finally, it's working...
我不知道ProcessBuilder
字符串中的空格有什么问题,但最后,它起作用了......
回答by Sarpe
I've solved in this way:
我是这样解决的:
public class Utils {
private static final String[] WIN_RUNTIME = { "cmd.exe", "/C" };
private static final String[] OS_LINUX_RUNTIME = { "/bin/bash", "-l", "-c" };
private Utils() {
}
private static <T> T[] concat(T[] first, T[] second) {
T[] result = Arrays.copyOf(first, first.length + second.length);
System.arraycopy(second, 0, result, first.length, second.length);
return result;
}
public static List<String> runProcess(boolean isWin, String... command) {
System.out.print("command to run: ");
for (String s : command) {
System.out.print(s);
}
System.out.print("\n");
String[] allCommand = null;
try {
if (isWin) {
allCommand = concat(WIN_RUNTIME, command);
} else {
allCommand = concat(OS_LINUX_RUNTIME, command);
}
ProcessBuilder pb = new ProcessBuilder(allCommand);
pb.redirectErrorStream(true);
Process p = pb.start();
p.waitFor();
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
String _temp = null;
List<String> line = new ArrayList<String>();
while ((_temp = in.readLine()) != null) {
System.out.println("temp line: " + _temp);
line.add(_temp);
}
System.out.println("result after command: " + line);
return line;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
If you don't need env variables in your .bash_profile cut "-l" parameter.
如果您的 .bash_profile 中不需要 env 变量,请剪切“-l”参数。
I have a Mac but it should work on Linux also.
我有一台 Mac,但它也可以在 Linux 上运行。
回答by Harish Gurubatham
public static void adbpush() {
System.out.println("adb push....");
String[] aCommand = new String[] { adbPath, "push", inputFile(String),OutputDirectory };
try {
// Process process = new ProcessBuilder(aCommand).start();
Process process = Runtime.getRuntime().exec(aCommand);
process.waitFor(3, TimeUnit.SECONDS);
System.out.println("file pushed");
} catch (Exception e) {
e.printStackTrace();
}
}
回答by Mukesh Rajput
It will be better to give full path for ADB execution: like this $ANDROID_HOME/platform-tools/adb devices
最好给出 ADB 执行的完整路径:像这样 $ANDROID_HOME/platform-tools/adb devices
This is the full code you can use:
这是您可以使用的完整代码:
String cmd = "$ANDROID_HOME/platform-tools/adb devices";
ProcessBuilder processBuilder = new ProcessBuilder();
if (Config.osName.contains("Windows"))
processBuilder.command("cmd.exe", "/c", cmd);
else
processBuilder.command("bash", "-c", cmd);
Process process = processBuilder.start();