Android存儲路徑探索

Tips: 複製的源碼爲Java代碼,示例使用Kotlin編寫。

內部存儲

內部存儲可以直接在設備的內部存儲中保存文件。默認情況下,保存到內部存儲的文件是應用的私有文件,其他應用(和用戶)不能訪問這些文件。 當用戶卸載您的應用時,這些文件也會被移除。

  • 返回內部存儲文件上目錄的絕對路徑,其中存儲了當前應用程序的所有私有文件。例:/data/user/0/應用包名
    public abstract File getDataDir();

示例如下:

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        val mDataFilePath = applicationContext.dataDir
        Log.e(javaClass.simpleName, mDataFilePath.path)
    }

打印輸出: /data/user/0/應用包名

  • 獲取當前應用在內部存儲上的根目錄,返回存儲在內部存儲上的文件目錄的絕對路徑。例:/data/user/0/應用包名/files
    public abstract File getFilesDir();

示例如下:

    // 獲取系統存儲上當前應用的根目錄文件
    val mFileDir = activity!!.applicationContext.filesDir
    // 打印系統存儲上當前應用的根目錄地址  
    Log.e(javaClass.simpleName, "根目錄:${mFileDir.path}")
    // 在系統存儲上當前應用的根目錄下創建文件夾
    val mRootFile = File(mFileDir, "content.txt")
    // 打印系統存儲上當前應用的根目錄地址 
    Log.e(javaClass.simpleName, "文件地址:${mRootFile.path}")
    
    // 此處省略調用代碼......
        
    /**
     * 向文件中寫入文本
     * Kotlin在擴展函數use中已經封裝了關閉流,所以這裏不用再調流的close()方法
     */
    private fun writeTextToFile(file: File) {
        BufferedWriter(FileWriter(file)).use {
            it.write("秦川小將")
        }
    }

    /**
     * 讀取文件中的文本內容
     * Kotlin在擴展函數use中已經封裝了關閉流,所以這裏不用再調流的close()方法
     */
    private fun readTextInFile(file: File) {
        BufferedReader(FileReader(file)).use {
            var mLine: String
            while (true) {
                mLine = it.readLine() ?: break
                Log.e(javaClass.simpleName, mLine) 
            }
        }
    }

注: Kotlin在擴展函數use中已經封裝了關閉流,所以這裏不用再調流的close()方法。

打印輸出如下:

根目錄: /data/user/0/com.files.sample/files
文件地址:/data/user/0/com.files.sample/files/content.txt

秦川小將

  • 檢索,創建需要的新目錄,應用程序可以在其中放置自己的自定義數據文件。例:/data/user/0/應用包名/自定義文件目錄名
    public abstract File getDir(String name, @FileMode int mode);

mode參數取值說明,如下:

Context.MODE_PRIVATE
默認的方式,創建的文件只能被本Activity所訪問。

Context.MODE_WORLD_READABLE
允許所有其他應用程序對創建的文件具有讀訪問權限,Android API 17以後不建議使用。從Android API 24嘗試使用此模式開始,將會拋出一個SecurityException異常。

Context.MODE_WORLD_WRITEABLE
允許所有其他應用程序對創建的文件具有寫入權限。Android API LEVEL 17以後不建議使用。

Context.MODE_APPEND
將內容以追加的方式寫到文件末尾。

示例如下:

val mFile = applicationContext.getDir("custom", Context.MODE_PRIVATE)
Log.e(javaClass.simpleName, mFile.path)

打印輸出:/data/user/0/com.files.sample/app_custom

  • 返回當前應用在內部存儲上的緩存目錄的絕對路徑。例:/data/user/0/應用包名/cache
    public abstract File getCacheDir();

示例如下:

    val mFile = applicationContext.cacheDir
    Log.e(javaClass.simpleName, mFile.path)

打印輸出: /data/user/0/com.files.sample/cache

外部存儲

外部存儲是有可能移除的存儲介質(例如 SD 卡)或不可移除存儲(設備自帶內存)。保存到外部存儲的文件是全局可讀取文件,而且,在計算機上啓用 USB 大容量存儲以傳輸文件後,可由用戶對這些文件進行修改。

存儲權限(Android v6.0需要動態申請)

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

1.Environment提供的存儲路徑

  • 系統根目錄,例:/system
    public static File getRootDirectory()
  • 返回用戶數據目錄,例:/data
    public static File getDataDirectory()
  • 返回下載/緩存內容目錄,例:/data/cache
    public static File getDownloadCacheDirectory()
  • 返回外部存儲目錄,例:/storage/emulated/0
    public static File getExternalStorageDirectory()

打印 /storage/emulated/0 目錄下所有文件名

 	val mFiles = Environment.getExternalStorageDirectory()
    mFiles.list().forEach {
        Log.e(javaClass.simpleName, "${mFiles.path}/$it")
    }

getExternalStorageDirectory 具體輸出:

/storage/emulated/0/MIUI
/storage/emulated/0/mipush
/storage/emulated/0/sogou
/storage/emulated/0/Android
/storage/emulated/0/.mn_1021243354
/storage/emulated/0/amap
/storage/emulated/0/backups
/storage/emulated/0/.dlprovider
/storage/emulated/0/.DataStorage
/storage/emulated/0/360
/storage/emulated/0/.sys.log
/storage/emulated/0/DCIM
/storage/emulated/0/miad
/storage/emulated/0/.mn_-980648280
/storage/emulated/0/MiMarket
/storage/emulated/0/data
/storage/emulated/0/mivideo
/storage/emulated/0/Download
/storage/emulated/0/com.miui.voiceassist
/storage/emulated/0/browser
/storage/emulated/0/.Rcs
/storage/emulated/0/.com.android.providers.downloads.ui
/storage/emulated/0/netease
/storage/emulated/0/Tencent
/storage/emulated/0/.UTSystemConfig
/storage/emulated/0/Pictures
/storage/emulated/0/.vivo
/storage/emulated/0/kingdid
/storage/emulated/0/FreeRun
/storage/emulated/0/fac_sources
/storage/emulated/0/wt_logs
/storage/emulated/0/JuphoonService
/storage/emulated/0/dctp
/storage/emulated/0/wlan_logs
/storage/emulated/0/did
/storage/emulated/0/.com.taobao.dp
/storage/emulated/0/baidu
/storage/emulated/0/com.netease.cloudmusic
/storage/emulated/0/.cm_restart_record
/storage/emulated/0/images
/storage/emulated/0/SmartHome
  • 獲取頂級共享/外部存儲目錄以及指定類型目錄的文件
    public static File getExternalStoragePublicDirectory(String type)

type 類型如下:

常量 目錄說明
Environment.DIRECTORY_MUSIC 標準的音樂存放目錄
Environment.DIRECTORY_PODCASTS 標準的系統廣播存放目錄
Environment.DIRECTORY_RINGTONES 標準的系統鈴聲存放目錄
Environment.DIRECTORY_ALARMS 標準的系統提醒鈴聲存放目錄
Environment.DIRECTORY_NOTIFICATIONS 標準的系統通知鈴聲存放目錄
Environment.DIRECTORY_PICTURES 標準的相冊存放目錄
Environment.DIRECTORY_MOVIES 標準的電影存放目錄
Environment.DIRECTORY_DOWNLOADS 標準的下載存放目錄
Environment.DIRECTORY_DCIM 標準的相機拍攝照片和視頻存放目錄
Environment.DIRECTORY_DOCUMENTS 標準的文檔存放目錄

對應常量值:


    public static String DIRECTORY_MUSIC = "Music";

    public static String DIRECTORY_PODCASTS = "Podcasts";

    public static String DIRECTORY_RINGTONES = "Ringtones";

    public static String DIRECTORY_ALARMS = "Alarms";

    public static String DIRECTORY_NOTIFICATIONS = "Notifications";

    public static String DIRECTORY_PICTURES = "Pictures";

    public static String DIRECTORY_MOVIES = "Movies";

    public static String DIRECTORY_DOWNLOADS = "Download";

    public static String DIRECTORY_DCIM = "DCIM";

    public static String DIRECTORY_DOCUMENTS = "Documents";
  • 獲取外部存儲設備的當前狀態
    public static String getExternalStorageState()

返回值如下:

常量 說明
Environment.MEDIA_UNKNOWN 未知存儲狀態
Environment.MEDIA_REMOVED 移除狀態:SDCard成功移除
Environment.MEDIA_UNMOUNTED 未掛載:識別到SDCard,但沒有掛載
Environment.MEDIA_CHECKING 檢查狀態:檢查SDCard的有效性
Environment.MEDIA_NOFS NOFS狀態:識別到SDCard卡,但無法掛載。無法掛載原因,可能是SDCard無存儲介質,或者SDCard卡的文件系統與Android無兼容
Environment.MEDIA_MOUNTED 掛載狀態:SDCard卡已經成功掛載
Environment.MEDIA_MOUNTED_READ_ONLY 只讀狀態:SDCard已經掛載,但是是隻讀的
Environment.MEDIA_SHARED 共享狀態:識別到SDCard卡,但SDCard未掛載,而是作爲mass storage等設備(如以u盤的方式連接到電腦上)
Environment.MEDIA_BAD_REMOVAL 非法移除狀態:移除SDCard之前,沒有卸載SDCard
Environment.MEDIA_UNMOUNTABLE 無法掛載狀態:識別到sdcard卡,但無法掛載。無法掛載的原因,可能是SDCard的存儲介質部分損壞

對應常量值:

    public static final String MEDIA_UNKNOWN = "unknown";

    public static final String MEDIA_REMOVED = "removed";

    public static final String MEDIA_UNMOUNTED = "unmounted";

    public static final String MEDIA_CHECKING = "checking";

    public static final String MEDIA_NOFS = "nofs";

    public static final String MEDIA_MOUNTED = "mounted";

    public static final String MEDIA_MOUNTED_READ_ONLY = "mounted_ro";

    public static final String MEDIA_SHARED = "shared";

    public static final String MEDIA_BAD_REMOVAL = "bad_removal";

    public static final String MEDIA_UNMOUNTABLE = "unmountable";
  • 返回指定路徑共享/外部存儲設備的當前狀態
    public static String getExternalStorageState(File path)

返回值與 static String getExternalStorageState() 一致。

  • 設備的外存是否是用內存模擬的,是則返回true
    public static boolean isExternalStorageEmulated()
  • 返回主“外部存儲設備是否是可拆卸的。
    public static boolean isExternalStorageRemovable()

2.Context提供的存儲路徑

  • 返回設備外部存儲上目錄的絕對路徑,應用程序可以在其中放置其擁有的永久文件。
    • 這些文件是應用程序的內部文件,通常不會作爲媒體顯示給用戶。
    • 同時當應用被卸載時,這些文件將會被刪除。
    • 例:/storage/emulated/0/Android/data/應用包名/files/type
    @Nullable
    public abstract File getExternalFilesDir(@Nullable String type);

參數type取值說明:

type取值與 getExternalStoragePublicDirectory 一樣,存儲路徑不同。
getExternalFilesDir 存儲的目錄卻是在 /storage/emulated/0/Android/data/應用包名/files/type

示例如下:

    val mFile = applicationContext.getExternalFilesDirs(Environment.DIRECTORY_PICTURES)
    if (mFile.isNotEmpty()){
        mFile.iterator().forEach {
            Log.e(javaClass.simpleName, it.path)
        }
    }

打印輸出:/storage/emulated/0/Android/data/com.files.sample/files/Pictures

  • 應用程序如果有obb文件,則返回應用程序的obb文件的外部存儲目錄的絕對路徑。例:/storage/emulated/0/Android/obb/應用報名
    public abstract File getObbDir();

示例如下:

    val mFile = applicationContext.obbDir
    Log.e(javaClass.simpleName, mFile.path)

打印輸出:/storage/emulated/0/Android/obb/com.files.sample

  • 應用程序如果有obb文件,則返回應用程序的obb文件的外部存儲目錄的絕對路徑的集合。通過 forEach 便利可查看全部。
    public abstract File[] getObbDirs();

示例如下:

    val mFile = applicationContext.obbDirs
    if (mFile != null && mFile.isNotEmpty()) {
        mFile.iterator().forEach {
            Log.e(javaClass.simpleName, it.path)
        }
    }

打印輸出:/storage/emulated/0/Android/obb/com.files.sample

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章