在Android中,你是不是只會(huì)在根目錄下存文件耿币?靠著一行代碼走天下:
String absolutePath = Environment.getExternalStorageDirectory().getAbsolutePath();
很多人搞不明白Android中的存儲(chǔ)路徑梳杏,我們大概只知道內(nèi)部存儲(chǔ)和外部存儲(chǔ),然而這兩個(gè)路徑究竟在哪里淹接?什么路徑需要權(quán)限十性,什么路徑不需要權(quán)限?Android到底給我們準(zhǔn)備了多少路徑供我們使用塑悼?你能準(zhǔn)確的調(diào)用這些API嗎劲适?
如果你能準(zhǔn)確的回答這些問題,那么請(qǐng)忽略本篇帖子
讓我們先來說內(nèi)部存儲(chǔ)厢蒜,這個(gè)也比較容易理解
內(nèi)部存儲(chǔ)霞势,位于data/data/包名/路徑下
對(duì)于設(shè)備中每一個(gè)安裝的 App,系統(tǒng)都會(huì)在 data/data 目錄下自動(dòng)創(chuàng)建與之對(duì)應(yīng)的文件夾斑鸦。這個(gè)文件夾用于 App 中的 WebView 緩存頁面信息愕贡,SharedPreferences 和 SQLiteDatabase 持久化應(yīng)用相關(guān)數(shù)據(jù)等。
一圖勝千言
大家知道Android系統(tǒng)是基于Linux的操作系統(tǒng)巷屿,所以文件系統(tǒng)也借鑒了Linux的固以。data就是系統(tǒng)根目錄下的的一個(gè)文件夾,而第二個(gè)data就是專門讓各種App存儲(chǔ)內(nèi)部數(shù)據(jù)的嘱巾。
data/data/是為所有App準(zhǔn)備的內(nèi)部存儲(chǔ)空間憨琳,怎么對(duì)這些數(shù)據(jù)加以區(qū)分呢?往下看??
第二個(gè)data展開后會(huì)有很多以包名命名的目錄浓冒,每個(gè)包名都對(duì)應(yīng)一個(gè)App的內(nèi)部存儲(chǔ)空間栽渴,即我們常說的內(nèi)部存儲(chǔ)空間尖坤,別的App是斷然無法訪問到的稳懒。圖中紅框是本篇帖子的示例App的目錄。
可以看到,假如我們只是創(chuàng)建了一個(gè)App场梆,那么在內(nèi)部存儲(chǔ)空間中(本篇以后所有的內(nèi)部存儲(chǔ)空間都專指App的內(nèi)部存儲(chǔ))墅冷,系統(tǒng)默認(rèn)只給我們創(chuàng)建了一個(gè)cache文件夾,這個(gè)是讓我們用來存放App的緩存數(shù)據(jù)
現(xiàn)在我們進(jìn)行下列操作
SharedPreferences test_sp = getSharedPreferences("test_sp", MODE_PRIVATE);
我們?cè)賮砜椿蛴停覀兊膬?nèi)部存儲(chǔ)下有什么目錄
可以看到寞忿,在上述代碼執(zhí)行后,系統(tǒng)在我們的內(nèi)部存儲(chǔ)中創(chuàng)建了shared_prefs
目錄顶岸,但是這個(gè)目錄是空的腔彰,并沒有創(chuàng)建對(duì)應(yīng)的sp文件
現(xiàn)在我們把代碼補(bǔ)全
SharedPreferences test_sp = getSharedPreferences("test_sp", MODE_PRIVATE);
SharedPreferences.Editor edit = test_sp.edit();
edit.putString("test", "test");
edit.commit();
現(xiàn)在再來看??
終于看到我們熟悉的sp文件了
- 內(nèi)部存儲(chǔ)位于data/data/包名/路徑下
- 系統(tǒng)默認(rèn)只在內(nèi)部存儲(chǔ)中創(chuàng)建cache目錄,并且此時(shí)cache目錄是空的
-
getSharedPreferences()
會(huì)讓系統(tǒng)在內(nèi)部存儲(chǔ)中創(chuàng)建shared_prefs
目錄辖佣,但不會(huì)創(chuàng)建sp文件,只有在sp文件中存儲(chǔ)了值霹抛,系統(tǒng)才會(huì)創(chuàng)建sp文件 -
sp文件
位于shared_prefs
目錄下
那么?我們的數(shù)據(jù)庫文件存儲(chǔ)在哪里呢卷谈?
現(xiàn)在我們創(chuàng)建一個(gè)數(shù)據(jù)庫文件
TestDBHelper helper = new TestDBHelper(MainActivity.this, "test_db.db", null, 1);
SQLiteDatabase database = helper.getWritableDatabase();
TestDBHelper
的創(chuàng)建請(qǐng)自行了解
可以看到杯拐,系統(tǒng)會(huì)自動(dòng)在內(nèi)部存儲(chǔ)中創(chuàng)建
databases
目錄,而我們創(chuàng)建的test_db.db
文件則位于該目錄下接下來我們看看WebView的緩存問題
public class WebActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout linearLayout = new LinearLayout(this);
WebView webView = new WebView(this);
linearLayout.addView(webView,LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT);
webView.loadUrl("http://www.baidu.com");
setContentView(linearLayout);
}
}
啟動(dòng)WebActivity
等頁面渲染出來以后我們查看內(nèi)部存儲(chǔ)路徑中的目錄有什么變化
可以看到世蔗,系統(tǒng)一次為我們創(chuàng)建了
app_textures
端逼、app_webview
、org.chromium.android_webview
三個(gè)文件夾污淋,而這三個(gè)文件夾的路徑如上圖所示顶滩,每個(gè)文件夾下的內(nèi)容我們也看不懂,可以確認(rèn)的是這里面的東西都是跟WebView緩存相關(guān)的寸爆。需要注意的是
org.chromium.android_webview
這個(gè)文件夾是位于cache
目錄下的诲祸。到目前為止,我們知道了
sp文件而昨、數(shù)據(jù)庫文件救氯、webView的緩存文件
在內(nèi)部存儲(chǔ)中的具體路徑,并且這些路徑都是由系統(tǒng)創(chuàng)建的歌憨,也就是說我們并不能操作該路徑着憨,例如,我們無法在databases路徑下存放其他文件务嫡,也沒有辦法把數(shù)據(jù)庫文件放到shared_prefs目錄下那么甲抖,我們就只能在內(nèi)部存儲(chǔ)中存放這三種文件嗎?
答案是否定的
現(xiàn)在來調(diào)這個(gè)API
//這個(gè)是Context對(duì)象的方法
//返回一個(gè)File對(duì)象心铃,這個(gè)對(duì)象的路徑是data/data/包名/files/
File filesDir = getFilesDir();
String absolutePath = filesDir.getAbsolutePath();
與其他目錄相同准谚,該目錄也不會(huì)自動(dòng)創(chuàng)建,只有我們調(diào)用了相應(yīng)的API的時(shí)候系統(tǒng)才會(huì)為我們創(chuàng)建對(duì)應(yīng)的目錄,不管此時(shí)該
現(xiàn)在我們?cè)谠撃夸洠?code>files)下創(chuàng)建兩個(gè)文件
try {
File filesDir = getFilesDir();
File txtFile = new File(filesDir,"test.txt");
File imgFile = new File(filesDir,"test.jpg");
txtFile.createNewFile();
imgFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
我們看目錄中的文件??
可以看到去扣,files目錄以及我們創(chuàng)建的兩份文件已經(jīng)如期在內(nèi)部存儲(chǔ)中了
現(xiàn)在我們來獲取內(nèi)部存儲(chǔ)路徑下的cache目錄
//這個(gè)是Context對(duì)象的方法
//返回一個(gè)File對(duì)象柱衔,這個(gè)對(duì)象的路徑是data/data/包名/files/
File cacheDir = getCacheDir();
String absolutePath = cacheDir.getAbsolutePath();
注意
File cacheDir = getCacheDir();
與File filesDir = getFilesDir();
有什么區(qū)別?
答案是:當(dāng)手機(jī)的內(nèi)部存儲(chǔ)空間比較低的時(shí)候,cache文件夾下的文件有可能會(huì)被刪除唆铐。api中同時(shí)注明了哲戚,你不要指望系統(tǒng)會(huì)幫你刪除此文件夾,你應(yīng)該自己設(shè)定一個(gè)閥值艾岂,每次存儲(chǔ)的時(shí)候檢測(cè)一下顺少。
在手機(jī)的應(yīng)用管理器中,每個(gè)應(yīng)用都有一個(gè)clearData和clearCache
第一個(gè)按鈕清除的是整個(gè)應(yīng)用的內(nèi)部存儲(chǔ)數(shù)據(jù)
第二個(gè)按鈕清除的是cache路徑下的數(shù)據(jù)
一王浴、內(nèi)部存儲(chǔ)的路徑在data/data/包名/路徑下
二脆炎、內(nèi)部存儲(chǔ)路徑中的文件是分類存儲(chǔ)的,我們無法干涉氓辣,除了cache目錄腕窥,別的目錄系統(tǒng)不會(huì)自動(dòng)創(chuàng)建
三、除了files目錄筛婉,別的目錄我們幾乎都是無法手動(dòng)操作的
四簇爆、別的App幾乎無法訪問內(nèi)部存儲(chǔ)中的數(shù)據(jù),除了用非法手段或者我們主動(dòng)暴露
五爽撒、內(nèi)部存儲(chǔ)目錄下的文件夾及文件會(huì)隨著app的卸載而被系統(tǒng)自動(dòng)刪除
//在本App的內(nèi)部存儲(chǔ)中創(chuàng)建一個(gè)文件入蛆,這個(gè)文件的路徑為data/data/packageName/文件名
//但是在測(cè)試的時(shí)候發(fā)現(xiàn)系統(tǒng)實(shí)際創(chuàng)建了一個(gè)app_test的文件
File test = getDir("test", MODE_PRIVATE);
//獲取本App的內(nèi)部存儲(chǔ)目錄,這個(gè)路徑是data/data/packageName/
//但是這個(gè)Api從24開始才有
File dataDir = getDataDir();
//在本App內(nèi)部存儲(chǔ)中創(chuàng)建一個(gè)文件
File dirs = new File(dataDir,"test");
if (!dirs.exists()) {
dirs.createNewFile();
}
//獲取內(nèi)部存儲(chǔ)的cache目錄
File cacheDir = getCacheDir();
//在cacahe目錄中創(chuàng)建一個(gè)文件
File myCacheFile = new File(cacheDir,"myCachefile");
if (!myCacheFile.exists()) {
myCacheFile.createNewFile();
}
//直接獲取內(nèi)部存儲(chǔ)中databases目錄下的數(shù)據(jù)庫文件
File databasePath = getDatabasePath("test2.db");
//在databases目錄下創(chuàng)建該文件
//ps:感覺不到這個(gè)Api存在的意義硕勿,因?yàn)槲覀儎?chuàng)建數(shù)據(jù)庫文件應(yīng)該使用SQLiteOpenHelper類
//不過我們可以利用這個(gè)方法在databases目錄中創(chuàng)建別的文件哨毁,但是這樣做并不好
if (!databasePath.exists()) {
databasePath.createNewFile();
}
//獲取內(nèi)部存儲(chǔ)的根目錄,這個(gè)路徑是/data
File dataDirectory = Environment.getDataDirectory();
//這個(gè)目錄我們沒有操作權(quán)限源武,我都不知道要這個(gè)Api干啥
File file = new File(dataDirectory,"datatest");
if (!file.exists()) {
file.createNewFile();
}
到此扼褪,Android中的內(nèi)部存儲(chǔ)就全部結(jié)束了,相信你應(yīng)該對(duì)內(nèi)部存儲(chǔ)了解的比較透徹了粱栖。