Android U盤文件讀寫複製操作 應用開發起因 總結 最後

前言

今天羣友在說公司要求他開發一個Android的U盤讀寫APP(具體要求就不說了),然後就有羣友分享了這篇文,大家都說這個文寫的不錯,受益匪淺。所以,在這裏就分享給大家,希望對大家的工作和學習有所幫助。

另外,我們羣是一個非常活躍的兩千人技術交流圈,對Android感興趣的朋友歡迎加入我們,私信我獲得羣密碼(羣專屬海量學習資源,免費共享)。

應用開發起因

起因是公司導師讓我研究一下Android如何通過apk來訪問u盤,往u盤裏面寫數據。需求下來了,就開始研究了,之前完全沒有接觸過Android與usb之間的內容,那就少不了了各種查資料了。

在網上翻了半天,不過網上這塊的資料也是非常的少,這也更加堅定了我要寫一個這樣的應用出來。網上大概都是這樣的,實現讀取u盤裏的txt文件,往u盤的txt文件裏寫入數據,可能確實是這塊比較冷門,都沒有一個完整一點的應用。

我思考了很久,大概有了一個應用的雛形,有兩個文件列表,一個是Android系統的文件列表,一個是U盤的文件列表,可以實現兩邊文本的讀寫數據,實現兩邊之間文本的複製,還有一個功能是後來導師提出的,實現圖片的讀寫。

那麼,計劃了這麼多,就開幹吧!

一.U盤的拔插監聽及讀取U盤設備

這個應該是此應用開發的第一步,我先研究的是U盤的拔插監聽,這裏要用到兩個監聽標誌。

ACTION_USB_DEVICE_ATTACHED
ACTION_USB_DEVICE_DETACHED

一個代表u盤插入,一個代表u盤拔出,再來看看usbManager裏的這倆。

"android.hardware.usb.action.USB_DEVICE_ATTACHED"
"android.hardware.usb.action.USB_DEVICE_DETACHED"

有了這兩個標誌就簡單了許多了

        //監聽otg插入 拔出
        IntentFilter usbDeviceStateFilter = new IntentFilter();
        usbDeviceStateFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
        usbDeviceStateFilter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
        registerReceiver(mOtgReceiver, usbDeviceStateFilter);

通過註冊這兩個標誌的監聽,來實現u盤拔插的廣播

               case UsbManager.ACTION_USB_DEVICE_ATTACHED://接收到U盤設備插入廣播
                    showToastMsg("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盤已拔出");
                    redUDiskDevsList();
                    break;

使用showToastMsg()方法來廣播u盤的拔插情況,當插入時再去調用redUDiskDevsList()方法,讀取u盤數據。

private boolean 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);
                mU_disk_ok = true;
                Log.d(TAG, "獲取到權限: "+mU_disk_ok);
            } else {
                //沒有權限,進行申請
                usbManager.requestPermission(device.getUsbDevice(), pendingIntent);
            }
        }
        if (storageDevices.length == 0) {
            u_disk_message.setText("請插入可用的U盤");
            mU_disk_ok = false;
        }else {
            u_disk_message.setText("");
        }
        return mU_disk_ok;
    }

這個講一個mU_disk_ok這個標誌,是我用來解決在進行操作時u盤是否實時保證插入並且獲取到了權限,因爲在開發過程中遇到一個問題。

當先插入了u盤獲取了權限以後,把u盤拔出,再去做U盤的一些操作,這就會導致一些bug的產生,所以對u盤的權限判斷應該是實時的,每次執行操作都要去判斷一次。使用mU_disk_ok作爲redUDiskDevsList()方法的返回值,當redUDiskDevsList()爲true時才執行u盤操作,否則提示請插入u盤。

再來看看readDevice(device)這個方法,在講這個之前有一個東西不能不提,libaums。這個是我在查閱資料時,基本網上涉及到usb操作的開發都會用到libaums這麼一個開源框架。

那麼就簡單的介紹一下libaums框架,來自於github上的介紹,A library to access USB mass storage devices (pen drives, external HDDs, card readers) using the Android USB Host API. Currently it supports the SCSI command set and the FAT32 file system.大致就是說這是一個一個使用Android USB Host API訪問USB存儲設備的庫,目前支持SCSI命令集和FAT32文件系統。

其實你只要知道,使用他可以幫助你開發usb的一些操作。

來看看如何使用,The library can be included into your project like this:

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

只要引用一下libaums,就可以了。
再說回到readDevice(device),這個方法在libaums有使用的示例介紹

UsbMassStorageDevice[] devices = UsbMassStorageDevice.getMassStorageDevices(this /* Context or Activity */);

for(UsbMassStorageDevice device: devices) {

    // before interacting with a device you need to call init()!
    device.init();

    // Only uses the first partition on the device
    FileSystem currentFs = device.getPartitions().get(0).getFileSystem();
    Log.d(TAG, "Capacity: " + currentFs.getCapacity());
    Log.d(TAG, "Occupied Space: " + currentFs.getOccupiedSpace());
    Log.d(TAG, "Free Space: " + currentFs.getFreeSpace());
    Log.d(TAG, "Chunk size: " + currentFs.getChunkSize());
}

那麼到這裏,通過使用libaums的開源庫,幫助我們實現了第一步的開發,U盤的拔插監聽及讀取U盤設備。

二.讀取文件列表

第二步,讀取文件列表,我的想法是把Android系統內部存儲和u盤的文件列表都直觀的讀取出來。

1.U盤文件列表讀取

如何把U盤的文件列表讀取出來,很重要的一點,通過cFolder拿到u盤根目錄的路徑。

cFolder = currentFs.getRootDirectory();

拿到根目錄以後就好辦了,只要去遍歷出根目錄下的文件名,添加到list中,再放到ArrayAdapter,通過listView進行顯示即可。

            List list = new ArrayList<>();
            UsbFile[] usbFiles = new UsbFile[0];
            try {
                usbFiles = cFolder.listFiles();
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (null != usbFiles && usbFiles.length > 0) {
                for (UsbFile usbFile : usbFiles) {
                    Log.d(TAG, "usbFile: "+usbFile.getName());
                    list.add(usbFile.getName());
                }
            }
            final String[] data = new String[list.size()];
            for(int i=0;i<list.size();i++){
                data[i] = String.valueOf(list.get(i));
            }
            ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(
                    MainActivity.this,android.R.layout.simple_list_item_1,data);
            u_disk_list.setAdapter(arrayAdapter);

2.Storage文件列表讀取

實現了u盤的文件列表讀取,再來研究下Android系統內部存儲的文件列表讀取。同樣的,第一步就是要拿到內部存儲根目錄的路徑。

而在讀取storage的文件列表前也是跟u盤操作一樣要先獲取到storage存儲權限。這裏又到了一個重點了,在Android sdk23之前,只要再AndroidManifest.xml中有這麼兩句就可以了。

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

而到了23以後,必須再手動去獲取一下權限

        int permission = ActivityCompat.checkSelfPermission(MainActivity.this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE);
        if (permission != PackageManager.PERMISSION_GRANTED) {
            // We don't have permission so prompt the user
            ActivityCompat.requestPermissions(MainActivity.this, PERMISSIONS_STORAGE,
                    REQUEST_EXTERNAL_STORAGE);
        }

除此之外,這裏再稍微講解一下Android系統的內部存儲與外部存儲,在以前的Android系統下,即4.4版本以前,就像我們的電腦一樣理解,電腦的硬盤算是內部存儲,而插入的移動硬盤算是外部存儲,而對於Android系統來說,系統的內部空間算內部存儲,插入的sd卡算外部存儲。

而在Android4.4以後,由於科技的發展,各種的Android機子都擴展了自己的機身存儲,比如8G,16G,到現在的64G 128G及以上。

這個在物理上也算是機身本身的內部存儲,因爲它是直接集成在Android機子裏的,但是在概念的叫法上變成了“外部存儲”,與sd卡一樣,原來Android系統內部的空間還是稱爲內部存儲。

不懂我解釋的大家能不能理解,總得來說就是4.4以後,Android的存儲分爲“內部存儲”與“外部存儲”,機身自帶的32G 64G的存儲在物理上確實是“內部”,但是它仍被稱爲“外部存儲”,與sd卡一樣。也就是說在4.4以後,即使你不插sd卡(現在也很少用sd卡了),它也是存在外部存儲的。

private final String storagePath = Environment.getExternalStorageDirectory().getAbsolutePath().toString();

這樣拿到的路徑應該是,/storage/emulated/0 這麼個路徑。

拿到存儲路徑就完了嗎?到這裏我運行發現一直報permission deny的錯誤,明明我有手動獲取了權限的啊,甚至我還打開的設置》應用》權限,在裏面確保了storage的權限開啓,爲什麼還是會報這樣的錯誤呢?
原來是因爲我使用的是Android10.0的系統,10.0有一個新特性。

在Android Q中引入了分區儲存功能,在外部存儲設備中爲每個應用提供了一個“隔離存儲沙盒”。其他應用無法直接訪問應用的沙盒文件。由於文件是應用的私有文件,不再需要任何權限即可訪問和保存自己的文件。此變更並有助於減少應用所需的權限數量,同時保證用戶文件的隱私性。Android Q 更改了應用對設備外部存儲設備中的文件(如:/sdcard )的訪問方式。

繼續使用 READ_EXTERNAL_STORAGE 和 WRITE_EXTERNAL_STORAGE 權限,只不過當擁有這些權限的時候,你只能訪問媒體文件,無法訪問其他文件。

有這麼一個方法可以選擇停用分區存儲,在AndroidManifest中添加android:requestLegacyExternalStorage=“true”。
果然,問題解決了!

            List list = new ArrayList<>();
            File storagefile = new File(storagePath);
            File[] files = storagefile.listFiles();
            if (null != files && files.length > 0) {
                for (File file : files) {
                    Log.d(TAG, "File: "+file.getName());
                    list.add(file.getName());
                }
            }
            final String[] data = new String[list.size()];
            for(int i=0;i<list.size();i++){
                data[i] = String.valueOf(list.get(i));
            }
            ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(
                    MainActivity.this,android.R.layout.simple_list_item_1,data);
            storage_list.setAdapter(arrayAdapter);

同樣的,通過ListView把文件列表給顯示出來。

三.通過文件列表進入文件,進行文本文件的讀取及寫入數據操作

這裏有分成兩個模塊,一個是u盤文本文件的讀寫數據操作,一個是Storage文本文件的讀寫數據操作。

1.U盤文本文件的讀寫操作

(1)U盤文本文件的數據讀取

首先,來說說u盤的,通過點擊ListView,進入新的activity並把所選的文件名傳過去。

u_disk_list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    if(data[position].endsWith(".txt")) {
                        Intent intent = new Intent(MainActivity.this, UDiskReadAndWriteTxt.class);
                        intent.putExtra("filename", data[position]);
                        startActivity(intent);
                    }         
            });

再到新的activity拿到傳過來的文件名

        Intent intent = getIntent();
        mU_DISK_FILE_NAME = intent.getStringExtra("filename");

然後是兩個操作,讀取和寫入,先講讀取。思路就是在u盤根目錄的文件下遍歷找到傳過來的文件名的文本文件

            UsbFile[] usbFiles = new UsbFile[0];
            try {
                usbFiles = cFolder.listFiles();
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (null != usbFiles && usbFiles.length > 0) {
                for (UsbFile usbFile : usbFiles) {
                    Log.d(TAG, "usbFile: "+usbFile.getAbsolutePath());
                    if (usbFile.getName().equals(mU_DISK_FILE_NAME)) {
                        readTxtFromUDisk(usbFile);
                    }
                }
            }

拿到usbFile以後,通過文件流InputStream來進行讀取。

        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 = sb;
            mHandler.sendMessage(msg);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (bufferedReader != null) {
                    bufferedReader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

我採用的方法是統一使用一個Handler來進行數據的接收。

            switch (msg.what) {
                case 101:
                    showToastMsg("讀取成功");
                    String txt = msg.obj.toString();
                    if (!TextUtils.isEmpty(txt))
                        u_disk_edt.setText(txt);
                    break;
            }

(2)U盤文本文件的數據寫入

先想想思路,跟讀取數據一樣,遍歷u盤的根目錄文件,找到傳過來的文件名的文本文件,然後進行輸入框傳過來的數據寫入。

            try {
                //獲取根目錄的文件
                UsbFile[] usbFiles = cFolder.listFiles();
                //如果有文件則遍歷文件列表
                if (usbFiles != null && usbFiles.length > 0) {
                    for (UsbFile file : usbFiles) {
                        Log.d(TAG, "file: "+file.getName());
                        if (file.getName().equals(mU_DISK_FILE_NAME)) {
                            OutputStream os = new UsbFileOutputStream(file);
                            os.write(content.getBytes());
                            os.close();
                        }
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            mHandler.sendEmptyMessage(100);

這塊的代碼,文件遍歷上與讀取時一樣,匹配完文件名以後通過OuputStream文件流來寫入數據。
寫入成功後,提示信息,“保存成功”

            switch (msg.what) {
                case 100:
                    showToastMsg("保存成功");
                    break;
            }

2.Storage文本文件的讀寫操作

(1)Storage文本文件的數據讀取

思路與u盤文本文件的讀取基本一致,不同在於不用去遍歷文件來獲取usbFile文件,只需要拿到文件的路徑,直接就可以拿到文件。
其中file就是Storage中文本文件的路徑。

File txtFile = new File(file);
            //讀取文件內容
            InputStream is = null;
            try {
                is = new FileInputStream(txtFile);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            //讀取祕鑰中的數據進行匹配
            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 = sb;
                mHandler.sendMessage(msg);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    if (bufferedReader != null) {
                        bufferedReader.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

(2)Storage文本文件的數據寫入

這一塊沒啥好講的,就把Storage的讀取與u盤的寫入結合一下就出來了。

            FileOutputStream fos = null;
            File txtFile = new File(file);
            try {
                fos = new FileOutputStream(txtFile);
                fos.write(content.getBytes());
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                if (fos != null) {
                    try {
                        fos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            mHandler.sendEmptyMessage(100);

四.通過文件列表進入文件,進行圖片的讀取操作

其實寫完上面的功能,這個應用的基礎功能就已經完成了,做到了對u盤拔插的監聽,對u盤設備的讀取,對u盤及Storage文件列表的讀取,文本文件的讀寫。讀取圖片這個功能,是我在網上沒有看到過的功能,而且之前也沒有接觸過圖片的讀取,更不用說對u盤裏圖片的讀取了。
那麼就開始研究吧,先看看圖片應該怎麼讀取出來?
通過ImageView的setImageBitmap()方法就可以把圖片讀取出來,而傳入的參數是Bitmap,那麼就是要獲取到圖片的Bitmap。

1.u盤圖片的讀取

一開始的工作與之前一樣,先遍歷U盤文件拿到usbFile,使用關鍵點在於,使用BufferedInputStream採用緩存的方式來讀取圖片,再使用BitmapFactory.decodeStream來解碼圖片,拿到Bitmap。

        UsbFile imgFile = usbFile;
        Bitmap bitmap = null;
        try {
            BufferedInputStream bis = new BufferedInputStream(new UsbFileInputStream(usbFile));
            bitmap = BitmapFactory.decodeStream(bis);
            bis.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        Message msg = mHandler.obtainMessage();
        msg.what = 102;
        msg.obj = bitmap;
        mHandler.sendMessage(msg);

拿到了Bitmap後,用ImageView的setImageBitmap()方法進行圖片的顯示。

            switch (msg.what) {
                case 102:
                    showToastMsg("讀取成功");
                    Bitmap bitmap = (Bitmap) msg.obj;
                    u_disk_img_show.setImageBitmap(bitmap);
                    break;
            }

2.Storage圖片的讀取

搞定了u盤圖片的讀取,那Storage的讀取就不在話下了。
可以直接上代碼了。

        File imgFile = new File(file);
        Bitmap bitmap = null;
        try {
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(imgFile));
            bitmap = BitmapFactory.decodeStream(bis);
            bis.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        Bitmap bitmapImg = bitmap;

        Message msg = mHandler.obtainMessage();
        msg.what = 102;
        msg.obj = bitmapImg;
        mHandler.sendMessage(msg);

五.實現文本文件與圖片在U盤與Storage之間的複製操作

1.實現文本文件在U盤與Storage之間的複製操作

(1)從U盤複製文本文件到Storage

複製操作與寫入數據操作有寫不同,寫入是在已有的文本文件下進行數據的寫入,而複製要做到的是先在U盤中讀取出要複製的文本文件的內容,再在Storage創建文本文件,把讀取到的內容寫入。
不過在複製前還需要對Storage中的文件遍歷進行判斷,看是否已存在了要複製的文件。

            Boolean flag = false;
            File storagefile = new File(storagePath);
            File[] files = storagefile.listFiles();
            if (null != files && files.length > 0) {
                for (File file : files) {
                    if(file.getName().equals(fileName)){
                        showToastMsg("寫入失敗,文本已存在");
                        flag = true;
                    }
                }
            }

            if(flag == false){
                UsbFile[] usbFiles = new UsbFile[0];
                try {
                    usbFiles = cFolder.listFiles();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (null != usbFiles && usbFiles.length > 0) {
                    for (UsbFile usbFile : usbFiles) {
                        Log.d(TAG, "usbFile: "+usbFile.getAbsolutePath());
                        if (usbFile.getName().equals(fileName)) {
                            //讀取文件內容
                            InputStream is = new UsbFileInputStream(usbFile);
                            //讀取祕鑰中的數據進行匹配
                            StringBuilder sb = new StringBuilder();
                            BufferedReader bufferedReader = null;
                            try {
                                bufferedReader = new BufferedReader(new InputStreamReader(is));
                                String read;
                                while ((read = bufferedReader.readLine()) != null) {
                                    sb.append(read);
                                }
                            } catch (Exception e) {
                                e.printStackTrace();
                            } finally {
                                try {
                                    if (bufferedReader != null) {
                                        bufferedReader.close();
                                    }
                                    if(is != null){
                                        is.close();
                                    }
                                } catch (IOException e) {
                                    e.printStackTrace();
                                }
                            }
                            FileOutputStream fos = null;
                            File txtFile = new File(internalDir);
                            try {
                                fos = new FileOutputStream(txtFile);
                                fos.write(sb.toString().getBytes());
                            } catch (FileNotFoundException e) {
                                e.printStackTrace();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }finally {
                                if (fos != null) {
                                    try {
                                        fos.close();
                                    } catch (IOException e) {
                                        e.printStackTrace();
                                    }
                                }
                            }
                        }
                    }
                }
            }

            mHandler.sendEmptyMessage(102);

(2)從Storage複製文本文件到U盤

有了上面的經驗,這裏的思路就是反向一下即可。
直接上代碼了。

            Boolean flag = false;
            UsbFile usbFile = null;
            try {
                //獲取根目錄的文件
                UsbFile[] usbFiles = cFolder.listFiles();
                //如果有文件則遍歷文件列表
                if (usbFiles != null && usbFiles.length > 0) {
                    for (UsbFile file : usbFiles) {
                        Log.d(TAG, "file: "+file.getName());
                        if (file.getName().equals(mU_DISK_FILE_NAME)) {
                            showToastMsg("寫入失敗,文本已存在");
                            flag = true;
                        }
                    }
                }
                //若所需文件未存在,創建所需文件
                if (flag == false){
                    FileInputStream fis = new FileInputStream(new File(txtFile));
                    StringBuilder sb = new StringBuilder();
                    BufferedReader bufferedReader = null;
                    try {
                        bufferedReader = new BufferedReader(new InputStreamReader(fis));
                        String read;
                        while ((read = bufferedReader.readLine()) != null) {
                            sb.append(read);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        try {
                            if (bufferedReader != null) {
                                bufferedReader.close();
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    usbFile = cFolder.createFile(uDiskFileName);
                    OutputStream os = new UsbFileOutputStream(usbFile);
                    os.write(sb.toString().getBytes());
                    os.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            mHandler.sendEmptyMessage(102);
        }else {
            storage_message.setText("必須插入可用U盤纔可寫入數據");
        }

2.實現圖片文件在U盤與Storage之間的複製操作

(1)從U盤複製到Storage

思路上與文本文件是一樣的,區別就在於文件的讀取方式不同,圖片採用的是BufferedInputStream和BufferedOutputStream的方式進行讀取和寫入。

            Boolean flag = false;
            UsbFile usbFile = null;
            try {
                File storagefile = new File(storagePath);
                File[] files = storagefile.listFiles();
                if (null != files && files.length > 0) {
                    for (File file : files) {
                        if(file.getName().equals(fileName)){
                            showToastMsg("圖片已經存在");
                            flag = true;
                        }
                    }
                }
                //若所需文件未存在,創建所需文件
                if(flag == false){
                    //獲取根目錄的文件
                    UsbFile[] usbFiles = cFolder.listFiles();
                    //如果有文件則遍歷文件列表
                    if (usbFiles != null && usbFiles.length > 0) {
                        for (UsbFile file : usbFiles) {
                            Log.d(TAG, "file: "+file.getName());
                            if (file.getName().equals(fileName)) {
                                BufferedInputStream bis = new BufferedInputStream(new UsbFileInputStream(file));
                                BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(internalDir));
                                int n= 0;
                                while((n=bis.read())!=-1) { //將圖片讀出存入緩存區
                                    bos.write(n); //圖片寫入緩存區
                                }
                                bos.flush();//刷新緩衝區
                                bis.close();
                                bos.close();
                            }
                        }
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            Message msg = mHandler.obtainMessage();
            msg.what = 101;
            mHandler.sendMessage(msg);

(2)從Storage複製到U盤

沒什麼好說的,直接上代碼。

            Boolean flag = false;
            UsbFile usbFile = null;
            try {
                //獲取根目錄的文件
                UsbFile[] usbFiles = cFolder.listFiles();
                //如果有文件則遍歷文件列表
                if (usbFiles != null && usbFiles.length > 0) {
                    for (UsbFile file : usbFiles) {
                        Log.d(TAG, "file: "+file.getName());
                        if (file.getName().equals(fileName)) {
                            showToastMsg("圖片已經存在");
                            flag = true;
                        }
                    }
                }
                //若所需文件未存在,創建所需文件
                if(flag == false){
                    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(internalDir));
                    usbFile = cFolder.createFile(fileName);
                    BufferedOutputStream bos = new BufferedOutputStream(new UsbFileOutputStream(usbFile));
                    int n= 0;
                    while((n=bis.read())!=-1) { //將圖片讀出存入緩存區
                        bos.write(n); //圖片寫入緩存區
                    }
                    bos.flush();//刷新緩衝區
                    bis.close();
                    bos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            Message msg = mHandler.obtainMessage();
            msg.what = 101;
            mHandler.sendMessage(msg);

到此爲止便實現了U盤與Storage之間文本文件及圖片文件的複製操作了

總結

這次的u盤應用開發是我之前完全沒有接觸過的領域,可以說是從0開始研究,先了解Android與usb之間的api有哪些,通過查閱資料大概瞭解到需要什麼樣的功能,瞭解到超牛逼的libaums庫,通過閱讀libaums的英文介紹學會使用u盤文件系統;重新學習了一邊Android的文件寫入讀取,接觸到了圖片的讀取寫入。

可以說這次的應用開發給我自己帶來的提升是全方位的,不僅是在寫代碼上,更多的是自學研究能力的提升。

這個應用可能還不是很成熟,存在有很多問題,希望有看到的人可以與我交流探討,我很樂意與需要的人一起分享問題的解決。

原文地址:https://blog.csdn.net/weixin_38737818/article/details/103893358

最後

Android學習是一條漫長的道路,我們要學習的東西不僅僅只有表面的 技術,還要深入底層,弄明白下面的 原理,只有這樣,我們才能夠提高自己的競爭力,在當今這個競爭激烈的世界裏立足。

常言:種一棵樹最好的時間有兩個,一個是十年前,另一個就是現在。

千里之行始於足下,願你我共勉。

本文在開源項目:https://github.com/xieyuliang/Note-Android中已收錄,裏面包含不同方向的自學編程路線、面試題集合/面經、及系列技術文章等,資源持續更新中...

這次就分享到這裏吧,下篇見

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章