Android數據存儲之Android 6.0運行時權限下文件存儲的思考

前言:

     在咱們作App開發的過程當中基本上都會用到文件存儲,因此文件存儲對於咱們來講是至關熟悉了,不過自從Android 6.0發佈以後,基於運行時權限機制訪問外置sdcard是須要動態申請權限,因此以往直接sdcard根目錄上直接新建了一個xxx/cache/目錄來作文件存儲就會不是那麼容易控制了,因此有必要從新認識一下Android文件存儲的相關知識了。android

背景:

   有關外置sdcard的讀寫權限算法

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

   在Android 6.0 以前只要申明瞭上述兩個權限就能夠放心大膽的在sdcard上進行讀寫了,惋惜Android 6.0以後就須要動態申請讀寫權限了,因此咱們該如何適配Android 6.0來進行文件存儲。首先咱們在使用文件存儲的時候儘可能作到如下幾點:瀏覽器

  • 不要隨意佔用用戶的內置存儲緩存

  • 不要隨意在SD卡上新建目錄,應該放置本身應用包名對應的擴展存儲目錄下,卸載App時能夠被自動清除。app

  • 對佔用的磁盤空間有上限,並按照必定的策略進行清除,好比DiskLru算法等。學習

Android文件存儲目錄:

1.)應用私有存儲(內置存儲)

訪問方式 詳細路徑 是否須要申請權限

Context.getFileDir();獲取內置存儲下的文件目錄,能夠用來保存不能公開給其餘應用的一些敏感數據如用戶我的信息spa

 /data/data/應用包名/files/  否

Context.getCacheDir();獲取內置存儲下的緩存目錄,能夠用來保存一些緩存文件如圖片,當內置存儲的空間不足時將系統自動被清除日誌

 /data/data/應用包名/cache/ 否 

注意:code

 因爲這裏使用的是Android 手機內置存儲,若是手機沒有得到root權限的話文件瀏覽器是沒法訪問的,一樣這種存儲也會隨之app被刪除而被刪除。orm

2.)應用擴展存儲(SD卡)

訪問方式 路徑詳情 是否須要申請權限

 Context.getExternalFilesDir();獲取SD卡上的文件目錄,

 SDCard/Android/data/應用包名/files/

 API < 19:是

API >= 19:否

 Context.getExternalCacheDir();獲取SD卡上的緩存目錄,能夠用來保存一些緩存文件如圖片

 SDCard/Android/data/應用包名/cache/

 API < 19:是

API >= 19:否

 注意:

   因爲存儲在sdcard上因此儘可能不要存在敏感數據好比用戶信息等,這裏的文件也會隨着app 被刪除而被刪除。

3.)公共存儲(SD卡)

訪問方式 路徑詳情 是否須要申請權限
Environment.getExternalStorageDirectory();獲取sdcard根目錄 SDCard/xxx文件夾名字/

注意:

  有時咱們也是須要存儲一些公共文件,並且但願這些文件可以不隨着App被刪除而被刪除,例如咱們錄製的視頻或者下載的音樂等。因爲這個目錄能夠被任何app訪問,因此咱們在使用的時候是須要申請權限的。

兼容Android 6.0 文件緩存實現

  前提:這裏主要處理一些非永久保存數據,須要永久保存的數據儘可能仍是要選擇sdcard 公共存儲方式的。

1.)獲取緩存根目錄

  /**
     * 獲取app的根目錄
     *
     * @return 文件緩存根路徑
     */
    public static String getDiskCacheRootDir() {
        File diskRootFile;
        if (existsSdcard()) {
            diskRootFile = LeeApplication.getApp().getExternalCacheDir();
        } else {
            diskRootFile = LeeApplication.getApp().getCacheDir();
        }
        String cachePath;
        if (diskRootFile != null) {
            cachePath = diskRootFile.getPath();
        } else {
            throw new IllegalArgumentException("disk is invalid");
        }
        return cachePath;
    }

這裏須要判斷sdcard是否可用

    /**
     * 判斷外置sdcard是否能夠正常使用
     *
     * @return
     */
    public static Boolean existsSdcard() {
        return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) || !Environment.isExternalStorageRemovable();
    }

2.)獲取指定功能的目錄

  /**
     * 獲取相關功能業務目錄
     *
     * @return 文件緩存路徑
     */
    public static String getDiskCacheDir(String dirName) {
        String dir = String.format("%s/%s/", getDiskCacheRootDir(), dirName);
        File file = new File(dir);
        if (!file.exists()) {
            boolean isSuccess = file.mkdirs();
            if (isSuccess) {
                Log.d(TAG, "dir mkdirs success");
            }
        }
        return file.getPath();
    }

在平常開發過程當中,咱們須要不一樣的文件放在不一樣的目錄下,好比:log日誌文件須要放在log文件下,就能夠經過上面的方法傳入「log」獲取該業務功能的文件夾。

3.)獲取指定功能文件路徑

    /**
     * 獲取log日誌根目錄
     * @return
     */
    public  static String getLogDir(){
        return getDiskCacheDir(LOG);
    }

    /**
     * 根據logName 獲取log文件全路徑
     * @param logName
     * @return
     */
    public  static String getLogFilePath(String logName){
        return  getLogDir()+logName;
    }

 總結:

      今天總結了Android的文件存儲及在6.0上的適配問題,最近忽然以爲本身有太多的知識須要學習了,也許因爲如今的經濟大環境致使互聯網遇到了資本寒冬了,其實對於我來講2012年已經經歷過一次了,對於技術人員來講應該冷靜的看待這個問題,須要作的就是在寒冬裏播種但願,那就是學習。以此共勉之~

相關文章
相關標籤/搜索