Android App 与 U 盘通信示例详解
前言
对于U盘的了解,相信大多数人应该只停留在跟U盘跟电脑通信的阶段,其实现在通过OTG线就可以实现手机跟U盘之间的数据操作,不仅可以将U盘中的文件读取到手机中来,还能将手机中的文件导出到U盘中,从而实现手机与U盘之间的通信。本文将从AndroidApp入手,通过相关的代码,带大家一步步了解手机与U盘之间的通信。代码我已经放上Github了,有需要的点击这里。
一、自定义广播接收器接收U盘相关的信息
在U盘插入或插出的时候,系统都会发出一条相关的广播,所以我们需要自定义广播接收器,接收这两条广播,然后进行相应的处理。
publicclassOtgReceiverextendsBroadcastReceiver{
@Override
publicvoidonReceive(Contextcontext,Intentintent){
Stringaction=intent.getAction();
switch(action){
//接收到U盘插入广播
caseUsbManager.ACTION_USB_DEVICE_ATTACHED:
showToast(context,"U盘已插入");
//获取相关的Usb设备
UsbDeviceattachUsbDevice=intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if(attachUsbDevice!=null){
//进行权限申请
permissionRequest();
}
break;
//接收到U盘拔出广播
caseUsbManager.ACTION_USB_DEVICE_DETACHED:
showToast(context,"U盘已拔出");
break;
default:
break;
}
}
}
因为Usb相关的设备操作,需要申请相关的权限,所以在接收到U盘插入的广播之后,我们需要进行权限申请。
privatevoidpermissionRequest(){
//设备管理器
UsbManagerusbManager=(UsbManager)MainActivity.getContext().get().getSystemService(Context.USB_SERVICE);
//获取U盘存储设备
UsbMassStorageDevice[]storageDevices=UsbMassStorageDevice.getMassStorageDevices(OtgApplication.getContext());
PendingIntentpendingIntent=PendingIntent.getBroadcast(OtgApplication.getContext(),0,newIntent(ACTION_USB_PERMISSION),0);
//进行权限申请
usbManager.requestPermission(device.getUsbDevice(),pendingIntent);
}
可以看到我们在申请权限的时候,传入了一个PendingIntent,PendingIntent里面传入我们自定义的广播ACTION_USB_PERMISSION,等到权限申请完成,便会发出这条广播,然后我们可以在广播接收器中接收并处理,从而进行后续的操作。
caseACTION_USB_PERMISSION:
UsbDeviceusbDevice=intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if(intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED,false)){
if(usbDevice!=null){
//读取U盘相关的信息
readDevice(getUsbMass(usbDevice));
}else{
showToast(context,"没有插入U盘");
}
}else{
showToast(context,"未获取到U盘权限");
}
break;
为了简化相关的代码,我导入Github上开源的libaums,所以需要在build.gradle里面加上
compile'com.github.mjdev:libaums:0.5.5'
通过接收我们自定义的广播,便可以从Intent里面获取相应的包含U盘信息的UsbDevice
privatevoidreadDevice(UsbMassStorageDevicedevice){
device.init();
//设备分区
Partitionpartition=device.getPartitions().get(0);
//文件系统
FileSystemcurrentFs=partition.getFileSystem();
//获取U盘的根目录
mRootFolder=currentFs.getRootDirectory();
//获取U盘的容量
longcapacity=currentFs.getCapacity();
//获取U盘的剩余容量
longfreeSpace=currentFs.getFreeSpace();
//获取U盘的标识
StringvolumeLabel=currentFs.getVolumeLabel();
}
二、将文件导入到U盘中
通常我们将手机跟U盘通过OTG线进行连接,都是为了将手机里面的文件导入到U盘中,我们就以图片为例子,看看怎样将图片导出到U盘中。
将图片导出到U盘中,我们可以通过流来实现,先在U盘对应的目录,创建新的jpg/png格式的文件,然后通过BitmapFactory将图片转换成Bitmap,再进一步拿到对应图片的ByteArrayOutputStream,最后将对应的字节写入文件中。
publicstaticvoidsavePictureToUsb(StringpicturePath,UsbFileroot){
UsbFilenewDir=root.createDirectory("Haoz"+System.currentTimeMillis());
UsbFilefile=newDir.createFile("Haoz"+System.currentTimeMillis()+".jpg");
Bitmapbitmap=BitmapFactory.decodeFile(picturePath);
OutputStreamoutputStream=newUsbFileOutputStream(file);
ByteArrayOutputStreamout=newByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG,100,out);
outputStream.write(out.toByteArray());
outputStream.flush();
outputStream.close();
file.flush();
file.close();
}
可以看到我们传入图片的路径以及U盘的根目录,便可以将图片写入到U盘中,在上一节中,我们已经通过广播拿到U盘的根目录,所以直接用就行了。将文件从U盘中导入到手机中,其实思路也是一样的。毕竟当U盘插入手机的那一刻,将U盘当成手机的一个普通的目录来处理就行了。
三、该注意的地方
虽然说,U盘跟手机之间的通信相对来说不是很难,但其实也有很多需要注意的地方,也是笔者在开发过程中踩过的坑,这里都记录出来,供大家参考。
3.1获取图片的路径
我们通过图片选择库或者照相机回调出来的,很多时候都是图片的Uri,而要得到图片对应的Bitmap需要的是图片的真实路径,我们可以通过以下方法进行转换。
publicstaticStringgetPath(ContentResolverresolver,Uriuri){
if(uri==null){
returnnull;
}
if(SCHEME_CONTENT.equals(uri.getScheme())){
Cursorcursor=null;
try{
cursor=resolver.query(uri,newString[]{MediaStore.Images.ImageColumns.DATA},
null,null,null);
if(cursor==null||!cursor.moveToFirst()){
returnnull;
}
returncursor.getString(cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA));
}finally{
if(cursor!=null){
cursor.close();
}
}
}
returnuri.getPath();
}
3.2文件相关的读写操作
文件相关的读写操作都是比较耗时的,特别是当文件比较大的时候。所以我们不能在主线程中进行文件的读写,必须将其放在子线程中,等I/O操作完成了,再转换到主线程中进行操作。
3.3广播的注册与移除
因为我们是自定义广播接收器来接收相应的广播,所以需要在Activity中进行广播的动态注册,将对应Action进行过滤。最后不要忘记了在onDestroy()中移除广播,防止内存泄露。
privatevoidregisterUDiskReceiver(){
IntentFilterusbDeviceFileter=newIntentFilter();
usbDeviceFileter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
usbDeviceFileter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
usbDeviceFileter.addAction(Intent.ACTION_MEDIA_MOUNTED);
registerReceiver(mOtgReceiver,usbDeviceFileter);
//注册监听自定义广播
IntentFilterfilter=newIntentFilter(OtgReceiver.ACTION_USB_PERMISSION);
registerReceiver(mOtgReceiver,filter);
}
@Override
protectedvoidonDestroy(){
super.onDestroy();
unregisterReceiver(mOtgReceiver);
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。