Android设备与外接U盘实现数据读取操作的示例

作者:迟做总比不做强 时间:2023-06-18 13:35:00 

现在越来越多手机支持OTG功能,通过OTG可以实现与外接入的U盘等USB设备实现数据传输。

 USB OTG(On The Go)作为USB2.0的补充协议,于2001年由USB-IF提出。它提出的背景是移动消费类电子产品的迅猛增加,而之前USB协议的主从协议标准让这些电子产品在离开PC电脑时的数据传输变得艰难,OTG技术正是为了解决这一问题的标准。

Android设备与外接U盘实现数据读取操作的示例

通过OTG技术实现设备间端到端互联

OTG协议规定连接时默认情况作为Host的设备为A设备,A设备负责为总线供电;默认作为Device的设备为B设备(USB OTG标准在完全兼容USB2.0标准的基础上,增加了一个ID pin;ID拉低为默认A设备);而有些设备由于集成了Host控制器和Device控制器,既可以作A设备又可以做B设备,称为dura-role device。

最近项目上用到了该功能,项目上用的是安卓7.1的盒子,要实现与插入的U盘进行数据操作。通过大量的找资料,终于实现了项目上需要的功能。找资料主要是解决两个问题:

  1. U盘权限问题

  2. U盘文件路径及文件操作

废话不多说,感觉还是喜欢直接上代码才爽快。项目中用到了一个开源框架,开源地址是:
https://github.com/magnusja/libaums。

代码部分:


public class MainActivity extends AppCompatActivity implements View.OnClickListener {
 //输入的内容
 private EditText u_disk_edt;
 //写入到U盘
 private Button u_disk_write;
 //从U盘读取
 private Button u_disk_read;
 //显示读取的内容
 private TextView u_disk_show;
 //自定义U盘读写权限
 private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
 //当前处接U盘列表
 private UsbMassStorageDevice[] storageDevices;
 //当前U盘所在文件目录
 private UsbFile cFolder;
 private final static String U_DISK_FILE_NAME = "u_disk.txt";
 private Handler mHandler = new Handler() {
   @Override
   public void handleMessage(Message msg) {
     switch (msg.what) {
       case 100:
         showToastMsg("保存成功");
         break;
       case 101:
         String txt = msg.obj.toString();
         if (!TextUtils.isEmpty(txt))
           u_disk_show.setText("读取到的数据是:" + txt);
         break;
     }
   }
 };

@Override
 protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_main);
   initViews();
 }

private void initViews() {
   u_disk_edt = (EditText) findViewById(R.id.u_disk_edt);
   u_disk_write = (Button) findViewById(R.id.u_disk_write);
   u_disk_read = (Button) findViewById(R.id.u_disk_read);
   u_disk_show = (TextView) findViewById(R.id.u_disk_show);
   u_disk_write.setOnClickListener(this);
   u_disk_read.setOnClickListener(this);
 }

@Override
 public void onClick(View view) {
   switch (view.getId()) {
     case R.id.u_disk_write:
       final String content = u_disk_edt.getText().toString().trim();
       mHandler.post(new Runnable() {
         @Override
         public void run() {
           saveText2UDisk(content);
         }
       });

break;
     case R.id.u_disk_read:
       mHandler.post(new Runnable() {
         @Override
         public void run() {
           readFromUDisk();
         }
       });

break;
   }
 }

private void readFromUDisk() {
   UsbFile[] usbFiles = new UsbFile[0];
   try {
     usbFiles = cFolder.listFiles();
   } catch (IOException e) {
     e.printStackTrace();
   }
   if (null != usbFiles && usbFiles.length > 0) {
     for (UsbFile usbFile : usbFiles) {
       if (usbFile.getName().equals(U_DISK_FILE_NAME)) {
         readTxtFromUDisk(usbFile);
       }
     }
   }
 }

/**
  * @description 保存数据到U盘,目前是保存到根目录的
  * @author ldm
  * @time 2017/9/1 17:17
  */
 private void saveText2UDisk(String content) {
   //项目中也把文件保存在了SD卡,其实可以直接把文本读取到U盘指定文件
   File file = FileUtil.getSaveFile(getPackageName()
           + File.separator + FileUtil.DEFAULT_BIN_DIR,
       U_DISK_FILE_NAME);
   try {
     FileWriter fw = new FileWriter(file);
     fw.write(content);
     fw.close();
   } catch (IOException e) {
     e.printStackTrace();
   }
   if (null != cFolder) {
     FileUtil.saveSDFile2OTG(file, cFolder);
     mHandler.sendEmptyMessage(100);
   }
 }

/**
  * @description OTG广播注册
  * @author ldm
  * @time 2017/9/1 17:19
  */
 private void registerUDiskReceiver() {
   //监听otg插入 拔出
   IntentFilter usbDeviceStateFilter = new IntentFilter();
   usbDeviceStateFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
   usbDeviceStateFilter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
   registerReceiver(mOtgReceiver, usbDeviceStateFilter);
   //注册监听自定义广播
   IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
   registerReceiver(mOtgReceiver, filter);
 }

/**
  * @description OTG广播,监听U盘的插入及拔出
  * @author ldm
  * @time 2017/9/1 17:20
  * @param
  */
 private BroadcastReceiver mOtgReceiver = new BroadcastReceiver() {
   public void onReceive(Context context, Intent intent) {
     String action = intent.getAction();
     switch (action) {
       case ACTION_USB_PERMISSION://接受到自定义广播
         UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
         //允许权限申请
         if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
           if (usbDevice != null) {
             //用户已授权,可以进行读取操作
             readDevice(getUsbMass(usbDevice));
           } else {
             showToastMsg("没有插入U盘");
           }
         } else {
           showToastMsg("未获取到U盘权限");
         }
         break;
       case UsbManager.ACTION_USB_DEVICE_ATTACHED://接收到U盘设备插入广播
         UsbDevice device_add = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
         if (device_add != null) {
           //接收到U盘插入广播,尝试读取U盘设备数据
           redUDiskDevsList();
         }
         break;
       case UsbManager.ACTION_USB_DEVICE_DETACHED://接收到U盘设设备拔出广播
         showToastMsg("U盘已拔出");
         break;
     }
   }
 };

/**
  * @description U盘设备读取
  * @author ldm
  * @time 2017/9/1 17:20
  */
 private void redUDiskDevsList() {
   //设备管理器
   UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
   //获取U盘存储设备
   storageDevices = UsbMassStorageDevice.getMassStorageDevices(this);
   PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
   //一般手机只有1个OTG插口
   for (UsbMassStorageDevice device : storageDevices) {
     //读取设备是否有权限
     if (usbManager.hasPermission(device.getUsbDevice())) {
       readDevice(device);
     } else {
       //没有权限,进行申请
       usbManager.requestPermission(device.getUsbDevice(), pendingIntent);
     }
   }
   if (storageDevices.length == 0) {
     showToastMsg("请插入可用的U盘");
   }
 }

private UsbMassStorageDevice getUsbMass(UsbDevice usbDevice) {
   for (UsbMassStorageDevice device : storageDevices) {
     if (usbDevice.equals(device.getUsbDevice())) {
       return device;
     }
   }
   return null;
 }

private void readDevice(UsbMassStorageDevice device) {
   try {
     device.init();//初始化
     //设备分区
     Partition partition = device.getPartitions().get(0);
     //文件系统
     FileSystem currentFs = partition.getFileSystem();
     currentFs.getVolumeLabel();//可以获取到设备的标识
     //通过FileSystem可以获取当前U盘的一些存储信息,包括剩余空间大小,容量等等
     Log.e("Capacity: ", currentFs.getCapacity() + "");
     Log.e("Occupied Space: ", currentFs.getOccupiedSpace() + "");
     Log.e("Free Space: ", currentFs.getFreeSpace() + "");
     Log.e("Chunk size: ", currentFs.getChunkSize() + "");
     cFolder = currentFs.getRootDirectory();//设置当前文件对象为根目录
   } catch (Exception e) {
     e.printStackTrace();
   }
 }

private void showToastMsg(String msg) {
   Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
 }

private void readTxtFromUDisk(UsbFile usbFile) {
   UsbFile descFile = usbFile;
   //读取文件内容
   InputStream is = new UsbFileInputStream(descFile);
   //读取秘钥中的数据进行匹配
   StringBuilder sb = new StringBuilder();
   BufferedReader bufferedReader = null;
   try {
     bufferedReader = new BufferedReader(new InputStreamReader(is));
     String read;
     while ((read = bufferedReader.readLine()) != null) {
       sb.append(read);
     }
     Message msg = mHandler.obtainMessage();
     msg.what = 101;
     msg.obj = read;
     mHandler.sendMessage(msg);
   } catch (Exception e) {
     e.printStackTrace();
   } finally {
     try {
       if (bufferedReader != null) {
         bufferedReader.close();
       }
     } catch (IOException e) {
       e.printStackTrace();
     }
   }
 }
}

对应布局文件:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context="com.ldm.androidudisk.MainActivity"
   android:orientation="vertical">

<TextView
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:text="Android盒子外接U盘文件读写测试DEMO"
     android:layout_gravity="center"
     android:layout_margin="10dp"
     />

<EditText
     android:id="@+id/u_disk_edt"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:layout_margin="10dp"
     android:hint="输入要保存到U盘中的文字内容"/>

<Button
     android:id="@+id/u_disk_write"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:layout_margin="10dp"
     android:gravity="center"
     android:text="往U盘中写入数据"/>

<Button
     android:id="@+id/u_disk_read"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:layout_margin="10dp"
     android:gravity="center"
     android:text="从U盘中读取数据"/>

<TextView
     android:id="@+id/u_disk_show"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_gravity="center"
     android:layout_marginLeft="10dp"
     />
</LinearLayout>

文件操作工具类:


package com.ldm.androidudisk.utils;

import android.os.Environment;

import com.github.mjdev.libaums.fs.UsbFile;
import com.github.mjdev.libaums.fs.UsbFileOutputStream;

import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import static android.os.Environment.getExternalStorageDirectory;

/**
* 文件操作工具类
*
* @author ldm
* @description:
* @date 2016-4-28 下午3:17:10
*/
public final class FileUtil {
 public static final String DEFAULT_BIN_DIR = "usb";

/**
  * 检测SD卡是否存在
  */
 public static boolean checkSDcard() {
   return Environment.MEDIA_MOUNTED.equals(Environment
       .getExternalStorageState());
 }

/**
  * 从指定文件夹获取文件
  *
  * @return 如果文件不存在则创建, 如果如果无法创建文件或文件名为空则返回null
  */
 public static File getSaveFile(String folderPath, String fileNmae) {
   File file = new File(getSavePath(folderPath) + File.separator
       + fileNmae);
   try {
     file.createNewFile();
   } catch (IOException e) {
     e.printStackTrace();
   }
   return file;
 }

/**
  * 获取SD卡下指定文件夹的绝对路径
  *
  * @return 返回SD卡下的指定文件夹的绝对路径
  */
 public static String getSavePath(String folderName) {
   return getSaveFolder(folderName).getAbsolutePath();
 }

/**
  * 获取文件夹对象
  *
  * @return 返回SD卡下的指定文件夹对象,若文件夹不存在则创建
  */
 public static File getSaveFolder(String folderName) {
   File file = new File(getExternalStorageDirectory()
       .getAbsoluteFile()
       + File.separator
       + folderName
       + File.separator);
   file.mkdirs();
   return file;
 }

/**
  * 关闭流
  */
 public static void closeIO(Closeable... closeables) {
   if (null == closeables || closeables.length <= 0) {
     return;
   }
   for (Closeable cb : closeables) {
     try {
       if (null == cb) {
         continue;
       }
       cb.close();
     } catch (IOException e) {
       e.printStackTrace();
     }
   }
 }

private static void redFileStream(OutputStream os, InputStream is) throws IOException {
   int bytesRead = 0;
   byte[] buffer = new byte[1024 * 8];
   while ((bytesRead = is.read(buffer)) != -1) {
     os.write(buffer, 0, bytesRead);
   }
   os.flush();
   os.close();
   is.close();
 }

/**
  * @description 把本地文件写入到U盘中
  * @author ldm
  * @time 2017/8/22 10:22
  */
 public static void saveSDFile2OTG(final File f, final UsbFile usbFile) {
   UsbFile uFile = null;
   FileInputStream fis = null;
   try {//开始写入
     fis = new FileInputStream(f);//读取选择的文件的
     if (usbFile.isDirectory()) {//如果选择是个文件夹
       UsbFile[] usbFiles = usbFile.listFiles();
       if (usbFiles != null && usbFiles.length > 0) {
         for (UsbFile file : usbFiles) {
           if (file.getName().equals(f.getName())) {
             file.delete();
           }
         }
       }
       uFile = usbFile.createFile(f.getName());
       UsbFileOutputStream uos = new UsbFileOutputStream(uFile);
       try {
         redFileStream(uos, fis);
       } catch (IOException e) {
         e.printStackTrace();
       }
     }
   } catch (final Exception e) {
     e.printStackTrace();
   }
 }
}

不要忘记在app/build.grade下添加:


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

及AndroidManifest.xml中添加权限:


<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

时间关系,就不贴图了,欢迎指导交流。

来源:http://blog.csdn.net/true100/article/details/77775700?locationNum=10&fps=1

标签:Android,U盘,数据读取
0
投稿

猜你喜欢

  • 史上最简洁C# 生成条形码图片思路及示例分享

    2023-08-24 15:50:25
  • 在C#中 webbrowser的使用心得

    2023-12-10 12:57:00
  • struts2单个文件上传的两种实现方式

    2023-04-23 05:33:30
  • SWT(JFace)体验之打开多个Form

    2021-11-29 03:19:15
  • java的三种随机数生成方式

    2022-03-06 13:43:57
  • Java 精炼解读数据结构的链表的概念与实现

    2022-03-02 05:17:11
  • Spring Core动态代理的实现代码

    2021-12-11 03:40:54
  • Android10.0实现本地音乐播放(附源码下载)

    2022-12-05 20:29:40
  • IDEA中使用Typora编辑md文件的方法

    2022-11-28 09:50:47
  • java判断String类型是否能转换为int的方法

    2022-08-17 23:45:52
  • Android开发升级AGP7.0后的一些适配方法技巧

    2022-10-22 17:41:22
  • java开发就业信息管理系统

    2022-06-19 02:09:30
  • C#使用WebSocket与网页实时通信的实现示例

    2023-02-15 01:22:24
  • SpringBoot3.0整合chatGPT的完整步骤

    2023-01-29 01:34:36
  • C#编译器对局部变量的优化指南

    2023-06-23 14:54:12
  • 简单的一次springMVC路由跳转实现

    2023-01-09 10:05:11
  • 查找算法之二分查找的C++实现

    2022-05-27 07:24:17
  • 让C# Excel导入导出 支持不同版本Office

    2023-01-11 05:30:53
  • java基础之数组常用操作总结(必看篇)

    2022-12-09 03:32:17
  • android 自定义Android菜单背景的代码

    2022-06-23 08:54:40
  • asp之家 软件编程 m.aspxhome.com