本方式可以獲得內部存儲設備地址、SD卡地址、USB設備地址,兼容性能達到99%(別問我為什么這么保證,因為是借鑒了Android設置->存儲頁面的源碼)。
由于調用了幾個被@hide的方法,所以采用了反射。
具體代碼如下:
public static List<HomeDirBean> getAllExternalStorage(Context context) { List<HomeDirBean> storagePath = new ArrayList<>(); StorageManager storageManager = (StorageManager) context.getSystemService(STORAGE_SERVICE); StorageVolume[] storageVolumes; try { Method getVolumeList = StorageManager.class.getDeclaredMethod("getVolumeList"); storageVolumes = (StorageVolume[]) getVolumeList.invoke(storageManager); Method getVolumeState = StorageManager.class.getDeclaredMethod("getVolumeState", String.class); for (StorageVolume storageVolume : storageVolumes) { String desc = storageVolume.getDescription(context); Log.i(TAG, "storageVolume name--->" + desc); Method getPath = StorageVolume.class.getMethod("getPath"); String path = (String) getPath.invoke(storageVolume); Log.i(TAG, "StoragePath--->" + path); //這里需要用StorageManager反射調用getVolumeState函數,而不應該用StorageVolume的getState方法,因為可能會報錯 String state = (String) getVolumeState.invoke(storageManager, path); Log.i(TAG, "storageVolume State--->" + state); if (Environment.MEDIA_MOUNTED.equals(state)) { HomeDirBean bean = new HomeDirBean(path, desc); storagePath.add(bean); } } } catch (Exception e) { Log.e(TAG, e.getMessage()); } return storagePath; }
這里需要注意,可能有小伙伴會問,既然StorageVolume類有getState方法,為啥還要用StorageManager反射調用getVolumeState方法,并傳入path地址,而在源碼里,StorageManager的getVolumeState的方法的實現,也是將path重新創建為StorageVolume類,然后再調用其getState方法,我們這樣做成這不是多此一舉嗎?
源碼截圖如下:
答案當然不是了,不然我也不會放棄性能去反射那個方法去裝這個逼了。主要原因是@hide的這個方法里,mountPoint被重新打包成StorageVolume時,這相當于系統去創建的一個StorageVolume實例,自然可以執行它的所有方法。而如果是應用直接調用,在被打包時,很多方法被隱藏了,比如這個getState方法,這時候應用就會報錯,找不到該方法。
先簡單寫到這,以后有補充再添加。
以上這篇Android獲得所有存儲設備位置的最佳方法就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持VEVB武林網。
新聞熱點
疑難解答