zoukankan      html  css  js  c++  java
  • 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卡已装入 }

  • 相关阅读:
    泛型约束new()的使用
    控制反转-依赖注入
    微服务的六个基本点
    java反编译工具
    Idea中一些常用设置
    JSP内置对象(9个常用的内置对象)
    输出输入流,的应用

    容器集合类
    容器与集合
  • 原文地址:https://www.cnblogs.com/lucktian/p/7016636.html
Copyright © 2011-2022 走看看