Android應用正確使用擴展SD卡

Android 開發時如何正確獲取使用擴展存儲路徑


先介紹一下Android的存儲

在 2.x 版本中,Android設備都是單存儲,第三方App寫文件,必須申請 WRITE_EXTERNAL_STORAGE 權限;html

在4.0以後,Android設備開始有了內置閃存,即 primary storage,而且能夠外置SD卡,即 secondary external storage device;android

WRITE_EXTERNAL_STORAGE 權限變成了僅僅控制 primary storage,同時引入了 WRITE_MEDIA_STORAGE 權限來控制secondary external storage device的操做。程序員

到了Android 4.4 KitKat,WRITE_MEDIA_STORAGE 權限僅提供給系統應用,再也不授予第三方App。緩存

關於 secondary external storage device 的寫操做也有了新規定。app

Android的文檔是這麼寫的:post

Link: http://source.android.com/devices/tech/storage/index.html:ui

The WRITE_EXTERNAL_STORAGE permission must only grant write access to the primary external storage on a device. Apps must not be allowed to write to secondary external storage devices, except in their package-specific directories as allowed by synthesized permissions. Restricting writes in this way ensures the system can clean up files when applications are uninstalled.this

翻譯: WRITE_EXTERNAL_STORAGE 權限,僅僅用於受權用戶寫 primary external storage,除了與本身包名相關的文件夾以外,應用程序不容許寫secondary external storage devices。google

舉例來講,若是應用的包名是com.example.foo,那麼外部存儲上的Android/data/com.example.foo/文件夾就可隨意訪問,其餘任何地方都不容許寫,而且,存儲在本身包名相關的文件夾的文件,當該應用被卸載時候也會隨之被清除。.net

分狀況來講:

  • 只有外部存儲的設備 這種設備通常是android4.0以前的,只有一個存儲,不受這個規則限制,仍是能夠隨便讀寫,但若是你刷了4.4系統,那麼就只能寫本身包名相關的文件夾了。
  • 只有內部存儲的設備 好比Nexus系列,sony L系列,不受這個規則限制,可是建議在本身的包名相關的文件夾寫數據。
  • 既有內部存儲又有外部存儲 須要遵照這個規定,不能在外部存儲亂寫了,須要在本身的包名相關的文件夾寫數據。

Google作了這個限制後解決了這個問題:

隨便一個App,都會在/sdcard、/sdcard1 上建一個目錄,刪了也會從新建,即便被卸載,也會留下一些垃圾文件。

可是,也產生了一個問題:

相似於視頻、圖像處理這種想在外部存儲緩存大量音視頻文件,而且App被卸載後還想保留的,就沒辦法了。

開發中應該怎麼使用?

做爲一個程序員,想必你也很討厭App在SD卡根目錄亂建目錄吧,那就從我作起,來遵照Google的這一規定吧。

經過Context.getExternalFilesDir()方法能夠獲取到 SDCard/Android/data/{package_name}/files/ ,儲存一些長時間保存的數據;

經過Context.getExternalCacheDir()方法能夠獲取到 SDCard/Android/data/{package_name}/cache/,儲存臨時緩存數據;

這兩個目錄分別對應 設置->應用->應用詳情裏面的」清除數據「與」清除緩存「選項。

一個獲取外部存儲Cache的例子:

/** * 獲取拓展存儲Cache的絕對路徑 * * @param context */ public static String getExternalCacheDir(Context context) {

if (!isMounted())
           return null;
     
      StringBuilder sb = new StringBuilder();

      File file = context.getExternalCacheDir();

      // In some case, even the sd card is mounted,
      // getExternalCacheDir will return null
      // may be it is nearly full.
     
      if (file != null) {
           sb.append(file.getAbsolutePath()).append(File.separator);
      } else {
           sb.append(Environment.getExternalStorageDirectory().getPath()).append("/Android/data/").append(context.getPackageName())
                     .append("/cache/").append(File.separator).toString();
      }
     
      return sb.toString();
 }

參考: https://plus.google.com/+TodLiebeck/posts/gjnmuaDM8sn http://blog.csdn.net/olevin/article/details/29575127 http://source.android.com/devices/tech/storage/index.html

相關文章
相關標籤/搜索