从Java程序执行ADB命令

时间:2014-01-04 15:07:07

标签: java process adb

我正在处理的程序使用ADB(Android Debug Bridge)将文件发送到我的手机:

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();
    }

我希望程序等到ADB完成传输,但ADB作为守护进程运行,因此永远不会完成。但该程序仍在继续,不知何故文件没有发送到我的手机(日志中没有例外)。当我从控制台运行命令时,它没有问题。

我做错了什么?如何通过ADB正确发送文件?

注意:is.read() == -1将不起作用,因为ADB守护程序将所有输出写入系统标准输出。我已经尝试将其转发到文本文件中。它保持空白,输出仍然写入终端

编辑:读取ADB流程的ErrorStream会返回每个adb push命令的adb帮助。再次:完全命令(从Eclipse控制台复制)在终端中工作

编辑2 :使用ProcessBuilder而不是RUntime.getRuntime.exec()会导致以下错误:

java.io.IOException: Cannot run program "adb -s 0123456789ABCDEF push "inputfile "outputfile""": error=2, File or directory not found

在ProcessBuilder的start()方法中 使用ADB的绝对路径(/usr/bin/adb)时也会发生同样的情况。 inputfile和outputfile字符串也是绝对路径,如/home/sebastian/testfile并且肯定存在。当从终端运行命令时(字符串“cmd”打印,复制和粘贴),evreything仍然可以正常工作。

4 个答案:

答案 0 :(得分:10)

我已经用这种方式解决了:

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;
        }
    }
}

如果您不想在.bash_profile cut&#34; -l&#34;中使用env变量。参数。

我有一台Mac,但它也适用于Linux。

答案 1 :(得分:8)

我终于明白了:

ProcessBuilder pb = new ProcessBuilder("adb", "-s", "0123456789ABCDEF", "push", inputfile, outputfile);
Process pc = pb.start();
pc.waitFor();
System.out.println("Done");

我不知道ProcessBuilder对字符串中的空格有什么问题,但最后,它正在工作......

答案 2 :(得分:0)

 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();
        }
    }

答案 3 :(得分:0)

最好提供完整的ADB执行路径:像这样$ANDROID_HOME/platform-tools/adb devices

这是您可以使用的完整代码:

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();