Android如何正確的保存應(yīng)用數(shù)據(jù)
在Android官方開發(fā)文檔中有一篇文檔來(lái)介紹如何保存應(yīng)用的數(shù)據(jù), 但筆者用過很多程序(從知名的到不知名的)處理的都不是很完美,或者沒有按照Android開發(fā)團(tuán)隊(duì)建議的方式去保存他們應(yīng)用的數(shù)據(jù)。當(dāng)一些試用過的軟件卸載后,在SDCard中還保留了這些軟件的文件目錄,時(shí)間一長(zhǎng)就有很多目錄需要手工去清理,并且很難確認(rèn)那些目錄是仍然在使用的那些目錄已經(jīng)沒用了,給用戶帶來(lái)困擾。這里我們來(lái)討論下該如何正確的保存應(yīng)用的數(shù)據(jù)。
首先數(shù)據(jù)分為兩種:和應(yīng)用相關(guān)的數(shù)據(jù);和應(yīng)用無(wú)關(guān)的數(shù)據(jù)。這里分別介紹:
應(yīng)用無(wú)關(guān)的數(shù)據(jù)是那些用戶比較關(guān)心的數(shù)據(jù),不管您的應(yīng)用在不在用戶設(shè)備上,這些數(shù)據(jù)用戶都希望保留,這些數(shù)據(jù)包含:用相機(jī)拍攝的照片、用瀏覽器(下載工具)下載的文件、用戶制作的個(gè)性鈴聲等。
假設(shè)您開發(fā)了一個(gè)照相應(yīng)用(例如: 360相機(jī)),用戶用您的應(yīng)用拍攝并處理過的照片就屬于應(yīng)用無(wú)關(guān)的數(shù)據(jù),如果用戶把您的應(yīng)用給卸載了,用戶還是會(huì)期望仍然保留他們拍攝并處理過的照片。這里的照片按照Android官方的建議應(yīng)該保存到 DIRECTORY_PICTURES 目錄中,該目錄通過Environment.getExternalStoragePublicDirectory(String type)來(lái)獲取,您可以在該目錄下創(chuàng)建一個(gè)以您的程序命名的目錄來(lái)保存數(shù)據(jù)。其他支持的目錄列表請(qǐng)參考這里。
應(yīng)用相關(guān)的數(shù)據(jù): 這種數(shù)據(jù)只和您的應(yīng)用相關(guān),如果您的應(yīng)用被用戶刪除了這些數(shù)據(jù)也沒有理由還存在用戶設(shè)備中。這種數(shù)據(jù)包含:數(shù)據(jù)庫(kù)文件、屬性配置文件、應(yīng)用的緩存文件等。這種數(shù)據(jù)可以有很多種保存方式,詳情參考這里。
這里我們只討論在API 8(Android 2.2)中新引入了一種保存到外部存儲(chǔ)空間的偽私有數(shù)據(jù)API, 通過函數(shù)getExternalFilesDir() 來(lái)獲取該路徑,同樣可以設(shè)置獲取各種類型數(shù)據(jù)的參數(shù),例如 DIRECTORY_MUSIC 和 DIRECTORY_RINGTONES (如果參數(shù)為null則返回您應(yīng)用數(shù)據(jù)的跟目錄)。比如一個(gè)應(yīng)用的包名為 org.goodev.test 的應(yīng)用,通過函數(shù)getExternalFilesDir(Environment.DIRECTORY_MOVIES)獲取到的文件路徑為 /storage/sdcard0/Android/data/org.goodev.test/files/Movies。
細(xì)心的讀者已經(jīng)發(fā)現(xiàn),該數(shù)據(jù)目錄為SDCard (外部存儲(chǔ)設(shè)備,有可能是內(nèi)置SDCard 比如 Nexus S) 中名字為 Android 的根目錄下,該目錄下有個(gè)用來(lái)保存應(yīng)用數(shù)據(jù)的 data 目錄,在這個(gè) data 目錄中保存了設(shè)備中各個(gè)應(yīng)用的數(shù)據(jù),依包名來(lái)命名,如果設(shè)置參數(shù)為null則返回的是跟目錄:/storage/sdcard0/Android/data/org.goodev.test/files。
為啥這個(gè)目錄我們稱之為偽私有數(shù)據(jù)目錄呢? 因?yàn)樵?.2以上的系統(tǒng)中,當(dāng)您的應(yīng)用被用戶卸載的時(shí)候,保存在這個(gè)目錄下的數(shù)據(jù)也會(huì)被系統(tǒng)刪除;并且在默認(rèn)情況下多媒體掃描器不會(huì)掃描該目錄下的圖片、 MP3等多媒體文件– 從這個(gè)角度看這個(gè)目錄是應(yīng)用的私有數(shù)據(jù)目錄。 由于該目錄存在于外部存儲(chǔ)空間中,任何其他具有讀寫外部存儲(chǔ)空間權(quán)限的應(yīng)用都可以訪問您的應(yīng)用數(shù)據(jù) — 從這個(gè)角度看這些數(shù)據(jù)又不是私有的。 所以我們就稱之為 偽私有數(shù)據(jù)。
那么為什么Android在2.2中引入這種偽私有數(shù)據(jù)保存方式呢? 這樣應(yīng)用的數(shù)據(jù)不是很不安全嗎? 這種存儲(chǔ)方式適合保存那些數(shù)據(jù)呢? 下面我們來(lái)逐個(gè)分析下這些問題:
為何引入這種存儲(chǔ)方式?
有些Android應(yīng)用在使用過程中,可能會(huì)產(chǎn)生很多需要保存的文件數(shù)據(jù),而這些數(shù)據(jù)需要在應(yīng)用卸載的時(shí)候被刪除掉,按照2.2之前的方式,這種 需求的數(shù)據(jù)只能保存到內(nèi)部存儲(chǔ)空間中,而系統(tǒng)的內(nèi)部存儲(chǔ)空間都是有限的,為了讓用戶能在有限的存儲(chǔ)空間中安裝更多的應(yīng)用,所以出現(xiàn)了這種存儲(chǔ)方式。
存儲(chǔ)在偽私有目錄的數(shù)據(jù)是不是很不安全?
當(dāng)然是不安全的,任何應(yīng)用都有可能訪問這些數(shù)據(jù),所以一般而言這里只保存那些不是非常敏感的數(shù)據(jù),由于這些目錄中的數(shù)據(jù)有可能被用戶或者其他應(yīng)用刪除掉,所以在使用這里面的數(shù)據(jù)的時(shí)候要先檢測(cè)下數(shù)據(jù)是否存在、有效,如果無(wú)效則需要從新下載使用。
這種存儲(chǔ)方式適合那些數(shù)據(jù)呢?
比如一個(gè)圖片瀏覽類的應(yīng)用,用該目錄來(lái)保存系統(tǒng)圖片的縮略圖方便提高應(yīng)用瀏覽圖片的流暢度;或者圖書類應(yīng)用用來(lái)保存圖書的封面圖片等。
如果您的應(yīng)用運(yùn)行在舊的設(shè)備(低于2.2的版本)上,則您也應(yīng)該按照上面的建議把文件保存到 /Android/data//files/ 目錄下,這樣如果用戶更新的設(shè)備版本后,這些數(shù)據(jù)就隨著應(yīng)用的卸載而被刪除掉了。
遺留問題
當(dāng)然也有一些比較有爭(zhēng)議的數(shù)據(jù),比如 IM聊天軟件接收到的圖片和自定義表情數(shù)據(jù) 應(yīng)該保存到SDCard中呢還是上面介紹的 偽私有數(shù)據(jù) 存儲(chǔ)目錄中呢? 如果用戶卸載了聊天軟件,用戶是否期望繼續(xù)保存他們接收到的圖片和自定義表情圖片呢? 這個(gè)問題恐怕針對(duì)不同的用戶得到的答案是不一樣的。這時(shí),我們咋辦??
個(gè)人建議針對(duì)這種沒有明確界限的需求,可以在用戶第一次使用程序的時(shí)候,引導(dǎo)用戶去設(shè)置他們的這些數(shù)據(jù)保存到哪里?保存到外部存儲(chǔ)空間(應(yīng)用卸載 后數(shù)據(jù)依然存在);或者保存到應(yīng)用外部存儲(chǔ)目錄中(應(yīng)用卸載后數(shù)據(jù)自動(dòng)刪除)。 這種做法類似下載一些PC軟件的做法,比如一些軟件在卸載的時(shí)候會(huì)填出對(duì)話框讓用戶選擇是否保留用戶數(shù)據(jù)。只不過在Android系統(tǒng)中卸載應(yīng)用目前沒辦 提供該功能,所以只能在應(yīng)用第一次使用的時(shí)候 讓用戶知道有這么個(gè)設(shè)置項(xiàng)。
PS:筆者目前最反感的就是一些應(yīng)用下載了很多小圖片到SDCard中,然后打開圖庫(kù)應(yīng)用會(huì)發(fā)現(xiàn)里面有很多這種小圖片(比如人的頭像啦、物品縮略 圖啦、圖書封面圖片啦),這種數(shù)據(jù)就不應(yīng)該出現(xiàn)在用戶的圖庫(kù)應(yīng)用中去。 如果把這些數(shù)據(jù)保存到上述的偽私有數(shù)據(jù)目錄中則 就不會(huì)出現(xiàn)這種問題。 目前為了避免這種問題,筆者不得不自己在各種目錄中創(chuàng)建“.nomedia”文件。相當(dāng)繁瑣啦!