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