关于安卓USB开发(一)文件复制,文件夹创建

背景

在安卓应用中,把某个文件,复制到插入的U盘中

开发环境

win10,jdk8+,as4+

测试机型

红米Note11,android13

源码问题

文末将会提供博主整合好的源码项目连接,以供学习交流

注意

本次实战,u盘格式是fat32,其他格式,测试过,并不支持。如果有更好的想法,开源库,可以留言探讨

开源库

libaums link

开始接入

首先第一步,就是一个大坑。国内的文章,一搜索,发现都是可以列入博物馆的了,实战起来的安卓系统版本,也是很低。最近这几年更新的文章,极少。

这里用到的,就是https://github.com/magnusja/libaums这个开源库。这个库最新的版本,是0.10.0,基于kotlin进行开发的,所以还在使用java的项目,就要引入java对kotlin的支持了。

(1)java项目引入kotlin支持

项目根部build.gradle文件,声明
classpath “org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.0”,如下图:
在这里插入图片描述
然后在开发模块build.gradle中,引入:

apply plugin: 'kotlin-android'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.0"

完成上述步骤后,java就支持kotlin了。

(2)开源库版本的引入方式

博主采用的,是把开源库下载到本地,编译以后,生成aar包,再去引入到开发模块中。
这里真实一波三折,先看三方库开源库的目录:
在这里插入图片描述
下载完以后,在本地运行,发现有很多报错,一一修改以后,才可以正常运行。

报错一

libusbcommunication依赖的libusb编译问题,导致编译失败

报错二

项目依赖的cmake环境,有些高版本的语法需要适配

报错三

主项目中,有些没有适配安卓目标版本的方法,运行的时候报错

以上就是大概的报错类型,处理完成后,才能进行引入

引入的方式,也有很多个,其中,这个开源库作者提供了两个思路:
(1)引入libaums这个库,这个库是比较通用的,但可能有些系统适配不了
(2)引入javafs这个库,这个库是基于libaums进行开发,适配了某些场景
但是通过博主的牺牲时间式引入以后,发现两个库,在我的redmi note 11,安卓13手机上,都不能在U盘创建目录,甚至创建文件也会失败。

因此,博主就开始去看这个库的issues了。

不看不知道,一看,的确有这种情况,而作者也是爱答不理,选择性回复。这就麻了。

最后,通过不断地推敲,查看issues,发现了一种新的引入方式,就是libusbcommunication,这个可不是本地引入的,是作者写好的一个远程库,引入方式如下:

    implementation("me.jahnen.libaums:libusbcommunication:0.3.0", {
        exclude group: "androidx.core", module: "core-ktx"
        exclude group: "androidx.core", module: "core"
        exclude group: "androidx.annotation", module: "annotation-experimental"
    })
    implementation("me.jahnen:java-fs:0.1.4")

这里其实引入的产物,和javafs模块是接近的,不过重要的是,内部可能做了某些处理,目前可以在手机上android13系统跑通,其他系统暂未测试!

上述的引入,对于exclude排除,按项目需要进行排除即可。

(3)开始编写

因为项目中,引入这个库的目的,是为了把文件复制到u盘,所以,这里博主直接封装了一个remote service进行处理,目的是为了不影响原有项目的进程。

而最核心的操作,无非就是一下几个。

(3-1)u盘插入监听,拔出监听

那这个功能实现,用广播即可,相关类:

UsbManager.ACTION_USB_DEVICE_ATTACHED
UsbManager.ACTION_USB_DEVICE_DETACHED
(3-2)u盘读写权限申请

使用USBManager的hasPermission方法,进行判断是否拥有读取该设备的权限,否则进行权限申请,申请的代码如下:

PendingIntent permissionIntent = PendingIntent.getBroadcast(mContext, 0,
                new Intent(USB_PERMISSION), PendingIntent.FLAG_MUTABLE);
getUsbManager().requestPermission(device, permissionIntent);

这里要注意的是,PendingIntent,在安卓高版本的flag。
其中,USB_PERMISSION是一个自定义广播,如果用户同意,系统则会回调该广播action,开发者只在广播接收类中,进行监听该action处理即可。
广播接收核心代码如下:
在这里插入图片描述
大概的意思,就是:
U盘插入–>权限申请
U盘拔出–>资源释放
授权成功–>连接U盘

(3-2)u盘连接

使用三方库提供的类:UsbMassStorageDevice进行设备获取,然后进行初始化,连接即可,示例代码如下:
在这里插入图片描述
可以看到有几个地方注意的:
(1)List是否为空,这个是用于获取操作文件的对象的,后续通过partition.getFileSystem()获取到操作对象进行操作。
(2)数据越界判断

通过上图中的连接操作以后,如无意外,则可以获取到UsbFileSystem操作对象了,如果获取不到,则需要根据设备,进行特定处理。

(3-2)u盘写操作

那么连接成功,又怎样进行写操作呢?
下面是相关的api:

UsbFile root = currentFs.getRootDirectory();

UsbFile[] files = root.listFiles();
for(UsbFile file: files) {
    Log.d(TAG, file.getName());
    if(!file.isDirectory()) {
        Log.d(TAG, file.getLength());
    }
}

UsbFile newDir = root.createDirectory("foo");
UsbFile file = newDir.createFile("bar.txt");

// write to a file
OutputStream os = new UsbFileOutputStream(file);

os.write("hello".getBytes());
os.close();

// read from a file
InputStream is = new UsbFileInputStream(file);
byte[] buffer = new byte[currentFs.getChunkSize()];
is.read(buffer);

详细的用法,可以参考开源库主页。
而对于某些设备,不能写入的情况,正如文章开头时所说的,通过引入方式的切换,进行尝试吧!

有更好的想法,欢迎评论区留言

源码地址链接:https://pan.baidu.com/s/1fpg1ZbboNxMK74dyf_783Q
提取码:r8k9
在这里插入图片描述
that’s all-----------------------------------------------------------------------------

  • 9
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值