Android-外接U盘实现数据读取操作(转载实践)

本来就没打算弄这个,之前老东家突然有个插入U盘到Android设备,然后提示安装apk的需求。有两点:

1. 系统是自己开发的,可以检测到U盘后自动识别自家应用,进而进行提示安装或者直接默认安装(仅限自己系统)

2. 系统不是自己的,开发一个小应用,然后启动该应用,检测U盘插入,然后读取规定好的文件(可以校验下md5或者签名), 然后拷贝到设备,然后提示进行安装(只能是提示而已,不是自己的系统肯定不能进行默认安装,没那个权限)

小白初步分析后进行了说明,如果要做就只能开个一个小应用了。好吧。然后快速找一堆资料,尽快尝试下,也没那么多时间去看官方,研究具体使用方式了啦。。。所以这里就直接贴代码,把网上的可行,不可行等情况都尝试下...

然后综合出一个可行的。。

权限:

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

第三方库:

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

UsbActivity.java

package com.example.lieyun_android;

import android.content.IntentFilter;
import android.hardware.usb.UsbManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import com.example.lieyun_android.myapplication.R;

public class UsbActivity extends AppCompatActivity {

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

        ///< @a 这种不好使
        //        IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MEDIA_MOUNTED);//插
        //        intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);//拔
        //        intentFilter.addAction(Intent.ACTION_MEDIA_REMOVED);  //完全拔出
        //        intentFilter.addDataScheme("file");//没有这行监听不起作用
        //        registerReceiver(mSdcardReceiver, intentFilter,
        //                "android.permission.READ_EXTERNAL_STORAGE",null);

        ///< 监听otg插入 拔出
        IntentFilter usbDeviceStateFilter = new IntentFilter();
        usbDeviceStateFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
        usbDeviceStateFilter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
        registerReceiver(usbBroadcastReceiver, usbDeviceStateFilter);
        //注册监听自定义广播
        IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
        registerReceiver(usbBroadcastReceiver, filter);
    }
    private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";

    private USBBroadcastReceiver usbBroadcastReceiver = new USBBroadcastReceiver();

    ///< @a 这种不好使
    //    private BroadcastReceiver mSdcardReceiver = new BroadcastReceiver() {
    //        @Override
    //        public void onReceive(Context context, Intent intent) {
    //            if (intent.getAction().equals(Intent.ACTION_MEDIA_UNMOUNTED)) {
    //                Toast.makeText(context, "插入", Toast.LENGTH_SHORT).show();
    //            } else if (intent.getAction().equals(Intent.ACTION_MEDIA_REMOVED)) {
    //                Toast.makeText(context, "remove ACTION_MEDIA_REMOVED", Toast.LENGTH_SHORT).show();
    //            }
    //        }
    //    };
}

USBBroadcastReceiver.java

package com.example.lieyun_android;

import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.util.Log;
import android.widget.Toast;

import com.github.mjdev.libaums.UsbMassStorageDevice;
import com.github.mjdev.libaums.fs.FileSystem;
import com.github.mjdev.libaums.fs.UsbFile;
import com.github.mjdev.libaums.fs.UsbFileInputStream;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

/*
*@Description: U盘检测广播
*@Author: hl
*@Time: 2018/9/20 10:11
*/
public class USBBroadcastReceiver extends BroadcastReceiver {
    private static final String TAG = "USBBroadcastReceiver";

    @Override
    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(context, getUsbMass(usbDevice));
                    } else {
                        Toast.makeText(context, "没有插入U盘", Toast.LENGTH_LONG).show();
                    }
                } else {
                    Toast.makeText(context, "未获取到U盘权限", Toast.LENGTH_LONG).show();
                }
                break;
            case UsbManager.ACTION_USB_DEVICE_ATTACHED://接收到U盘设备插入广播
                UsbDevice device_add = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                if (device_add != null) {
                    //接收到U盘插入广播,尝试读取U盘设备数据
                    redUDiskDevsList(context);
                }
                break;
            case UsbManager.ACTION_USB_DEVICE_DETACHED://接收到U盘设设备拔出广播
                Toast.makeText(context, "拔出", Toast.LENGTH_LONG).show();
                break;
        }

        ///< 另外一种乱七八糟拼凑判断U盘插入的方法,不是特别好用 这个地方本来是这样:intent.getExtras().getBoolean("connected") ,但是我发现需要修改为host_connected
        ///< 这种判断方式肯定不如上面的UsbManager.ACTION_USB_DEVICE_ATTACHED
        //        if (intent.getAction().equals(ACTION_USB_PERMISSION)) {
        //            UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
        //            //允许权限申请
        //            if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
        //                if (usbDevice != null) {
        //                    //用户已授权,可以进行读取操作
        //                    readDevice(context, getUsbMass(usbDevice));
        //                } else {
        //                    Toast.makeText(context, "没有插入U盘", Toast.LENGTH_LONG).show();
        //                }
        //            } else {
        //                Toast.makeText(context, "未获取到U盘权限", Toast.LENGTH_LONG).show();
        //            }
        //        } else if (intent.getAction().equals("android.hardware.usb.action.USB_STATE")) {
        //            Toast.makeText(context, "action=" + intent.getAction(), Toast.LENGTH_LONG).show();
        //            Bundle bundle = intent.getExtras();
        //            for (String key : bundle.keySet()) {
        //                Toast.makeText(context, "Key=" + key + " + content=" + bundle.get(key), Toast.LENGTH_LONG).show();
        //            }
        //            if (intent.getExtras().getBoolean("host_connected")) {
        //                // usb 插入
        //                Toast.makeText(context, "插入", Toast.LENGTH_LONG).show();
        //
        //                UsbDevice device_add = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
        //                Toast.makeText(context, "device_add=" + device_add, Toast.LENGTH_LONG).show();
        //
        //                if (device_add != null) {
        //                    //接收到U盘插入广播,尝试读取U盘设备数据
        //                    redUDiskDevsList(context);
        //               }

        //                UsbMassStorageDevice[] devices =
        //                        UsbMassStorageDevice.getMassStorageDevices(context /* Context or Activity */);
        //                Toast.makeText(context, "devices.length=" + devices.length, Toast.LENGTH_LONG).show();
        //                for (UsbMassStorageDevice device : devices) {
        //
        //                    // before interacting with a device you  need to call init()!
        //                    try {
        //                        device.init();
        //                        // Only uses the first partition on the device
        //                        FileSystem currentFs = device.getPartitions().get(0).getFileSystem();
        //                        Log.d(TAG, "Capacity: " + currentFs.getCapacity());
        //                        Toast.makeText(context, "Capacity: " + currentFs.getCapacity(), Toast.LENGTH_LONG).show();
        //                        Log.d(TAG, "Occupied Space: " + currentFs.getOccupiedSpace());
        //                        Toast.makeText(context, "Occupied Space: " + currentFs.getOccupiedSpace(), Toast.LENGTH_LONG).show();
        //                        Log.d(TAG, "Free Space: " + currentFs.getFreeSpace());
        //                        Toast.makeText(context, "Free Space: " + currentFs.getFreeSpace(), Toast.LENGTH_LONG).show();
        //                        Log.d(TAG, "Chunk size: " + currentFs.getChunkSize());
        //                        Toast.makeText(context, "Chunk size: " + currentFs.getChunkSize(), Toast.LENGTH_LONG).show();
        //                    } catch (IOException e) {
        //                        //e.printStackTrace();
        //                        Toast.makeText(context, "IOException" + e.getMessage(), Toast.LENGTH_LONG).show();
        //                    }
        //                }
        //            } else {
        //                //   usb 拔出
        //                Toast.makeText(context, "拔出", Toast.LENGTH_LONG).show();
        //            }
        //        }
    }

    //当前处接U盘列表
    private UsbMassStorageDevice[] storageDevices;
    //自定义U盘读写权限
    private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
    //当前U盘所在文件目录
    private UsbFile cFolder;
    private final static String U_DISK_FILE_NAME = "u_disk.txt";

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

    /**
     * 获取对应的U盘设备
     * @param usbDevice
     * @return
     */
    private UsbMassStorageDevice getUsbMass(UsbDevice usbDevice) {
        for (UsbMassStorageDevice device : storageDevices) {
            if (usbDevice.equals(device.getUsbDevice())) {
                return device;
            }
        }
        return null;
    }

    /**
     * 读取U盘信息
     * @param context
     * @param device
     */
    private void readDevice(Context context, UsbMassStorageDevice device) {
        try {
            device.init();
            // Only uses the first partition on the device
            FileSystem currentFs = device.getPartitions().get(0).getFileSystem();
            //Toast.makeText(context, "getRootDirectory: " + currentFs.getRootDirectory().getName(), Toast.LENGTH_LONG).show();
            Log.d(TAG, "Capacity: " + currentFs.getCapacity());
            //Toast.makeText(context, "Capacity: " + currentFs.getCapacity(), Toast.LENGTH_LONG).show();
            Log.d(TAG, "Occupied Space: " + currentFs.getOccupiedSpace());
            //Toast.makeText(context, "Occupied Space: " + currentFs.getOccupiedSpace(), Toast.LENGTH_LONG).show();
            Log.d(TAG, "Free Space: " + currentFs.getFreeSpace());
            //Toast.makeText(context, "Free Space: " + currentFs.getFreeSpace(), Toast.LENGTH_LONG).show();
            Log.d(TAG, "Chunk size: " + currentFs.getChunkSize());
            //Toast.makeText(context, "Chunk size: " + currentFs.getChunkSize(), Toast.LENGTH_LONG).show();
            //设置当前文件对象为根目录
            cFolder = currentFs.getRootDirectory();
            ///< 读取当前目录下的文件
            readFromUDisk(context);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取U盘文件信息
     * @param context
     */
    private void readFromUDisk(Context context) {
        UsbFile[] usbFiles = new UsbFile[0];
        try {
            usbFiles = cFolder.listFiles();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (null != usbFiles && usbFiles.length > 0) {
            for (UsbFile usbFile : usbFiles) {
                Toast.makeText(context, "usbFile.getName(): " + usbFile.getName(), Toast.LENGTH_LONG).show();
                if (usbFile.getName().equals(U_DISK_FILE_NAME)) {
                    readTxtFromUDisk(usbFile);
                }
            }
        }
    }

    /**
     * @description 保存数据到U盘,目前是保存到根目录的
     * @author ldm
     * @time 2017/9/1 17:17
     */
    private void saveText2UDisk(Context context, String content) {
        //项目中也把文件保存在了SD卡,其实可以直接把文本读取到U盘指定文件
        File file = null;///< FileUtil.getSaveFile(context.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);
        }
    }

    /**
     * 读取U盘文件的内容
     * @param usbFile
     */
    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();
            }
        }
    }
}

以上拿过去就可以用了。可以读取U盘所有的文件信息,然后你就可以进行相关文件操作了哈。记得给动态给读写权限...(现今存储需要动态给了,就算不是外卡也需要provider了).......里面有些尝试无法可行(最新xxx米系统上反正不行)...

最后感谢网友.. https://blog.csdn.net/true100/article/details/77775700,记得给人家点赞转发...

有空再看这块: https://blog.csdn.net/srw11/article/details/39154053

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351

推荐阅读更多精彩内容

  • feisky云计算、虚拟化与Linux技术笔记posts - 1014, comments - 298, trac...
    不排版阅读 3,836评论 0 5
  • 〇、摘要: 常见Mac电脑安装macOS操作系统有以下方式(本文主要讨论方式3,黑苹果和虚拟机不在讨论范畴)。 方...
    笑笑爸比阅读 8,782评论 3 3
  • 1、第八章 Samba服务器2、第八章 NFS服务器3、第十章 Linux下DNS服务器配站点,域名解析概念命令:...
    哈熝少主阅读 3,720评论 0 10
  • 总结整理了一下android权限相关的知识,由于篇幅过长,分为两篇博客来写,上篇博客主要是详解权限和安全,下篇主要...
    Shawn_Dut阅读 3,776评论 2 10
  • 每到周末 都是火药味十足 围着业绩转 补货、面销、清洁、人力 大家都不愿意妥协 站在自己的立场 各抒己见 我也处于...
    幸福氧花阅读 209评论 0 2