安卓內外部存儲完全解析 -- 別再弄混了

安卓開發(fā)離不開手機存儲盅弛,然而大部分人對于安卓開發(fā)中的存儲概念存在誤區(qū),內部外部SD卡傻傻分不清叔锐?

概念掃盲


以下引用來自對官方文檔的理解

安卓手機的存儲分為 2 部分挪鹏,內部存儲 ( Internal ) 和外部存儲
( External )

呵呵呵,先別說話愉烙,然而重點來了(敲黑板)讨盒,按照官方的說法,

內部存儲是指系統的存儲空間步责,沒有root是訪問不到的呦親返顺,比如sharedPreferenced或者database都是保存在這里面的禀苦。

外部存儲,又分為 2 部分:

  1. 機器自帶的存儲遂鹊,也就是手機廠商常說的16G振乏,32G,64G之類的存儲空間

  2. SD卡秉扑,其實正確叫法應該是TF卡慧邮,就是可插拔的那個小東西

然而現實中,常常有同事把手機那個32G舟陆,64G存儲叫做內部存儲= =误澳,寶寶好累,人家明明是 ExternalStorage G厍忆谓!

希望本篇能讓大家對內外部存儲有一個正確鮮明的認識

常用路徑總結


一. 內部存儲

files目錄

getFilesDir()

路徑如下

/data/user/0/<包名>/files // 7.0手機 不確定是手機原因還是系統原因
/data/data/<包名>/files // 4.0手機

文檔云:若想操作該路徑,你需要一個輸出流:

openFileOutput()

就像這樣:

FileOutputStream output = this.openFileOutput("- -!.txt", Context.MODE_PRIVATE);
byte[] bytes = "我是剛寫入的".getBytes();
output.write(bytes);
output.close();

注: this 是 context 對象

/data/data/<包名>/files/- -!.txt

路徑下會看到新文件哦

如果你還想讀取的話踱承,文檔云:你需要一個輸入流:

FileInputStream input = this.openFileInput("- -!.txt");
byte[] bytess = new byte[input.available()];
String result = "";
while (input.read(bytess, 0, bytess.length) != -1) {
     Log.d("qwer", "result ===>> " + new String(bytess, "UTF-8")); 
}

Log如下

D/qwer: result ===>> 我是剛寫入的

內部緩存目錄

getCacheDir()

文檔云:

如果您想要緩存一些數據倡缠,而不是永久存儲這些數據,應該使用 getCacheDir() 來打開一個 File勾扭,它表示您的應用應該將臨時緩存文件保存到的內部目錄毡琉。

當設備的內部存儲空間不足時,Android 可能會刪除這些緩存文件以回收空間妙色。 但您不應該依賴系統來為您清理這些文件桅滋, 而應該始終自行維護緩存文件,使其占用的空間保持在合理的限制范圍內(例如 1 MB)身辨。 當用戶卸載您的應用時丐谋,這些文件也會被移除

路徑如下:

/data/data/<包名>/cache

特別的,還有getDir() :

getDir("- -!.txt", Context.MODE_PRIVATE).getAbsolutePath()

路徑如下:

/data/data/<包名>/app_- -!.txt

app_是系統自己加上去的

小結

內部存儲就是系統的存儲,沒有root你是看不到的煌珊,內部存儲最大特點就是可以用Context對象調用各個獲取路徑的方法号俐。比如:context.fileList()
那就是

/data/data/<包名>/files

下的文件遍歷。

deleteFile("ABC")就是

/data/data/<包名>/files

刪除下名為 ABC 的文件
</br></br></br>

二. 外部存儲


操作外部存儲你首先需要以下權限

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

當你申請了write權限定庵,那么read權限默認也就通過啦

再判斷狀態(tài):

if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState))

外部存儲的根目錄

Environment.getExternalStorageDirectory()

/storage/emulated/0

這個路徑根據手機廠家不同會有些許變化

外部公共目錄

直接傳入 Environment 中的常量獲取相應的路徑吏饿,如下:

Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_ALARMS));

/storage/emulated/0/Alarms

或者

Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES));

/storage/emulated/0/Pictures

公有目錄下,系統會區(qū)分不同類別(例如鈴聲在系統設置中顯示為鈴聲而不是音樂)

外部私有目錄

當用戶卸載您的應用時蔬浙,此目錄及其內容將被刪除
系統媒體掃描程序不會讀取這些目錄中的文件,但是其他應用依然可以對該目錄下的文件可以讀寫

4.4以后訪問該目錄不再需要權限了

getExternalFilesDir(String type)

/storage/emulated/0/Android/data/<包名>/files/<type>

eg.
getExternalFilesDir(Environment.DIRECTORY_MUSIC)

/storage/emulated/0/Android/data/<包名>/files/Music

特別的:ContextCompat下的

ContextCompat.getExternalFilesDirs(context,type)

返回一個File[]猪落,在4.4以后第一條數據默認外部主存儲目錄,第二條數據就是sd卡路徑啦畴博,但是注意4.4之前是沒有第二條數據的哦

外部緩存目錄

該目錄下的特點是卸載程序后笨忌,該目錄和其下所有文件均會被刪除

getExternalCacheDir()

/storage/emulated/0/Android/data/<包名>/cache

注意,使用該目錄注意管理空間俱病,你不能等系統幫你清理官疲,而是自己清理不再需要的緩存

特別的:ContextCompat下的

ContextCompat.getExternalCacheDirs()

道理同上

內外部路徑匯總一覽

路徑 方法名 所屬
/data/data/<包名>/files getFilesDir() 內部
/data/data/<包名>/cache getCacheDir() 內部
/data/data/<包名>/app_<name> getDir() 內部
/storage/emulated/0 Environment.getExternalStorageDirectory() 外部根目錄
/storage/emulated/0/<type> Environment.getExternalStoragePublicDirectory(type) 外部九大公有目錄
/storage/emulated/0/Android/data/<包名>/files/<type> getExternalFilesDir(type) 外部私有目錄
/storage/emulated/0/Android/data/<包名>/cache getExternalCacheDir() 外部緩存目錄

發(fā)現特點了嗎朋友袱结,無論外部內部,只有路徑中有包名途凫,那么就是私有的垢夹,而且是隨著程序的卸載而被刪除的,有包名的路徑均是Context中的方法颖榜,而公有的路徑均是Environment調用的

SD卡路徑

這個貨真真是要了老命棚饵,一般的方法根部不好使,結合網上有的方法加上公司項目中的方法掩完,總結如下:

百分百好用的獲取SD卡路徑方法:

        try {
            StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
            Method getVolumeList = null;
            getVolumeList = sm.getClass().getDeclaredMethod("getVolumeList");
            Object[] volumeList = (Object[]) getVolumeList.invoke(sm);
            for (Object volume : volumeList) {
                Method getPath = volume.getClass().getDeclaredMethod("getPath");
                Method isRemovable = volume.getClass().getDeclaredMethod("isRemovable");
                String path = (String) getPath.invoke(volume);              
                boolean removable = (Boolean) isRemovable.invoke(volume);
                if (removable) {
                    paths.add(path);
                }
            }
            for (String path : paths) {
                Log.d("qwer", "path = > " + path);
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

最后集合 path 中的值就是SD卡根目錄

/storage/sdcard1

雖然無視版本百分百好用,但是如果你的手機有SD卡槽卻沒插SD卡硼砰,該方法最后 path 返回的是 null 且蓬,也就是說該方法無法判斷到底是沒插SD卡還是根本不支持SD卡

其實還有一種方法

String path = System.getenv("SECONDARY_STORAGE");

該方法只要你手機支持SD卡,無論你插沒插SD卡题翰,均會返回SD卡路徑恶阴,但是6.0及以上該方法被移除

Environment中源碼其實就是根據這個方法獲取路徑的

安卓官方文檔大家一定要看,他就是我們開發(fā)者的權威呀豹障,圣經呀7胧隆!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末血公,一起剝皮案震驚了整個濱河市昵仅,隨后出現的幾起案子,更是在濱河造成了極大的恐慌累魔,老刑警劉巖摔笤,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異垦写,居然都是意外死亡吕世,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門梯投,熙熙樓的掌柜王于貴愁眉苦臉地迎上來命辖,“玉大人,你說我怎么就攤上這事分蓖《В” “怎么了?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵咆疗,是天一觀的道長漓帚。 經常有香客問我,道長午磁,這世上最難降的妖魔是什么尝抖? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任毡们,我火速辦了婚禮,結果婚禮上昧辽,老公的妹妹穿的比我還像新娘衙熔。我一直安慰自己,他們只是感情好搅荞,可當我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布红氯。 她就那樣靜靜地躺著,像睡著了一般咕痛。 火紅的嫁衣襯著肌膚如雪痢甘。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天茉贡,我揣著相機與錄音塞栅,去河邊找鬼。 笑死腔丧,一個胖子當著我的面吹牛放椰,可吹牛的內容都是我干的。 我是一名探鬼主播愉粤,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼砾医,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了衣厘?” 一聲冷哼從身側響起如蚜,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎头滔,沒想到半個月后怖亭,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡坤检,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年兴猩,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片早歇。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡倾芝,死狀恐怖,靈堂內的尸體忽然破棺而出箭跳,到底是詐尸還是另有隱情晨另,我是刑警寧澤,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布谱姓,位于F島的核電站借尿,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜路翻,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一狈癞、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧茂契,春花似錦蝶桶、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至厌小,卻和暖如春恢共,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背召锈。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工旁振, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人涨岁。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像吉嚣,于是被迫代替她去往敵國和親梢薪。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內容