You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

安卓开发:如何实现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):

  • 实现步骤
    1. 在项目的build.gradle中添加库依赖
    2. UsbMassStorageDevice枚举已连接的大容量存储设备
    3. 调用setupDevice()挂载设备,获取FileSystem实例
    4. 通过FileSystem遍历OTG设备上的目录,打开目标文件的输入流
    5. 将输入流的数据写入安卓应用的内部存储(比如getFilesDir()getExternalFilesDir()
    6. 操作完成后调用teardown()释放资源,避免内存泄漏

路径2:用原生USB Host API手动实现(适合深入理解)

如果想要完全掌控USB通信逻辑,需要自行实现大容量存储设备的SCSI命令:

  1. 获取对应接口与端点
    • 遍历设备的UsbInterface实例,找到标记为INTERFACE_CLASS_MASS_STORAGE的接口
    • 从该接口中找到批量IN端点(用于读取OTG设备数据)和批量OUT端点(用于发送命令)
  2. 建立设备连接
    • UsbManager.openDevice(usbDevice)获取UsbDeviceConnection对象
    • 调用connection.claimInterface(usbInterface, true)获取接口使用权(注意:Android 6.0+需要先通过UsbManager.requestPermission()请求USB权限)
  3. 发送SCSI命令访问文件系统
    • 先发送INQUIRY命令确认设备身份
    • 再发送READ_CAPACITY命令获取存储容量
    • READ10命令读取磁盘扇区的原始数据,然后解析FAT32/NTFS等文件系统结构,定位目标文件(这部分是最复杂的,需要处理文件系统的元数据)
  4. 执行文件传输
    • 定位到目标文件的扇区数据后,通过批量IN端点读取原始字节
    • 打开安卓内部存储的输出流(比如new FileOutputStream(new File(getFilesDir(), "transferred_file.txt"))
    • 将读取到的字节写入输出流,建议用缓冲流提升传输效率

三、关键注意事项

  • 权限处理
    • USB权限:在操作设备前,务必通过UsbManager.requestPermission()请求设备访问权限
    • 存储权限:Android 10+写入应用私有目录(如getFilesDir())无需额外权限;若要写入公共存储,需使用存储访问框架(SAF)或申请MANAGE_EXTERNAL_STORAGE权限(Android 11+)
  • 资源清理:操作完成或设备断开时,调用releaseInterface()close()关闭UsbDeviceConnection,避免资源泄漏
  • 异常处理:USB通信和文件IO容易出错,要捕获UsbExceptionIOException等异常,并给用户清晰的反馈
  • 进度追踪:传输大文件时,建议实现进度回调,更新UI让用户了解传输状态

内容的提问来源于stack exchange,提问作者Sairamkrishna Mammahe

火山引擎 最新活动