Android OTG 读写U盘文件

news/2024/11/7 22:35:07/

最近项目需要做一个关于OTG的功能,其实也就使用到U盘的文件读取,一般这种需求是不需要的,因为大部分的系统都会自动挂载U盘,但是个别系统还是需要自己去实现,查了很多资料都没有找到一个完整的能用的例子,要么就是年代偏远,好不容易运行起来跑不了,或者没效果,这个过程是很烦的,google了一下后,发现了一个开源的文件管理器,但是该管理器在使用的时候却出现了OTG无法读取的问题,详细的话可以自己去看看 GitHub - 1hakr/AnExplorer: 📁 Another Android Explorer ( File Manager ) is an All-in-One Open source file manager. AnExplorer File Manager (File Explorer) is designed for all android devices including Phones, Phablets, Tablets, Chromecast, Wear OS, Android TV and Chromebooks. It's a fully designed with Material guidelines by Google.,我是去看源码它的USB实现过程中从中提取了一部分东西,再结合看的其他博客,总算能实现读写的效果。
阅读之前,可先看一下这几篇文章了解一些概念:

android-USB-OTG 外部设备通讯 USB插拔检测

Android实战技巧之四十九:Usb通信之USB Host

https://developer.android.com/guide/topics/connectivity/usb/host.html

    好吧,其实看了也只是有个大概的了解,要想实现其实还是差了点,特别是获取U盘目录什么的简直不知道该怎么下手,废话不多说,看一下个人实现,如果你有更好的实现,欢迎留言讨论。

    首先,肯定需要获取读取OTG和文件权限,在manifest.xml中加入以下权限

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.hardware.usb.host" android:required="false" />

    然后,部分手机上是没有otg的所以需要加入特性。

 <uses-feature android:name="android.hardware.usb.host" android:required="true" /> 

    有了权限后,就可以开始编码了。

    第一步,注册广播,监听otg插拔事件。

//监听otg插入 拔出
IntentFilter usbDeviceStateFilter = new IntentFilter();
usbDeviceStateFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
usbDeviceStateFilter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
//注册监听自定义广播
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(mUsbReceiver, filter);

    ACTION_USB_PERMISSION是定义的一个权限字段

private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";

    接上

    //otg插入 拔出广播getActivity().registerReceiver(mUsbReceiver, usbDeviceStateFilter);//这里我用的碎片registerReceiver(mUsbReceiver, usbDeviceStateFilter);//这里我用的碎片//mUsbReceiver只是一个普通的广播,根据action,去分别处理对应的事件。private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {public void onReceive(Context context, Intent intent) {String action = intent.getAction();switch (action) {case ACTION_USB_PERMISSION://接受到自定义广播synchronized (this) {UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { //允许权限申请if (usbDevice != null) {//Do something}} else {TShow("用户未授权,读取失败");}}break;case UsbManager.ACTION_USB_DEVICE_ATTACHED://接收到存储设备插入广播UsbDevice device_add = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);if (device_add != null) {TShow("接收到存储设备插入广播");}break;case UsbManager.ACTION_USB_DEVICE_DETACHED://接收到存储设备拔出广播UsbDevice device_remove = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);if (device_remove != null) {TShow("接收到存储设备拔出广播");//拔出或者碎片 Activity销毁时 释放引用//device.close();}break;}}};

    TShow()是我个人的Toast消息封装,上述中的广播每一个都可以获取到usb设备的实体信息类,可以根据个人逻辑处理。

    第二步,枚举设备

        //获取管理者UsbManager usbManager = (UsbManager) getContext().getSystemService(Context.USB_SERVICE);//枚举设备UsbMassStorageDevice[] storageDevices = UsbMassStorageDevice.getMassStorageDevices(getContext());//获取存储设备PendingIntent pendingIntent = PendingIntent.getBroadcast(getActivity(), 0, new Intent(ACTION_USB_PERMISSION), 0);for (UsbMassStorageDevice device : storageDevices) {//可能有几个 一般只有一个 因为大部分手机只有1个otg插口if (usbManager.hasPermission(device.getUsbDevice())) {//有就直接读取设备是否有权限read(device);} else {//没有就去发起意图申请usbManager.requestPermission(device.getUsbDevice(), pendingIntent); //该代码执行后,系统弹出一个对话框,}}

    申请意图执行后,会进入上面的广播中,然后,在需要处理的地方去执行读取操作。

    第三步,读取U盘信息

    这里需要说明一下,UsbMassStorageDevice这个类来自开源库,里面包含了一些获取大容量存储设备的操作和其他封装。可以在Gradle中加入依赖:

        compile 'com.github.mjdev:libaums:+'

该库GitHub地址:https://github.com/magnusja/libaums#using-buffered-streams-for-more-efficency

    read(device);的详细代码:

private void read(UsbMassStorageDevice massDevice) {// before interacting with a device you need to call init()!try {massDevice.init();//初始化//Only uses the first partition on the devicePartition partition = massDevice.getPartitions().get(0);FileSystem currentFs = partition.getFileSystem();//fileSystem.getVolumeLabel()可以获取到设备的标识//通过FileSystem可以获取当前U盘的一些存储信息,包括剩余空间大小,容量等等Log.d(TAG, "Capacity: " + currentFs.getCapacity());Log.d(TAG, "Occupied Space: " + currentFs.getOccupiedSpace());Log.d(TAG, "Free Space: " + currentFs.getFreeSpace());Log.d(TAG, "Chunk size: " + currentFs.getChunkSize());UsbFile root = currentFs.getRootDirectory();} catch (Exception e) {e.printStackTrace();TShow("读取失败");}}

    到这里就已经可以获取到U盘根目录的实体类UsbFile了 

    UsbFile的部分函数:

listFiles();//该函数可以获取到某个目录下所有的文件boolean isDirectory();//判断是否是目录void setName(String newName) throws IOException//给目录或文件设置名称String getName();//获取该文件或目录的名称UsbFile getParent();//该函数可以获取父类对象,比如根目录是root,它有个子目录music,那么通过music的UsbFile对象可以获取到root的文件和目录列表,也就解决了获取上一级目录文件的问题。    long getLength();//如果是个文件,可以获取到文件大小void read(long offset, ByteBuffer destination) throws IOException;//文件读取操作void write(long offset, ByteBuffer source) throws IOException;//文件写入操作UsbFile createDirectory(String name) throws IOException;//如果是个目录,那么会在该目录下创建一个新的目录UsbFile createFile(String name) throws IOException;//如果该目录存在,会在该目录下生成一个新的文件void delete() throws IOException;//文件和目录删除操作boolean isRoot();//当前目录是否是根目录

    常用的函数就这几个,基本上包括了U盘文件的增删改查,如果说需要一个File的对象,那么可以通过流的形式进行先保存到本地再获取。因为File对象指向了一个具体的uri地址,也就是说,必须要有能访问的具体路径,比如内置存储和sd卡的目录。

    具体步骤:先创建一个具体的文件,然后以io形式进行文件写入,相当于复制,io完成后即可获取File对象

    如下:       

 new Thread(new Runnable() {@Overridepublic void run() {try {FileOutputStream os = new FileOutputStream(tempFile);InputStream is = new UsbFileInputStream(usbFile);int bytesRead = 0;byte[] buffer = new byte[1024 * 8];//作者的推荐写法是currentFs.getChunkSize()为buffer长度while ((bytesRead = is.read(buffer)) != -1) {os.write(buffer, 0, bytesRead);}os.flush();os.close();is.close();//Do something} catch (Exception e) {e.printStackTrace();}}}).start();

    好了,基本上整个流程就是这样的,由于百度账户注销了,所以源码没了,但是只要看懂了这个流程基本上就没什么问题了。


http://www.ppmy.cn/news/762522.html

相关文章

USB OTG连接方式

1. 概要 OTG设备使用插头中的ID引脚来区分A/B Device&#xff0c;ID接地被称作为A-Device,充当USB Host&#xff0c;A-Device始终为总线 提供电力&#xff0c;ID悬空被称作为B-Device,充当USB Device&#xff0c;设备的USB Host/USB Device角色可以通过HNP(主机交换 协议)切换。…

otg接口形式

&#xff08;1&#xff09;USB &#xff08;2&#xff09;Mini USB USB设备分为三种&#xff1a;HOST&#xff0c;OTG&#xff0c;DEVICE。其中ID脚在OTG功能中才使用。 A&#xff0c;如果你的系统自己仅仅是用做Slave&#xff0c;那么就使用B接口。任何时候都悬空&#xff0c;…

USB OTG原理简述

USB OTG即USB On-The-Go的缩写&#xff0c;他目的是实现在没有Host的情况下&#xff0c;实现设备间的数据传送。例如数码相机直接连接到打印机上&#xff0c;通过OTG技术&#xff0c;连接两台设备间的USB口&#xff0c;将拍出的相片立即打印出来&#xff1b;手机读写U盘。 OTG…

USB OTG原理简述实际的USB连接线中,是没有USB_ID这根线的。 都是在接口部分直接拉死的。两用OTG设备都有一个Mini-AB插槽,所以一个Mini-A至Mini-B电缆可以直接将两个连接

USB OTG即USB On-The-Go的缩写&#xff0c;他目的是实现在没有Host的情况下&#xff0c;实现设备间的数据传送。例如数码相机直接连接到打印机上&#xff0c;通过OTG技术&#xff0c;连接两台设备间的USB口&#xff0c;将拍出的相片立即打印出来&#xff1b;手机读写U盘。 OTG …

USB HOST与 USB OTG的区别及工作原理

在SmartQ 7上面,同时存在USB HOST与 USB OTG两个接口,我想问一下,这两个接口有什么区别么?我怎么认为HOST属于是多余呢? 麻烦高手解答,感激不尽!!! 零 USB背景知识 USB是一种数据通信方式&#xff0c;也是一种数据总线&#xff0c;而且是最复杂的总线之一。 硬件上&#xf…

android OTG (USB读写,U盘读写)最全使用相关总结

androidOTG (USB读写&#xff0c;U盘读写) 最全使用相关总结 简介第一种读取方法:android推荐使用的通过endpoint的形式进行通信第二种读取方法:像读你sdcard的形式来读你的U盘设备注意注意注意 提示 博主&#xff1a;来自火星的萨满_906285288 博客地址&#xff1a; https://…

android OTG

关键词&#xff1a;android 4.0 USB OTG 键盘 鼠标 device u盘 平台信息: 内核&#xff1a;linux3.0 系统&#xff1a;android4.0.3 平台&#xff1a;S5PV310(samsung exynos 4210) 把这一段时间的工作内容记录下 一、OTG的概念 OTG是On-The-Go的缩写&#xff0c;是近年…

小知识·OTG工作原理

目录 OTG是什么 一、OTG的历史 二、OTG的原理 1.设计原理 2.相关原理 三、OTG的功能 四、如何使用OTG功能&#xff1f; 三、OTG工作原理 1 新的协议 1.1 事务请求协议SRP 1.2 主机流通协议HNP 2 连接器和电缆 2.1 连接器 2.2 电缆 3 USB On-The-Go设备类…