首先给予足够的读写权限:
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.hardware.usb.host" android:required="false" /> <uses-feature android:name="android.hardware.usb.host" android:required="true" />
其次添加一个U盘读写操作的依赖包,我用的也是大家都推荐的:
compile 'com.github.mjdev:libaums:0.5.5'
继续上代码:首先是写操作(注意:需要你的手机root了才可以)
第一步:注册广播
/** * @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 = 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盘"); } }
设备写入:
/** * @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(MainActivity.this,file, cFolder); mHandler.sendEmptyMessage(100); } }
文件操作类:
public 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(); } public static List<String> getAllExterSdcardPath() { List<String> SdList = new ArrayList<String>(); String firstPath = Environment.getExternalStorageDirectory().getPath(); try { Runtime runtime = Runtime.getRuntime(); // 运行mount命令,获取命令的输出,得到系统中挂载的所有目录 Process proc = runtime.exec("mount"); InputStream is = proc.getInputStream(); InputStreamReader isr = new InputStreamReader(is); String line; BufferedReader br = new BufferedReader(isr); while ((line = br.readLine()) != null) { Log.d("", line); // 将常见的linux分区过滤掉 if (line.contains("proc") || line.contains("tmpfs") || line.contains("media") || line.contains("asec") || line.contains("secure") || line.contains("system") || line.contains("cache") || line.contains("sys") || line.contains("data") || line.contains("shell") || line.contains("root") || line.contains("acct") || line.contains("misc") || line.contains("obb")) { continue; } // 下面这些分区是我们需要的 if (line.contains("fat") || line.contains("fuse") || (line.contains("ntfs"))) { // 将mount命令获取的列表分割,items[0]为设备名,items[1]为挂载路径 String items[] = line.split(" "); if (items != null && items.length > 1) { String path = items[1].toLowerCase(Locale.getDefault()); // 添加一些判断,确保是sd卡,如果是otg等挂载方式,可以具体分析并添加判断条件 if (path != null && !SdList.contains(path) && path.contains("sd")) SdList.add(items[1]); } } } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } if (!SdList.contains(firstPath)) { SdList.add(firstPath); } return SdList; } /** * @description 把本地文件写入到U盘中 * @author ldm * @time 2017/8/22 10:22 */ public static void saveSDFile2OTG(Context context,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(); Toast.makeText(context,e.toString(),Toast.LENGTH_LONG).show(); } } }
private final static String U_DISK_FILE_NAME = "****.txt";//星号写自己要写入文件的文件名
读取操作:Ps:一开始以为挺简单,后面发现没那么简单
获取UsbDevice
private UsbMassStorageDevice getUsbMass(UsbDevice usbDevice) { if(usbDevice!=null){ 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); //文件系统 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();//设置当前文件对象为根目录 UsbFile[] usbFiles=cFolder.listFiles(); if (null != usbFiles && usbFiles.length > 0) { for (UsbFile usbFile : usbFiles) { if (usbFile.getName().equals(U_DISK_FILE_NAME)) { readFile(usbFile); // readTxtFromUDisk(usbFile); } } } } catch (Exception e) { e.printStackTrace(); android.widget.Toast.makeText(AddPwsAddressActivity.this,e.toString(), android.widget.Toast.LENGTH_LONG).show(); } }
private void readFile(final UsbFile uFile) { String sdPath = SDUtils.getSDPath();//获取sd根目录 创建一个同名文件 String filePath = sdPath + "/" + uFile.getName(); final File f = new File(filePath); if (!f.exists()) { try { f.createNewFile(); //设置视图 //执行线程 executorService.execute(new Runnable() { @Override public void run() { try { FileOutputStream os = new FileOutputStream(f); InputStream is = new UsbFileInputStream(uFile); final String bt = redFileStream(os, is); runOnUiThread(new Runnable() { @Override public void run() { android.widget.Toast.makeText(AddPwsAddressActivity.this,bt, android.widget.Toast.LENGTH_LONG).show(); Message msg = mHandler.obtainMessage(); msg.what = 101; android.widget.Toast.makeText(AddPwsAddressActivity.this,bt, android.widget.Toast.LENGTH_LONG).show(); msg.obj = bt; mHandler.sendMessage(msg); } }); } catch (final Exception e) { e.printStackTrace(); } } }); } catch (final Exception e) { e.printStackTrace(); } }else { try { executorService.execute(new Runnable() { @Override public void run() { try { FileOutputStream os = new FileOutputStream(f); InputStream is = new UsbFileInputStream(uFile); final String bt = redFileStream(os, is); runOnUiThread(new Runnable() { @Override public void run() { android.widget.Toast.makeText(AddPwsAddressActivity.this,bt, android.widget.Toast.LENGTH_LONG).show(); Message msg = mHandler.obtainMessage(); msg.what = 101; android.widget.Toast.makeText(AddPwsAddressActivity.this,bt, android.widget.Toast.LENGTH_LONG).show(); msg.obj = bt; mHandler.sendMessage(msg); } }); } catch (final Exception e) { e.printStackTrace(); } } }); } catch (final Exception e) { e.printStackTrace(); } } }
private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case 100: showToastMsg("保存成功"); break; case 101: if(msg.obj==null){ Toast.makeText(MainActivity.this,"空的",Toast.LENGTH_LONG).show(); }else{ String txt = msg.obj.toString(); if (!TextUtils.isEmpty(txt)) u_disk_show.setText("读取到的数据是:" + txt); } break; } } };
Ps:别忘记反注册广播
特别感谢(对代码有疑问的可以提给我或者去看这两篇博客):
https://blog.csdn.net/csdn635406113/article/details/70146041
https://blog.csdn.net/true100/article/details/77775700
还要感谢我朋友猴子的无私分享~
sd卡工具类:
public class SDUtils { private static final String TAG = "文件工具类"; public static String getSDPath() { File sdDir = null; boolean sdCardExist = Environment.getExternalStorageState() .equals(Environment.MEDIA_MOUNTED); //判断sd卡是否存在 if (sdCardExist) { sdDir = Environment.getExternalStorageDirectory();//获取跟目录 // sdDir1 = Environment.getDataDirectory(); // sdDir2 = Environment.getRootDirectory(); } else { Log.d(TAG, "getSDPath: sd卡不存在"); } Log.d(TAG, "getSDPath: " + sdDir.getAbsolutePath()); return sdDir.getAbsolutePath(); }