zoukankan      html  css  js  c++  java
  • Android设备与外接U盘实现数据读取操作

    现在越来越多手机支持OTG功能,通过OTG可以实现与外接入的U盘等USB设备实现数据传输。关于OTG,可以参考:
    http://blog.csdn.net/srw11/article/details/39154053。
    最近项目上用到了该功能,项目上用的是安卓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"/>
    
    
  • 相关阅读:
    复盘:错误理解zuul路径匹配,无法使用zuul
    oracle 查询含clob 字段慢
    Javascript生成二维码(QR)
    那些可以在数据库里做的事:分页与过滤
    小谈Scrum敏捷开发流程
    45个实用的JavaScript技巧、窍门和最佳实践
    编写更好的jQuery代码的建议
    冷门JS技巧
    jQuery编程的最佳实践
    chrome扩展安装图文教程
  • 原文地址:https://www.cnblogs.com/DreamRecorder/p/9213709.html
Copyright © 2011-2022 走看看