Android獲得所有存儲(chǔ)設(shè)備位置的最佳方法
本方式可以獲得內(nèi)部存儲(chǔ)設(shè)備地址、SD卡地址、USB設(shè)備地址,兼容性能達(dá)到99%(別問我為什么這么保證,因?yàn)槭墙梃b了Android設(shè)置->存儲(chǔ)頁面的源碼)。
由于調(diào)用了幾個(gè)被@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反射調(diào)用getVolumeState函數(shù),而不應(yīng)該用StorageVolume的getState方法,因?yàn)榭赡軙?huì)報(bào)錯(cuò)
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;
}
這里需要注意,可能有小伙伴會(huì)問,既然StorageVolume類有g(shù)etState方法,為啥還要用StorageManager反射調(diào)用getVolumeState方法,并傳入path地址,而在源碼里,StorageManager的getVolumeState的方法的實(shí)現(xiàn),也是將path重新創(chuàng)建為StorageVolume類,然后再調(diào)用其getState方法,我們這樣做成這不是多此一舉嗎?
源碼截圖如下:

答案當(dāng)然不是了,不然我也不會(huì)放棄性能去反射那個(gè)方法去裝這個(gè)逼了。主要原因是@hide的這個(gè)方法里,mountPoint被重新打包成StorageVolume時(shí),這相當(dāng)于系統(tǒng)去創(chuàng)建的一個(gè)StorageVolume實(shí)例,自然可以執(zhí)行它的所有方法。而如果是應(yīng)用直接調(diào)用,在被打包時(shí),很多方法被隱藏了,比如這個(gè)getState方法,這時(shí)候應(yīng)用就會(huì)報(bào)錯(cuò),找不到該方法。
先簡單寫到這,以后有補(bǔ)充再添加。
以上這篇Android獲得所有存儲(chǔ)設(shè)備位置的最佳方法就是小編分享給大家的全部內(nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Android編程實(shí)現(xiàn)實(shí)時(shí)監(jiān)聽EditText文本輸入的方法
這篇文章主要介紹了Android編程實(shí)現(xiàn)實(shí)時(shí)監(jiān)聽EditText文本輸入的方法,結(jié)合實(shí)例形式分析了EditText控件及事件響應(yīng)相關(guān)操作技巧,需要的朋友可以參考下2017-06-06
Android實(shí)現(xiàn)局部圖片滑動(dòng)指引效果示例
現(xiàn)在滑動(dòng)效果用的比較多,尤其是在手機(jī)端上面,本文介紹了Android實(shí)現(xiàn)局部圖片滑動(dòng)指引效果示例,現(xiàn)在就分享給大家,也給大家做個(gè)參考。2016-10-10
android上一個(gè)可追蹤代碼具體到函數(shù)某行的日志類
追蹤代碼到函數(shù)具體某行,這樣的功能,是每一個(gè)程序員都希望會(huì)有的,因?yàn)樗梢詭椭覀冏粉櫟侥承写a的錯(cuò)誤,接下來介紹下android上一個(gè)可追蹤代碼到函數(shù)具體某行的日志類,希望對開發(fā)者有所幫助2012-12-12
Kotlin構(gòu)造函數(shù)與成員變量和init代碼塊執(zhí)行順序詳細(xì)講解
這篇文章主要介紹了Kotlin構(gòu)造函數(shù)與成員變量和init代碼塊執(zhí)行順序,kotlin里面的構(gòu)造函數(shù)分為主構(gòu)造函數(shù)和次構(gòu)造函數(shù)。主構(gòu)造函數(shù)只能有一個(gè),次構(gòu)造函數(shù)個(gè)數(shù)不限制,可以有一個(gè)或者多個(gè)2022-11-11
源碼淺析Android中內(nèi)存泄漏檢測工具Leakcanary的使用
大名鼎鼎的 Leakcanary 想必作為 Android 開發(fā)都多多少少接觸過,新版本的 Leakcanary 也用 Kotlin 重寫了一遍,最近詳細(xì)查看了下源碼,就來和大家簡單分享一下2023-04-04
Android使用Notification實(shí)現(xiàn)通知功能
這篇文章主要為大家詳細(xì)介紹了Android使用Notification實(shí)現(xiàn)通知功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11
Android?使用flow實(shí)現(xiàn)倒計(jì)時(shí)的方式
這篇文章主要介紹了Android?使用flow實(shí)現(xiàn)倒計(jì)時(shí)的方式,借助Flow這個(gè)工具,更加優(yōu)雅地實(shí)現(xiàn)這個(gè)需求功能,文末給大家整理了Android?實(shí)現(xiàn)倒計(jì)時(shí)的幾種方式,需要的朋友可以參考下2022-04-04

