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

如何捕获adb pull与push命令的输出?

如何捕获adb pull与push命令的输出?

嗨,我之前也踩过这个坑!其实问题出在adb的pull和push命令的输出流上——它们默认会把进度提示、执行结果这些内容输出到标准错误流(stderr),而不是常规的标准输出流(stdout)。如果你之前只读取了stdout的话,自然抓不到任何内容啦。

给你两种可行的解决方案,按需选择:

方案一:合并stdout和stderr一起读取

这种方式最简单,用ProcessBuilder的redirectErrorStream(true)把两个流合并,这样只需要读取一次就能拿到所有输出:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class Main {
    private static void pullTest() {
        String strAdbPath = "/my/path/to/android/sdk/folder/platform-tools/adb";
        String strRemotePath = "/storage/sdcard0/Android/media/com.package.my/.";
        String strLocalPath = "./local_destination/"; // 记得补上本地目标路径

        try {
            // 用ProcessBuilder构建adb pull命令
            ProcessBuilder pb = new ProcessBuilder(strAdbPath, "pull", strRemotePath, strLocalPath);
            // 把stderr合并到stdout,这样可以统一读取
            pb.redirectErrorStream(true);
            Process process = pb.start();

            // 读取合并后的输出流
            InputStream inputStream = process.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println("ADB输出:" + line);
                // 这里可以把输出存入变量、写入日志或者做其他处理
            }

            // 等待命令执行完毕,获取退出码判断执行状态
            int exitCode = process.waitFor();
            System.out.println("命令执行完成,退出码:" + exitCode);

            // 关闭资源
            reader.close();
            inputStream.close();
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        pullTest();
    }
}

方案二:分开读取stdout和stderr

如果需要区分两种流的内容(比如把错误信息单独处理),可以开两个线程分别读取stdout和stderr,避免因为某一个流缓冲区满了导致进程阻塞:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
    private static void pullTest() {
        String strAdbPath = "/my/path/to/android/sdk/folder/platform-tools/adb";
        String strRemotePath = "/storage/sdcard0/Android/media/com.package.my/.";
        String strLocalPath = "./local_destination/";

        try {
            ProcessBuilder pb = new ProcessBuilder(strAdbPath, "pull", strRemotePath, strLocalPath);
            Process process = pb.start();

            // 单独读取stdout的线程
            new Thread(() -> {
                try (BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
                    String line;
                    while ((line = stdoutReader.readLine()) != null) {
                        System.out.println("标准输出:" + line);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }).start();

            // 单独读取stderr的线程(adb pull/push的输出主要在这里)
            new Thread(() -> {
                try (BufferedReader stderrReader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
                    String line;
                    while ((line = stderrReader.readLine()) != null) {
                        System.out.println("标准错误输出:" + line);
                        // 这里可以专门处理adb的进度、结果信息
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }).start();

            // 等待命令执行完成
            int exitCode = process.waitFor();
            System.out.println("命令执行完成,退出码:" + exitCode);

        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        pullTest();
    }
}

另外提醒一下,相比Runtime.exec(),用ProcessBuilder来创建进程会更灵活,还能设置工作目录、环境变量这些参数,推荐优先使用哦。

备注:内容来源于stack exchange,提问作者Luca

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 17:18:17