如何编写Java standalone程序读取Android设备文件并存至Windows主机
Java实现Android设备文件拉取到Windows主机的可行方案
目前能稳定跑通、兼容绝大多数安卓版本的实现路径是基于安卓原生ADB调试能力做对接,不要自己从零实现传输协议,踩坑率极高。下面分两种实现路径给你参考:
方案1:调用ADB进程实现(开发成本最低,优先选这个)
这个方案最快1天就能写完稳定可用的版本,不需要啃复杂的协议文档,兼容性拉满。
- 前置准备:从官方Android SDK Platform-Tools包里取出
adb.exe、AdbWinApi.dll、AdbWinUsbApi.dll三个文件,打包进你的Java程序资源目录,运行时释放到系统临时目录调用即可,不需要用户手动安装任何安卓开发相关工具。 - 核心实现步骤:
- 程序启动后先执行
adb start-server拉起ADB服务,再执行adb devices枚举当前已连接的设备(同时支持USB线连、同一局域网下的无线调试连接) - 检测到设备在线后,直接执行
adb pull <安卓端文件绝对路径> <Windows本地保存路径>完成文件传输 - 读取ADB进程的输出流、错误流,判断传输是否成功,处理文件不存在、权限不足、设备断连等异常
- 程序启动后先执行
- 核心代码参考:
import java.io.IOException; import java.nio.charset.StandardCharsets; public class AdbFileTransfer { /** * 从安卓设备拉取文件到本地 * @param adbPath 临时目录下的adb.exe绝对路径 * @param deviceRemotePath 安卓设备上的文件绝对路径,比如/sdcard/DCIM/test.jpg * @param windowsLocalPath Windows本地保存路径,比如D:/backup/test.jpg * @return 传输是否成功 */ public static boolean pullFile(String adbPath, String deviceRemotePath, String windowsLocalPath) throws IOException, InterruptedException { ProcessBuilder pb = new ProcessBuilder(adbPath, "pull", deviceRemotePath, windowsLocalPath); pb.redirectErrorStream(true); Process process = pb.start(); // 读取执行输出 String output = new String(process.getInputStream().readAllBytes(), StandardCharsets.UTF_8); int exitCode = process.waitFor(); // adb执行成功返回码为0,输出包含pulled字段代表文件拉取完成 return exitCode == 0 && output.contains("pulled"); } }
- 适配注意点:
- 安卓11及以上版本拉取应用私有目录(比如
/data/data/xxx)的文件,需要先引导用户在开发者选项里开启USB调试、授予文件相关权限,部分设备需要执行adb root拿到权限后才能访问系统目录 - 用无线调试连接时,安卓10及以下版本可以直接在同一局域网下执行
adb connect 设备IP:5555连接;安卓11及以上版本需要先通过配对码执行adb pair 设备IP:配对端口完成鉴权,再走connect逻辑连接
- 安卓11及以上版本拉取应用私有目录(比如
方案2:集成纯Java ADB协议库(无外部exe依赖)
如果你的程序不允许拉起外部进程、对包体积有严格要求,可以选纯Java实现的ADB协议库,直接通过代码和安卓设备的adbd守护进程通信,不需要自带adb.exe相关文件。
- 核心逻辑:自己实现ADB协议的握手、RSA鉴权、Sync指令传输逻辑,建立连接后逐块读取安卓端的文件流,写入Windows本地文件即可。
- 缺点:需要自己处理协议兼容、异常重连逻辑,开发调试成本比直接调用ADB进程高很多,适合有定制化需求的场景。
避坑提醒
- 别尝试对接MTP协议实现传输:不同厂商对MTP的魔改非常多,实际用起来经常出现文件列表枚举不全、大文件传输中断、中文文件名乱码的问题,根本做不到全机型稳定兼容
- 别要求用户在安卓端安装配套APK:会大幅提升使用门槛,ADB是安卓系统原生支持的调试能力,用户只需要开一下USB调试就能用,接受度高很多
- 传大文件的时候记得解析ADB输出的进度信息,给用户展示实时传输进度,不要阻塞主线程避免程序假死
内容的提问来源于stack exchange,提问作者Sanjeevan
相关产品推荐
相关产品推荐

