简体   繁体   English

从 Java 程序执行 ADB 命令

[英]Execute ADB command from Java program

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.我希望程序等到 ADB 完成传输,但 ADB 作为守护进程运行,因此永远不会完成。 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.当我从控制台运行命令时,它可以正常工作。

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 output to the system standard output.注意: is.read() == -1将不起作用,因为 ADB 守护进程将所有输出写入系统标准输出。 I've tried forwarding it into a textfile.我试过将它转发到一个文本文件中。 It stayed empty and the output was still written to the terminal instead它保持为空,输出仍然写入终端

EDIT : Reading the ErrorStream of the ADB process returned the adb help for each adb push -command.编辑:读取 ADB 进程的 ErrorStream 返回了每个adb push命令的 adb 帮助。 Again: The exact commands (copied from Eclipse console) work in a terminal再次:确切的命令(从 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 ).在 ProcessBuilder 的start() -方法中使用 ADB 的绝对路径 ( /usr/bin/adb ) 时也会发生同样的情况。 The inputfile and outputfile Strings are also absolute paths, like /home/sebastian/testfile and definitely exist. inputfile 和 outputfile 字符串也是绝对路径,如/home/sebastian/testfile并且肯定存在。 When running the commands from terminal (string "cmd" printed, copy&paste), evreything still works fine.从终端运行命令(打印字符串“cmd”,复制和粘贴)时,evreything 仍然可以正常工作。

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对字符串中的空格有什么问题,但最后,它正在工作......

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 上运行。

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

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();
Process process = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(process.getOutputStream());
string cmd = "/system/bin/input keyevent 23\n";
os.writeBytes(cmd);

the phone must be rooted.手机必须root。 here I have executed adb command "input keyevent 23".在这里我执行了 adb 命令“input keyevent 23”。 remember when you execute adb command through su you does not need to add "adb shell input keyevent 23"请记住,当您通过 su 执行 adb 命令时,您不需要添加“adb shell input keyevent 23”

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM