如何捕获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
相关产品推荐
相关产品推荐

