APP中的存儲路徑


訪問SD卡 所需權限 

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

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

App專屬文件 vs App獨立文件

app專屬文件就是那些只有該app才可以使用的文件,例如專屬格式的電子書,app獨立文件就是那些不依賴於某特定app的文件,例如照片。

App獨立文件

這類文件當我們刪除應用之后,還應該保留在手機上的,例如拍照的照片,不應該隨着刪除應用而被刪除掉。對於這類文件,android給我們提供了特定的目錄,這些目錄都是以DIRECTORY開頭的,例如:DIRECTORY_MUSIC , DIRECTORY_PICTURES.

訪問這些文件夾有兩種方式:

Environment.getExternalStorageDirectory()是獲得外部存儲的第一層的對象

第一種:File sdCard = Environment.getExternalStorageDirectory();

這個sdCard的路徑為mnt/sdcard/ 即為SD卡根路徑,我們可以指定訪問的文件夾名

File sdCard = Environment.getExternalStorageDirectory();

File directory_pictures = new File(sdCard, "Pictures");

Log.i(TAG,"directory_pictures="+directory_pictures);

得到的路徑如下: 

這里寫圖片描述

第二種:Environment.getExternalStoragePublicDirectory(String type)

如果您需要往sdcard中保存特定類型的內容,可以考慮使用Environment.getExternalStoragePublicDirectory(String type)函數,該函數可以返回特定類型的目錄,目前支持如下類型:

DIRECTORY_ALARMS //警報的鈴聲
DIRECTORY_DCIM //相機拍攝的圖片和視頻保存的位置
DIRECTORY_DOWNLOADS //下載文件保存的位置
DIRECTORY_MOVIES //電影保存的位置, 比如 通過google play下載的電影
DIRECTORY_MUSIC //音樂保存的位置
DIRECTORY_NOTIFICATIONS //通知音保存的位置
DIRECTORY_PICTURES //下載的圖片保存的位置
DIRECTORY_PODCASTS //用於保存podcast(博客)的音頻文件
DIRECTORY_RINGTONES //保存鈴聲的位置

 

File directory_pictures = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);

Log.e(TAG, "directory_pictures="+directory_pictures);

得到的路徑如下: 

這里寫圖片描述

第二種方法是一個更加方便的訪問Android給我們提供好的一些公共目錄的方法,第一種方式更加靈活,可以自己指定目錄。

 

===================================================================

Android系統提供了Environment.getExternalStorageDirectory()接口獲得存儲設備的路徑,但是這個接口往往給出的結果並不是我們想要的,在某些設備上它返回的是手機內部存儲,某些設備上返回的手機外部存儲。還有就是某些android設備支持擴展多個sdcard,這個時候想要獲得所有存儲器的掛載路徑,這個接口是沒有辦法辦到的。

那么,Android系統的文件管理器是如何把所有掛載的存儲設備加載出來的呢?通過查看文件管理器的源碼發現是在MountPointManager類中處理的,通過調用StorageManager類的getVolumeList()方法獲取的。

 

[java]  view plain  copy
 
  1. /** 
  2.     * This method initializes MountPointManager. 
  3.     *  
  4.     * @param context Context to use 
  5.     */  
  6.    public void init(Context context) {  
  7.        mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);  
  8.        final String defaultPath = getDefaultPath();  
  9.        LogUtils.d(TAG, "init,defaultPath = " + defaultPath);     
  10.        if (!TextUtils.isEmpty(defaultPath)) {  
  11.            mRootPath = ROOT_PATH;  
  12.        }  
  13.        mMountPathList.clear();  
  14.        // check media availability to init mMountPathList  
  15.        StorageVolume[] storageVolumeList = mStorageManager.getVolumeList();  
  16.        if (storageVolumeList != null) {  
  17.            for (StorageVolume volume : storageVolumeList) {  
  18.                MountPoint mountPoint = new MountPoint();  
  19.                mountPoint.mDescription = volume.getDescription(context);  
  20.                mountPoint.mPath = volume.getPath();  
  21.                mountPoint.mIsMounted = isMounted(volume.getPath());  
  22.                mountPoint.mIsExternal = volume.isRemovable();  
  23.                mountPoint.mMaxFileSize = volume.getMaxFileSize();  
  24.                LogUtils.d(TAG, "init,description :" + mountPoint.mDescription + ",path : "  
  25.                        + mountPoint.mPath + ",isMounted : " + mountPoint.mIsMounted  
  26.                        + ",isExternal : " + mountPoint.mIsExternal + ", mMaxFileSize: " + mountPoint.mMaxFileSize);  
  27.                mMountPathList.add(mountPoint);  
  28.            }  
  29.        }  
  30.        IconManager.getInstance().init(context, defaultPath + SEPARATOR);  
  31.    }  


系統提供了StorageManager類,它有一個方法叫getVolumeList(),這個方法的返回值是一個StorageVolume數組,StorageVolume類中封裝了掛載路徑,掛載狀態,以及是否可以移除等信息。下面是這個方法的源碼。

 

 

[java]  view plain  copy
 
  1. /** 
  2.  * Returns list of all mountable volumes. 
  3.  * @hide 
  4.  */  
  5. public StorageVolume[] getVolumeList() {  
  6.     if (mMountService == null) return new StorageVolume[0];  
  7.     try {  
  8.         Parcelable[] list = mMountService.getVolumeList();  
  9.         if (list == null) return new StorageVolume[0];  
  10.         int length = list.length;  
  11.         StorageVolume[] result = new StorageVolume[length];  
  12.         for (int i = 0; i < length; i++) {  
  13.             result[i] = (StorageVolume)list[i];  
  14.         }  
  15.         return result;  
  16.     } catch (RemoteException e) {  
  17.         Log.e(TAG, "Failed to get volume list", e);  
  18.         return null;  
  19.     }  
  20. }  


getVolumeList()方法是隱藏的,不能在應用代碼中直接調用,所以我們只能通過反射來調用這個方法了。

 

 

通過反射機制獲取Android設備的所有存儲設備

 

[java]  view plain  copy
 
  1. public class StorageInfo {  
  2.     public String path;  
  3.     public String state;  
  4.     public boolean isRemoveable;  
  5.     public StorageInfo(String path) {  
  6.         this.path = path;  
  7.     }  
  8.     public boolean isMounted() {  
  9.         return "mounted".equals(state);  
  10.     }  
  11.     @Override  
  12.     public String toString() {  
  13.         return "StorageInfo [path=" + path + ", state=" + state  
  14.                 + ", isRemoveable=" + isRemoveable + "]";  
  15.     }  
  16. }  

 

 

[java]  view plain  copy
 
  1. public static List<StorageInfo> listAllStorage(Context context) {  
  2.     ArrayList<StorageInfo> storages = new ArrayList<StorageInfo>();  
  3.     StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);  
  4.     try {  
  5.         Class<?>[] paramClasses = {};  
  6.         Method getVolumeList = StorageManager.class.getMethod("getVolumeList", paramClasses);  
  7.         Object[] params = {};  
  8.         Object[] invokes = (Object[]) getVolumeList.invoke(storageManager, params);  
  9.           
  10.         if (invokes != null) {  
  11.             StorageInfo info = null;  
  12.             for (int i = 0; i < invokes.length; i++) {  
  13.                 Object obj = invokes[i];  
  14.                 Method getPath = obj.getClass().getMethod("getPath", new Class[0]);  
  15.                 String path = (String) getPath.invoke(obj, new Object[0]);  
  16.                 info = new StorageInfo(path);  
  17.   
  18.                 Method getVolumeState = StorageManager.class.getMethod("getVolumeState", String.class);  
  19.                 String state = (String) getVolumeState.invoke(storageManager, info.path);  
  20.                 info.state = state;  
  21.   
  22.                 Method isRemovable = obj.getClass().getMethod("isRemovable", new Class[0]);  
  23.                 info.isRemoveable = ((Boolean) isRemovable.invoke(obj, new Object[0])).booleanValue();  
  24.                 storages.add(info);  
  25.             }  
  26.         }  
  27.     } catch (Exception e) {  
  28.         e.printStackTrace();  
  29.     }  
  30.     storages.trimToSize();  
  31.     return storages;  
  32. }  
  33.   
  34. public static List<StorageInfo> getAvaliableStorage(List<StorageInfo> infos){  
  35.     List<StorageInfo> storages = new ArrayList<StorageInfo>();  
  36.     for(StorageInfo info : infos){  
  37.         File file = new File(info.path);  
  38.         if ((file.exists()) && (file.isDirectory()) && (file.canWrite())) {  
  39.             if (info.isMounted()) {  
  40.                 storages.add(info);  
  41.             }  
  42.         }  
  43.     }  
  44.       
  45.     return storages;  
  46. }  

 

調用上述方法:

 

[java]  view plain  copy
 
  1. List<StorageInfo> list = listAllStorage(this);  
  2. for(StorageInfo info : list){  
  3.     Log.e(TAG, info.toString());  
  4. }  
  5. Log.e(TAG, "-----------------");  
  6. List<StorageInfo> infos = getAvaliableStorage(list);  
  7. for(StorageInfo info : infos){  
  8.     Log.e(TAG, info.toString());  
  9. }  
  10.   
  11. Log.e(TAG, "Environment.getExternalStorageDirectory(): " + Environment.getExternalStorageDirectory());  

 

連上手機進行驗證,輸出Log信息:

 

可以看到,通過listAllStorage()方法獲取到了手機上的所有存儲設備,通過getAvaliableStorage()方法的過濾獲取到了掛載狀態的所有存儲設備。由於該手機只有一個可讀寫的存儲設備,因此與Environment.getExternalStorageDirectory()方法獲取到的結果一致。

 

 

===================================================================

getExternalFilesDir(null)參數傳入的為null,這樣默認訪問的是files文件夾,我們可以指定子文件夾

getExternalFilesDir(null) 得到  "/mmn/sdcard/Android/data/< package name >/files/

getExternalFilesDir("Caches") 得到 "/mmn/sdcard/Android/data/< package name >/files/Caches"

 

有些時候我們的手機沒有安裝SD卡,所以我們使用前需要判斷一下:

if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { //SD卡已裝入 }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM