安卓学习笔记获取手机内存与SD卡路径及大小

实现原理

  • 通过反射,调用StorageManger被隐藏接口getVolumePaths(),来获得手机的存储路径,进而通过StatFs获取区块blockCount与blockSize的大小,以计算出内存值
  • 在使用getBlockCountLong(),getBlockSizeLong(),getAvailableBlocks()时要注意api>=18;

方法代码

/**
     * 获取ROM总大小
     * @param context
     * @return
     */
    public static String getMaxRomSpace(Context context) {
        StatFs fs = new StatFs(getInnerSDCardPath(context));
        String romSpace; 
        if (Build.VERSION.SDK_INT  >=18) {
            long blockCount = fs.getBlockCountLong();
            long bloackSize = fs.getBlockSizeLong();
            long totalSpace = bloackSize*blockCount;
            romSpace = Formatter.formatFileSize(context, totalSpace);
        }else{
            long blockCount = fs.getBlockCount();
            long bloackSize = fs.getBlockSize();
            long totalSpace = bloackSize*blockCount;
            romSpace = Formatter.formatFileSize(context, totalSpace);
        }
        return romSpace;
    }
/**
     * 获取SD卡总大小
     * @param context
     * @return
     */
    public static String getMaxSDSpace(Context context) {
        String extPath = getExtSDCardPath(context);
        if (TextUtils.isEmpty(extPath)) {
            Toast.makeText(context, "无SD卡", 0).show();
            return null;
        }
        File path = new File(extPath);
        StatFs fs = new StatFs(path.getPath());
        String sdSpace;
        if (Build.VERSION.SDK_INT  >=18) {
            long blockCount = fs.getBlockCountLong();
            long bloackSize = fs.getBlockSizeLong();
            long totalSpace = bloackSize*blockCount;
            sdSpace = Formatter.formatFileSize(context, totalSpace);
        }else{
            long blockCount = fs.getBlockCount();
            long bloackSize = fs.getBlockSize();
            long totalSpace = bloackSize*blockCount;
            sdSpace = Formatter.formatFileSize(context, totalSpace);
        }
        return sdSpace;
    }
/**
     * 获取rom可用大
     * 小
     * @param context
     * @return
     */
    public static String getAvailableRomSpace(Context context) {
        File path = Environment.getDataDirectory();
        StatFs fs = new StatFs(path.getPath());
        String Space = null ;
        if (Build.VERSION.SDK_INT  >=18) {

            long blockCount = fs.getAvailableBlocksLong();
            long bloackSize = fs.getBlockSizeLong();
            long totalSpace = bloackSize*blockCount;
            Space = Formatter.formatFileSize(context, totalSpace);
        }else{
            long blockCount = fs.getAvailableBlocks();
            long bloackSize = fs.getBlockSize();
            long totalSpace = bloackSize*blockCount;
            Space = Formatter.formatFileSize(context, totalSpace);
        }
        return Space;
    }

    /**
     * 获取SD卡可用大小
     * @param context
     * @return
     */
    public static String getAvailableSdSpace(Context context) {
        String extPath = getExtSDCardPath(context);
        if (TextUtils.isEmpty(extPath)) {
            Toast.makeText(context, "无SD卡", 0).show();
            return null;
        }
        File path = new File(extPath);
        StatFs fs = new StatFs(path.getPath());
        String Space;
        if (Build.VERSION.SDK_INT >=18) {
            long blockCount = fs.getAvailableBlocksLong();
            long bloackSize = fs.getBlockSizeLong();
            long totalSpace = bloackSize*blockCount;
            Space = Formatter.formatFileSize(context, totalSpace);
        }else{
            long blockCount = fs.getAvailableBlocks();
            long bloackSize = fs.getBlockSize();
            long totalSpace = bloackSize*blockCount;
            Space = Formatter.formatFileSize(context, totalSpace);
        }
        return Space;
    }
    /**
     * 获取外置SD卡路径
     * @return  应该就一条记录或空
     */
    public static String getExtSDCardPath(Context context){
        StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
        try {
            getPathsMethod = sm.getClass().getMethod("getVolumePaths", null);
            String[] path = (String[]) getPathsMethod.invoke(sm, null);
            return path[1];
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 获取内置内存路径
     * @return  应该就一条记录或空
     */
    public static String getInnerSDCardPath(Context context){
        StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
        try {
            getPathsMethod = sm.getClass().getMethod("getVolumePaths", null);
            String[] path = (String[]) getPathsMethod.invoke(sm, null);
            return path[0];
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }

注意:随着Android版本的变化以及权限加强,以上方法可能不再生效。


2018/1/15更新

  • 首先拿到StorageManager,然后通过它使用反射拿到getVolumeList方法,getVolumeList方法反射得到StorageVolume数组
  • 遍历该StorageVolume数组,得到每一个StorageVolume,并使用反射得到其getPath方法
  • getPath反射得到路径,通过StorageVolume的isRemovale方法还可以判断是否可以移除(实际上可移除的为sdcard)
    /**
    * 获取Android内部存储或外置SD卡路径
    *
    * @param context  上下文
    * @param isRemovale true获取的是外部存储,false获取的是内部存储
    * @return
    */
   public static String getStoragePath(Context context, boolean isRemovale) {
       // 拿到StorageManager
       StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
       Class<?> storageVolumeClazz = null;
       try {
           // 反射获得StorageVolume
           storageVolumeClazz = Class.forName("android.os.storage.StorageVolume");
           // 反射获得StorageManager的getVolumeList方法
           Method getVolumeList = storageManager.getClass().getMethod("getVolumeList");
           // 反射获得StorageVolume的getPath方法
           Method getPath = storageVolumeClazz.getMethod("getPath");
           // 拿到StorageVolume的isRemovable方法
           Method isRemovable = storageVolumeClazz.getMethod("isRemovable");
           Object result = getVolumeList.invoke(storageManager); // 得到Storage Volume数组
           final int length = Array.getLength(result);
           for (int i = 0; i < length; i++) {  // 遍历数组,拿到StorageVolume中的路径mPath
               Object storageVolume = Array.get(result, i);
               String path = (String) getPath.invoke(storageVolume);
               // 判断是否是可移除的,可移除表示是sdcard
               boolean removable = (Boolean) isRemovable.invoke(storageVolume);
               if (isRemovale == removable) { // isRemovale为true返回sdcard路径,false返回内部存储路径
                   return path;
               }
           }
       } catch (ClassNotFoundException e) {
           e.printStackTrace();
       } catch (InvocationTargetException e) {
           e.printStackTrace();
       } catch (NoSuchMethodException e) {
           e.printStackTrace();
       } catch (IllegalAccessException e) {
           e.printStackTrace();
       }
       return null;
   }

注:以上方法通过Java反射实现的,不太了解的可以参考Java反射机制

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值