1. 程式人生 > >Android儲存路徑詳細說明

Android儲存路徑詳細說明

一、儲存的分類

Android的儲存路徑實際分類為

內部儲存路徑
內部快取儲存路徑

外部儲存路徑
外部快取儲存路徑

在有些手機上,系統也會在內部劃出一個內部的SDCard路徑和內部儲存路徑,所以當有SDCard的時候,就會有6個路徑存在了

內部儲存空間中的應用私有目錄

對於裝置中每一個安裝的 App,系統都會在內部儲存空間的 data/data 目錄下以應用包名為名字自動建立與之對應的資料夾。這個資料夾用於 App 中的 WebView 快取頁面資訊,SharedPreferences 和 SQLiteDatabase 持久化應用相關資料等。

對於沒有 Root 過的手機,普通使用者是無法檢視 data/data 目錄內容的。不過開發人員可以使用模擬器除錯應用,並通過 DDMS(Dalvik Debug Monitor Server)提供的 File Explorer 工具檢視模擬器裝置的儲存空間。

這裡寫圖片描述

注意:當用戶解除安裝 App 時,系統自動刪除 data/data 目錄下對應包名的資料夾及其內容。

外部儲存空間中的應用私有目錄

考慮內部儲存空間容量有限,普通使用者不能直接直觀地檢視目錄檔案等其他原因,Android 在外部儲存空間中也提供有特殊目錄供應用存放私有檔案,檔案路徑為:
/storage/emulated/0/Android/data/app package name

備註:一般裝置都有內建 SD 卡,同時也提供外部 SD 卡拓展,可能對應路徑的目錄名有所差異。

值得注意的是,與內部儲存空間的應用私有目錄不同的是:

  • 第一,預設情況下,系統並不會自動建立外部儲存空間的應用私有目錄。只有在應用需要的時候,開發人員通過 SDK 提供的 API 建立該目錄資料夾和操作資料夾內容。

  • 第二,自 Android 7.0 開始,系統對應用私有目錄的訪問許可權進一步限制。其他 App 無法通過 file:// 這種形式的 Uri 直接讀寫該目錄下的檔案內容,而是通過 FileProvider 訪問。

  • 第三,宿主 App 可以直接讀寫內部儲存空間中的應用私有目錄;而在 4.4 版本開始,宿主 App 才可以直接讀寫外部儲存空間中的應用私有目錄,使開發人員無需在 Manifest 檔案中或者動態申請外部儲存空間的檔案讀寫許可權。
    而相同點在於:同屬於應用私有目錄,當用戶解除安裝 App 時,系統也會自動刪除外部儲存空間下的對應 App 私有目錄資料夾及其內容。

同樣,Android SDK 中也提供有便捷的 API 供開發人員直接操作外部儲存空間下的應用私有目錄:

  • getExternalFilesDir()

  • getExternalCacheDir()

等等,當然,也可以通過 Environment 類間接操作,只不過需要向用戶申請操作許可權:

Environment.getExternalStorageDirectory();

類似於 File 和 Cache 預設分類目錄,開發人員也可以在應用私有目錄中建立屬於自己的自定義目錄,方便於分類儲存應用相關檔案。

值得注意的一點是,對於外部儲存空間下的應用私有目錄檔案,由於普通使用者可以自由修改和刪除,開發人員在使用時,一定要做好判空處理和異常捕獲,防止應用崩潰退出!

外部儲存空間中的公共目錄

通常來說,應用涉及到的持久化資料分為兩類:應用相關資料和應用無關資料。前者是指專供宿主 App 使用的資料資訊,比如一些應用的配置資訊,資料庫資訊,快取檔案等。當應用被解除安裝,這些資訊也應該被隨之刪除,避免儲存空間產生不必要的佔用。

相對而言,後者更偏向於這類資訊:當應用被解除安裝,使用者仍然希望保留於裝置當中的資訊。常見如,拍照類應用的圖片檔案,使用者是使用瀏覽器手動下載的檔案等。

顯然,無論是內部儲存空間,還是外部儲存空間,上述兩個應用私有目錄由於其特有的生命週期(隨著應用解除安裝而自動清除)只適合儲存應用相關資料。

或者從訪問許可權上來說,應用無關資料應該是宿主應用希望與其他應用共享這些資料的,應該存放在外部儲存空間的公共目錄資料夾下。

外部儲存空間已經為使用者預設分類出一些公共目錄。開發人員可以通過 Environment 類提供的方法直接獲取相應目錄的絕對路徑,傳遞不同的 type 引數型別即可:

Environment.getExternalStoragePublicDirectory(String type);

Envinonment 類提供諸多 type 引數的常量,比如:

  • DIRECTORY_MUSIC:Music

  • DIRECTORY_MOVIES:Movies

  • DIRECTORY_PICTURES:Pictures

  • DIRECTORY_DOWNLOADS:Download

等等,以第一個常量為例,音樂類別的公共目錄絕對路徑為:/storage/emulated/0/Music。如果你使用檔案管理器開啟裝置的外部儲存空間的話,均可以看到這些公共目錄資料夾。

面對如此諸多的預設類別,開發人員在儲存自己應用的公共檔案時,也要養成良好的習慣,將要儲存的資料分門別類地儲存在不同公共目錄下。當然,你也可以在公共目錄下再次建立屬於自己應用的目錄,便於管理。

注意:訪問外部儲存空間時記得申請讀寫許可權!

外部儲存空間中的其他目錄一般來說,利用兩種應用私有目錄和公共目錄便能夠儲存應用中需要儲存的資料和檔案。如果這些還不夠的話,那一定是你的開發姿勢不對。在 Code Review 的前提下,如果還是不夠的話,還可以在外部儲存空間自由建立其他目錄,通過這個方式獲取外部儲存空間的絕對路徑,然後操作檔案:

Environment.getExternalStorageDirectory();

小結

使用應用私有目錄儲存應用相關資料,使用公共目錄儲存應用無關資料(共享資料)。無論哪種情況,都需要做好資料分類儲存,便於清除等統一管理。隨便開啟手機上的幾個應用,不難發現,很多應用都包含一個清理快取的功能。事實上,開發人員清理的就是應用相關資料,也就是應用私有目錄下的檔案。

考慮到外部儲存空間上的內容可能被使用者手動刪除,或者解除安裝拓展 SD 卡等不可控因素,操作前記得使用 Environment 類提供的 API 方法判斷容量是否充足、檔案是否存在等情況,做好異常捕獲,減少應用崩潰率。相信這一定是一個良好的習慣。

二、儲存路徑和快取儲存路徑的區別

  1. 快取路徑一般用於存放一些快取資料,當程式刪除的時候,快取資料夾也會隨之刪除,避免了程式在解除安裝之後殘留大量檔案。

  2. 內部快取路徑和外部快取路徑也有所區別,當系統的記憶體空間緊張時,內部快取路徑下的檔案會被刪除,但是沒有一個嚴格的標準保障,應該對這些快取檔案佔用的最大儲存空間設定個最大值,當實際超過這個值時,要對這些快取檔案做相應的清理工作 。但是系統不會觀察外部快取路徑下是否超出大小,要自己去做檔案清理機制。

  3. 內部快取路徑預設別的程式不能訪問檔案,所以一些私密的資料,別的他應用是訪問不了的,如果需要執行系統或者其他應用訪問,可以通過修改openFileOutput()下的int mode引數讓別的應用也可以訪問。

三、內部快取路徑

內部的 /data/data/一般是看不到的,除非root

清除快取

context.getCacheDir() 

模擬器:內部快取路徑:/data/data/com.mocn.testin/cache/內部快取路徑.png
Nexus5:內部快取路徑:/data/user/0/com.mocn.testin/cache/內部快取路徑.png

this .getFilesDir() 

模擬器:內部資料夾快取路徑:/data/data/com.mocn.testin/files/內部資料夾快取路徑.png

this .getDir( "資料夾名字" , Context. MODE_PRIVATE);

模擬器: 內部快取路徑新目錄:/data/data/com.mocn.testin/app_資料夾名字/內部快取路徑新目錄.png

this .getFileStreamPath ("下載" )

模擬器:下載:/data/data/com.mocn.testin/files/下載/下載.png

0 MODE_PRIVATE 為預設操作模式,代表該檔案是私有資料,只能被應用本身訪問,在該模式下寫入的內容會覆蓋原檔案的內容。
1 MODE_WORLD_READABLE 表示當前檔案可以被其他應用讀取。
2 MODE_WORLD_WRITEABLE 表示當前檔案可以被其他應用寫入。
3 MODE_MULTI_PROCESS SharedPreference的裝載標記,設定它,檔案將會在SharedPreference例項被裝載到程序的時候檢查是否被修改,主要用在一個應用有多個程序的情況。

清除資料會還原成最初的樣子,所有的目錄,sharepreferces,database檔案等都會清空

四、外部儲存和外部快取的路徑

1、外部快取路徑

清除快取

context.getExternalCacheDir() 

模擬器:外部快取路徑:/storage/emulated/0/Android/data/com.mocn.testin/cache/外部快取路徑.png

Nexus5:外部快取路徑:/storage/emulated/0/Android/data/com.mocn.testin/cache/外部快取路
徑.context.getExternalFilesDir() :

外部資料夾快取路徑:/storage/emulated/0/Android/data/com.mocn.testin/files/ssssss/外部資料夾快取路徑.png

Context.getExternalFilesDir()
public File getAlbumStorageDir(Context context, String albumName) {  
// Get the directory for the app's private pictures directory.  
 File file = newFile(context.getExternalFilesDir(  
Environment.DIRECTORY_PICTURES), albumName);  
if(!file.mkdirs()) {  
Log.e(LOG_TAG, "Directory not created");  
 }  
 returnfile;  
}  

上面的程式碼建立了一個picture目錄,並在這個目錄下建立了一個名為albumName的檔案,Environment.DIRECTORY_PICTURES其實就是字串picture。

所有應用程式的外部儲存的私有檔案都放在根目錄的Android/data/下,目錄形式為/Android/data//

如果你的api 版本低於8,那麼不能使用getExternalFilesDir(),而是使用Environment.getExternalStorageDirectory()獲得根路徑之後,自己再想辦法操作/Android/data//下的檔案。

也就是說api 8以下的版本在操作檔案的時候沒有專門為私有檔案和公共檔案的操作提供api支援。你只能先獲取根目錄,然後自行想辦法。

2、外部儲存路徑

Environment. getExternalStorageDirectory()

模擬器:/storage/emulated/0/外部儲存路徑.png
Nexus5:外部儲存路徑:/storage/emulated/0/外部儲存路徑.png

Environment.getExternalStoragePublicDirectory

[java] view plain copy

1. public File getAlbumStorageDir(String albumName) {  
2. // Get the directory for the user's public pictures directory.  
3. File file = newFile(Environment.getExternalStoragePublicDirectory(  
4. Environment.DIRECTORY_PICTURES), albumName);  
5. if(!file.mkdirs()) {  
6. Log.e(LOG_TAG, "Directory not created");  
7. }  
8. returnfile;  
9. }  

在上面的程式碼中我們建立獲得了存放picture的目錄,並且新建立一個albumName檔案。
如果你的api 版本低於8,那麼不能使用getExternalStoragePublicDirectory(),而是使用Environment.getExternalStorageDirectory(),他不帶引數,也就不能自己建立一個目錄,只是返回外部儲存的根路徑。

在使用外部儲存之前,你必須要先檢查外部儲存的當前狀態,以判斷是否可用。

1. boolean mExternalStorageAvailable = false;  
2. boolean mExternalStorageWriteable = false;  
3. String state = Environment.getExternalStorageState();  
4. if(Environment.MEDIA_MOUNTED.equals(state)) {  
5. // We can read and write the media  
6. mExternalStorageAvailable = mExternalStorageWriteable = true;  
7. } elseif(Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {  
8. // We can only read the media  
9. mExternalStorageAvailable = true;  
10. mExternalStorageWriteable = false;  
11. } else{  
12. // Something else is wrong. It may be one of many other states, but all we need  
13. //  to know is we can neither read nor write  
14. mExternalStorageAvailable = mExternalStorageWriteable = false;  
15. }  

三、getFilesDir,getExternalFilesDir,getExternalStorageDirectory,getExternalStoragePublicDirectory區別

getFilesDir,getExternalFilesDir,getExternalStorageDirectory,getExternalStoragePublicDirectory區別:

1. Log.i("codecraeer", "getFilesDir = " + getFilesDir());  
2. Log.i("codecraeer", "getExternalFilesDir = " + getExternalFilesDir("exter_test").getAbsolutePath());  
3. Log.i("codecraeer", "getDownloadCacheDirectory = " + Environment.getDownloadCacheDirectory().getAbsolutePath());  
4. Log.i("codecraeer", "getDataDirectory = " + Environment.getDataDirectory().getAbsolutePath());  
5. Log.i("codecraeer", "getExternalStorageDirectory = " + Environment.getExternalStorageDirectory().getAbsolutePath());  
6. Log.i("codecraeer", "getExternalStoragePublicDirectory = " + Environment.getExternalStoragePublicDirectory("pub_test"));  

在log中看到如下結果:

(nexus 3)上是/storage/emulated/0,奇怪的是在有些手機上同樣的程式碼卻是下面的情況:

部儲存根目錄為/mnt/sdcard.

參考

相關推薦

Android儲存路徑詳細說明

一、儲存的分類 Android的儲存路徑實際分類為 內部儲存路徑 內部快取儲存路徑 外部儲存路徑 外部快取儲存路徑 在有些手機上,系統也會在內部劃出一個內部的SDCard路徑和內部儲存路徑,所以當有SDCard的時候,就會有6個路徑存在了 內部

Android 各種路徑詳細說明

公有 4.2 查找 知識 移動 禁用 符號 alc 絕對路徑 說起Android“內部存儲”,對於開發者而言可以毫不猶豫地脫口而出,不就是/data/data目錄嘛,也不盡然,/data/user/0/又如何解釋?那說起“外部存儲”,例如sd卡目錄獲取值,更是眾說紛紜,是/

Android儲存路徑最全總結

Logger.i("1、" + Environment.getRootDirectory() + ";2、" + Environment.getDataDirectory() + ";3、" + Environment.getD

Android儲存路徑瞭解

在瞭解儲存路徑之前,先來看看Android QQ的檔案管理介面,瞭解一下QQ的資料檔案路徑來源,到底是來源於什麼地方? QQ 檔案截圖 手Q檔案管理對應儲存目錄 我的檔案:是指放在QQ指定目錄下的檔案:/tencent/QQfile_recv/(順便說一下微信

Android 儲存路徑選擇

Android能用來儲存的地方有兩個,一個是手機內建的儲存空間,一個是外接的SD卡,內建的儲存空間一般比較小,所以應用的快取建議儲存在外接的SD卡中。 在Android系統中如何獲得儲存的路徑呢? public static void getRo

Android手機儲存路徑

手機儲存 手機分為內部儲存和外部儲存 1、內部儲存 主要方法 路徑 Environment.getDataDirectory() /data Environment.getDo

Android 外部儲存,內部儲存路徑

import android.content.Context; import android.os.Environment; import android.util.Log; public class DirectoryUtils { private static final String

Android 本地儲存之外部儲存/內部儲存路徑獲取大全

//:/system String rootDir = Environment.getRootDirectory().toString(); System.out.println("Environment.getRootDirectory()=:" +

Android儲存一張drawable下的圖片資源儲存到絕對路徑

Resources res = this.getResources(); BitmapDrawable d = (BitmapDrawable) res.getDrawable(R.drawable.ic_launcher); Bitmap img = d.getBitmap();

Android檔案儲存路徑分析

1.internal or external storage 內部儲存和外部儲存的對比: 1.內部儲存永遠可以訪問,由於外部儲存可能是SD卡,可能無法訪問; 2.內部儲存檔案只有本App才能訪問,外部儲存檔案可以共享給其他APP; 3.解除安裝APP,相應的內部儲存檔案被系統刪除

MySQL 5.7版本的安裝使用詳細教程+更改資料庫data的儲存路徑

因為看到mysql5.7加入了新特性documentation 所以重新安裝了一下mysql5.7版本的,順便把步驟貼一貼 (一)下載: 官網連結 步驟:【Downloads–>Community–>MySQL on Window

Android外部儲存/內部儲存路徑獲取大全

String publicDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString(); (adsbygoogle = window.ads

android學習-android儲存和快取路徑備忘錄

手機本地儲存路徑(openOutputStream)對應設定-應用-清除資料 context.getFilesDir().getAbsolutePath() /data/data/com.examp

Android 獲取本地儲存路徑的各種方法詳解

Android 中獲取本地儲存路徑,有四個方法, getCacheDir()、getFilesDir()、getExternalFilesDir()、getExternalCacheDir()。 接下來介紹下每個方法的特點以及路徑地址 getCacheDir(

unity中的檔案儲存路徑與各平臺(Android,iOS)的關係

主要是這個問題困擾我了一陣子,所以特寫寫。。。 unity中的的各種儲存方法的對應關係(直接上截圖吧) 重點說的是Application.presistentDataPath方法,因為這個問題在Android中困擾我很久, 先說說iOS端,很簡單,就是儲存到iOS的沙

Android資料儲存路徑位置

File filepathq = getFilesDir();File filepathw = getCacheDir();File filepathe = getExternalCacheDir();File filepathr = getExternalFilesDir

android sdcard各種儲存路徑解惑

在開發app的過程中,需要儲存一些資料,這時就會遇到各種儲存路徑,sdcard/、storage/sdcard0、mnt/sdcard等等,會讓人很難以理解。這其中的很多路徑都是指向同一個路徑,有點指標的味道。 其中的sdcard/、mnt/sdcard、storage/

Android 預設AP名字,以及AP名字儲存路徑

最近在修改Settings.apk,其中有一條需求是修改預設的ap名字。於是我們跟蹤一下原始碼來解決一下困擾我的問題。 首先在Settings\src\com\android\settings\TetherSettings.java的程式碼中 p

Android 獲取建立各種儲存路徑工具類(內建許可權獲取)

前言 最近工作比較輕,從專案中總結抽象出一些工具類,利人利己,歡迎交流完善~ 概念介紹 1、內部儲存 Internal Storage: 注意內部儲存不是記憶體。內部儲存位於系統中很特殊的一個位置,如果你想將檔案儲存於內部儲存中,那麼檔案預設

android獲取外部儲存和內部儲存路徑

StorageManager sm = (StorageManager) activity.getSystemService(Context.STORAGE_SERVICE); // 獲取sdcard的路徑:外部儲存和內部儲存 String[] paths