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

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

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

通过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"/>

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android中Json数据读取与创建的方法

    首先介绍下JSON的定义,JSON是JavaScript Object Notation的缩写. 一种轻量级的数据交换格式,具有良好的可读和便于快速编写的特性.业内主流技术为其提供了完整的解决方案(有点类似于正则表达式,获得了当今大部分语言的支持),从而可以在不同平台间进行数据交换.JSON采用兼容性很高的文本格式,同时也具备类似于C语言体系的行为. JSON的结构: (1) Name/Value Pairs(无序的):类似所熟知的Keyed list. Hash table.Disctiona

  • android读写sd卡操作写入数据读取数据示例

    复制代码 代码如下: package com.example.sdcardtest;import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.io.InputStreamReader;import java.io.RandomAccessFil

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

    现在越来越多手机支持OTG功能,通过OTG可以实现与外接入的U盘等USB设备实现数据传输. USB OTG(On The Go)作为USB2.0的补充协议,于2001年由USB-IF提出.它提出的背景是移动消费类电子产品的迅猛增加,而之前USB协议的主从协议标准让这些电子产品在离开PC电脑时的数据传输变得艰难,OTG技术正是为了解决这一问题的标准. 通过OTG技术实现设备间端到端互联 OTG协议规定连接时默认情况作为Host的设备为A设备,A设备负责为总线供电:默认作为Device的设备为B设备

  • Android编程中File文件常见存储与读取操作demo示例

    本文实例讲述了Android编程中File文件常见存储与读取操作.分享给大家供大家参考,具体如下: MainActivity文件代码如下: package example.com.myapplication; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; im

  • PyTorch数据读取的实现示例

    前言 PyTorch作为一款深度学习框架,已经帮助我们实现了很多很多的功能了,包括数据的读取和转换了,那么这一章节就介绍一下PyTorch内置的数据读取模块吧 模块介绍 pandas 用于方便操作含有字符串的表文件,如csv zipfile python内置的文件解压包 cv2 用于图片处理的模块,读入的图片模块为BGR,N H W C torchvision.transforms 用于图片的操作库,比如随机裁剪.缩放.模糊等等,可用于数据的增广,但也不仅限于内置的图片操作,也可以自行进行图片数

  • SpringBoot yaml语法与数据读取操作详解

    目录 yaml yaml语法规则 字面值表示方式: 数组表示方式: 对象数组格式: 对象数组缩略格式: 读取yaml数据 编写yaml文件 读取单一数据 读取二级数据 读取数组数据 读取服务器端口号 读取对象属性 封装全部数据到Environment对象 读取yaml引用类型属性数据 application.yml MyDataSource 读取数据 变量的引用 application.yml 读取数据 context-path @Autowired报错解决方案 yaml YAML是一种数据序列

  • MySQL实现数据插入操作的示例详解

    目录 一.方法分类 二.具体方法 三.实例 (1)常规插入 (2)从另一个表导入 (3)插入时数据重复 四.注意事项 (1)不写字段名,需要填充自增ID (2)按字段名填充,可以不录入id 其余注意事项 使用MySQL插入数据时,可以根据需求场景选择合适的插入语句,例如当数据重复时如何插入数据,如何从另一个表导入数据,如何批量插入数据等场景.本文通过给出每个使用场景下的实例来说明数据插入的实现过程和方法. 一.方法分类 二.具体方法 使用场景 作用 语句 注意 常规插入 忽略字段名 insert

  • TP5(thinkPHP5)框架基于ajax与后台数据交互操作简单示例

    本文实例讲述了TP5(thinkPHP5)框架基于ajax与后台数据交互操作.分享给大家供大家参考,具体如下: Ajax最大的一点是页面无刷新,在页面内与服务器通信,给用户的体验非常好.可以把以前一些服务器负担的工作转嫁到客户端,利用客户端闲置的能力来处理,减轻服务器和带宽的负担,节约空间和宽带租用成本.并且减轻服务器的负担,ajax的原则是"按需取数据",可以最大程度的减少冗余请求,和响应对服务器造成的负担. 最近在用tp5开发企业微应用,很有收获,觉得最需要注意的是thinkphp

  • ThinkPHP3.1数据CURD操作快速入门

    1.CURD概述: CURD是一个数据库技术中的缩写词,一般的项目开发的各种参数的基本功能都是CURD.它代表创建(Create).更新(Update).读取(Read)和删除(Delete)操作.CURD 定义了用于处理数据的基本原子操作.之所以将CURD提升到一个技术难题的高度是因为完成一个涉及在多个数据库系统中进行CURD操作的汇总相关的活动,其性能可能会随数据关系的变化而有非常大的差异. CURD在具体的应用中并非一定使用create.update.read和delete字样的方法,但是

  • Android 6.0区别U盘和SD卡设备的方法详解

    如下所示: public static boolean isSdcardExists(Context context) { StorageManager storageManager = StorageManager.from(context.getApplicationContext()); List<VolumeInfo> volumes = storageManager.getVolumes(); for (VolumeInfo volInfo : volumes) { DiskInfo

  • Android通过json向MySQL中读写数据的方法详解【写入篇】

    本文实例讲述了Android通过json向MySQL中写入数据的方法.分享给大家供大家参考,具体如下: 先说一下如何通过json将Android程序中的数据上传到MySQL中: 首先定义一个类JSONParser.Java类,将json上传数据的方法封装好,可以直接在主程序中调用该类,代码如下 public class JSONParser { static InputStream is = null; static JSONObject jObj = null; static String j

  • Android设备上非root的抓包实现方法(Tcpdump方法)

    通常我们在Android应用中执行某个命令时会使用"Runtime.getRuntime().exec("命令路径")"这种方式,但是当我们执行抓包操作时,使用这条命令无论如何都不行,通过下面代码打印结果发现,该命令一定要在root权限下才能执行. BufferedReader brW = new BufferedReader(new InputStreamReader(p.getErrorStream())); while((str = brW.readLine(

随机推荐