安卓开发:如何实现USB OTG至内部存储的文件传输?
实现USB OTG文件传输至安卓内部存储的思路
Nice work getting the USB Host detection up and running! Moving files from your OTG device to Android's internal storage is totally achievable—here's a straightforward breakdown of how to make it happen:
一、首先:验证目标设备类型
既然你已经能获取设备的类别、子类等信息,第一步要确认连接的OTG设备是大容量存储设备:
- 检查
usbDevice.getDeviceClass()是否返回UsbConstants.USB_CLASS_MASS_STORAGE - 进一步验证子类是否为
UsbConstants.USB_SUBCLASS_SCSI_TRANSPARENT(这是U盘、移动硬盘等设备的标准子类)
二、选择实现路径
你有两种靠谱的方案可选,按需挑选即可:
路径1:借助第三方库快速实现(推荐)
跳过底层USB协议的复杂逻辑,用成熟的开源库直接搞定。最常用的是libaums(Android USB Mass Storage Library):
- 实现步骤:
- 在项目的build.gradle中添加库依赖
- 用
UsbMassStorageDevice枚举已连接的大容量存储设备 - 调用
setupDevice()挂载设备,获取FileSystem实例 - 通过
FileSystem遍历OTG设备上的目录,打开目标文件的输入流 - 将输入流的数据写入安卓应用的内部存储(比如
getFilesDir()或getExternalFilesDir()) - 操作完成后调用
teardown()释放资源,避免内存泄漏
路径2:用原生USB Host API手动实现(适合深入理解)
如果想要完全掌控USB通信逻辑,需要自行实现大容量存储设备的SCSI命令:
- 获取对应接口与端点
- 遍历设备的
UsbInterface实例,找到标记为INTERFACE_CLASS_MASS_STORAGE的接口 - 从该接口中找到批量IN端点(用于读取OTG设备数据)和批量OUT端点(用于发送命令)
- 遍历设备的
- 建立设备连接
- 用
UsbManager.openDevice(usbDevice)获取UsbDeviceConnection对象 - 调用
connection.claimInterface(usbInterface, true)获取接口使用权(注意:Android 6.0+需要先通过UsbManager.requestPermission()请求USB权限)
- 用
- 发送SCSI命令访问文件系统
- 先发送
INQUIRY命令确认设备身份 - 再发送
READ_CAPACITY命令获取存储容量 - 用
READ10命令读取磁盘扇区的原始数据,然后解析FAT32/NTFS等文件系统结构,定位目标文件(这部分是最复杂的,需要处理文件系统的元数据)
- 先发送
- 执行文件传输
- 定位到目标文件的扇区数据后,通过批量IN端点读取原始字节
- 打开安卓内部存储的输出流(比如
new FileOutputStream(new File(getFilesDir(), "transferred_file.txt"))) - 将读取到的字节写入输出流,建议用缓冲流提升传输效率
三、关键注意事项
- 权限处理:
- USB权限:在操作设备前,务必通过
UsbManager.requestPermission()请求设备访问权限 - 存储权限:Android 10+写入应用私有目录(如
getFilesDir())无需额外权限;若要写入公共存储,需使用存储访问框架(SAF)或申请MANAGE_EXTERNAL_STORAGE权限(Android 11+)
- USB权限:在操作设备前,务必通过
- 资源清理:操作完成或设备断开时,调用
releaseInterface()和close()关闭UsbDeviceConnection,避免资源泄漏 - 异常处理:USB通信和文件IO容易出错,要捕获
UsbException、IOException等异常,并给用户清晰的反馈 - 进度追踪:传输大文件时,建议实现进度回调,更新UI让用户了解传输状态
内容的提问来源于stack exchange,提问作者Sairamkrishna Mammahe




