欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2023-12-01 15:33:40
现在越来越多手机支持otg功能,通过otg可以实现与外接入的u盘等usb设备实现数据传输。  usb otg(on the go)作为usb2.0的补充协议,于...

现在越来越多手机支持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盘文件路径及文件操作

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

代码部分:

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

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

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