You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mac OS下Java程序化执行Android设备ADB命令失败求助

我之前也踩过这个坑!问题核心出在**shell重定向符号>**的处理逻辑上:当你在终端手动执行命令时,是系统的shell(Mac上默认是zsh/sh)帮你解析了>,把adb的输出重定向到指定文件;但Java的Runtime.exec()直接调用的是adb进程,它会把>和后面的路径当成adb的命令参数,而不是交给shell处理,自然就不会生成你想要的文件了,而且因为没有语法错误,所以也不会抛出异常。

下面给你两种靠谱的解决方案,按需选择:

方案1:通过Shell执行完整命令

直接让Mac的shell来处理整个命令,用/bin/sh -c(或/bin/zsh -c,取决于你的默认shell)把完整命令包裹起来,并且用字符串数组传递参数(避免空格等特殊字符导致的拆分问题):

// 保存截图到Mac本地
Process process = Runtime.getRuntime().exec(new String[]{
    "/bin/sh", 
    "-c", 
    "adb exec-out screencap -p > /Users/dmytro/Documents/other/1.png"
});
// 等待命令执行完成,还可以检查退出码排查问题
int exitCode = process.waitFor();
if (exitCode != 0) {
    BufferedReader errReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
    String line;
    while ((line = errReader.readLine()) != null) {
        System.err.println("执行错误:" + line);
    }
}

同样的逻辑可以套用到其他adb命令上:

// 保存logcat到本地文件
Runtime.getRuntime().exec(new String[]{
    "/bin/sh", 
    "-c", 
    "adb logcat > /Users/dmytromynziak/Documents/other/log.txt"
});

// 保存截图到Android设备存储
Runtime.getRuntime().exec(new String[]{
    "/bin/sh", 
    "-c", 
    "adb exec-out screencap -p > /sdcard/1.png"
});

方案2:手动处理输入输出流(跨平台更可控)

如果你不想依赖系统shell,也可以自己读取adb的输出流,再写入到目标文件——这种方式在Windows和Mac上都能正常工作,还能更灵活地控制输出内容:

比如保存截图到Mac本地:

Process process = Runtime.getRuntime().exec("adb exec-out screencap -p");
InputStream inputStream = process.getInputStream();
FileOutputStream outputStream = new FileOutputStream("/Users/dmytro/Documents/other/1.png");

// 逐块读取输出并写入文件
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
    outputStream.write(buffer, 0, bytesRead);
}

// 记得关闭资源
inputStream.close();
outputStream.close();
process.waitFor();

对于logcat这种持续输出的命令,建议开一个单独线程来读取:

Process process = Runtime.getRuntime().exec("adb logcat");
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
FileWriter writer = new FileWriter("/Users/dmytromynziak/Documents/other/log.txt");

// 启动线程异步读取logcat输出
new Thread(() -> {
    String line;
    try {
        while ((line = reader.readLine()) != null) {
            writer.write(line + "\n");
            writer.flush(); // 确保内容实时写入文件
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            reader.close();
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}).start();

// 需要停止logcat时,调用process.destroy();

额外小建议:优先用ProcessBuilder替代Runtime.exec

ProcessBuilder比Runtime.exec更强大,能更方便地设置工作目录、环境变量,也更容易管理进程的输入输出,推荐你后续开发中使用:

ProcessBuilder pb = new ProcessBuilder("/bin/sh", "-c", "adb exec-out screencap -p > /Users/dmytro/Documents/other/1.png");
// 可选:设置命令执行的工作目录
// pb.directory(new File("/Users/dmytro/Documents/other"));
Process process = pb.start();
int exitCode = process.waitFor();
// 处理执行结果...

内容的提问来源于stack exchange,提问作者dmytro Minz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:41:26