美文网首页
Android版本6.0以上SD卡相关方法

Android版本6.0以上SD卡相关方法

作者: KevinGarnett21 | 来源:发表于2021-09-13 20:04 被阅读0次

    Android版本6.0以上SD卡相关方法(反射)

    1. 概述

    1. 主要是获取SD外置存储卡的相关方法;
    2. 获取内置存储卡视频或者图片大小;
    3. 千万注意: 首先要申请Android的读取权限;

    2. 获取SD卡路径方法

    1) 获取StorageManager的实例

    StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
    

    2) 通过反射获取存储卡的集合

    // 反射获取存储卡的集合
    Method getVolumeList = StorageManager.class.getDeclaredMethod("getVolumeList");
    List<Object> getVolumeInfo = (List<Object>) getVolumes.invoke(storageManager);
    
    // 反射获取SD卡的类型 
    // 1. TYPE_PRIVATE 内部存储
    // 2. TYPE_PUBLIC  外部存储(这就是我们需要获取的SD卡)
    Field getType = obj.getClass().getField("type");
    

    3) 通过反射获取是否可读以及存储卡路径

    // 1. 是否可读(可读可以获取SD卡的路径以及总内存和剩余内存)
    Method isMountedReadable = obj.getClass().getDeclaredMethod("isMountedReadable");
    boolean readable = (boolean) isMountedReadable.invoke(obj);
    
    // 2. 获取SD卡路径
    Method file = obj.getClass().getDeclaredMethod("getPath");
    File f = (File) file.invoke(obj);
    
    // 3. 根据路径获取总内存以及剩余内存
    long total = f.getTotalSpace();
    long used = f.getFreeSpace();
    

    3. 格式化以及挂载的方法(一般都是搭配使用)

    // 1. 反射格式化的方法
    Method format = StorageManager.class.getDeclaredMethod("format", String.class);
    format.invoke(storageManager, id);
    // 2. 反射挂载的方法
    Method mount = StorageManager.class.getDeclaredMethod("mount", new Class[]{String.class});
    mount.invoke(storageManager, id);
    

    PS: 遍历内置存储卡所有视频以及图片(以视频为例)

    注意: 外置存储卡目前我没找到方法测试

    // 1. 通过上下文获取ContentResolver
    ContentResolver resolver = context.getContentResolver();
    
    // 2. 创建想要查询的内容数组(拿视频为例)
    // 名称 、 大小 、 路径
    String[] querys = new String[]{MediaStore.Video.Media.DISPLAY_NAME,
                        MediaStore.Video.Media.SIZE, MediaStore.Video.Media.DATA};;
    
    // 3. 创建Uri
    Urli uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
    
    // 4. 开始查询(注意 cursor可能为空,需要注意判空)
    Cursor cursor = resolver.query(uri, querys, null, null, null);
    
    // 5 . 开始查询(注意是根据querys一一对应的)
    String displayName = cursor.getString(0);
    int siz = cursor.getInt(1);
    String data = cursor.getString(2);
    
    // 可以打印这些数据查看
    
    

    最后: 附详细代码

    public class StorageUtils {
    
        private final static String TAG = "StorageUtils";
    
        // 是否有外置存储卡
        public static boolean hasSd = false;
    
        public static StorageManager storageManager;
    
        public static boolean initSd(Context context) {
            storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
            // 1000单位,个人测过的大部分是以1000为单位的,部分是1024,实际使用可以自己测试下
            float unit = 1000;
            try {
                Method getVolumes = StorageManager.class.getDeclaredMethod("getVolumes");
                List<Object> getVolumeInfo = (List<Object>) getVolumes.invoke(storageManager);
                if (null != getVolumeInfo && getVolumeInfo.size() > 0) {
    
                    for (int i = 0; i < getVolumeInfo.size(); i++) {
                        Object obj = getVolumeInfo.get(i);
                        Field getType = obj.getClass().getField("type");
                        int type = getType.getInt(obj);
                        if (type == 0) {//TYPE_PUBLIC
                            //外置存储
                            Method isMountedReadable = obj.getClass().getDeclaredMethod("isMountedReadable");
                            boolean readable = (boolean) isMountedReadable.invoke(obj);
                            if (readable) {
                                hasSd = true;
                                Method file = obj.getClass().getDeclaredMethod("getPath");
                                File f = (File) file.invoke(obj);
                                //外置存储
                                String path = getPath(obj);
                                long total = f.getTotalSpace();
                                long free = f.getFreeSpace();
                                Log.e(TAG, "外置:" + path + ",total:" + getUnit(total, unit) + ",free:" + getUnit(free, unit));
                            }
                        }
                    }
                    return true;
                }
            } catch (SecurityException e) {
                Log.e(TAG, "请检查权限");
            } catch (Exception e) {
                e.printStackTrace();
            }
            return false;
        }
    
        private static String getPath(Object obj) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
            String sdPath = "";
            Method isMountedReadable = obj.getClass().getDeclaredMethod("isMountedReadable");
            boolean readable = (boolean) isMountedReadable.invoke(obj);
            if (readable) {
                Method file = obj.getClass().getDeclaredMethod("getPath");
                File f = (File) file.invoke(obj);
                sdPath = f.getPath();
            }
            return sdPath;
        }
    
        // 获取外置存储卡视频的大小
        public static long getVideoSize(Context context) {
            //获取ContentResolver实例
            long total = 0;
            ContentResolver resolver = context.getContentResolver();
            // 视频为例: 需要查询的内容->名称,大小,路径
            String[] querys= new String[]{MediaStore.Video.Media.DISPLAY_NAME,
                    MediaStore.Video.Media.SIZE, MediaStore.Video.Media.DATA};
            Uri uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
            //开始查询,查询结果是一个cursor对象
            Cursor cursor = resolver.query(uri, querys, null, null, null);
            //若查询的Uri不存在,则cursor为空,所以要做非空判断
            if (cursor != null) {
                while (cursor.moveToNext()) {
                    // 判断路径
                    String displayName = cursor.getString(0);
                    int size = cursor.getInt(1);
                    String filePath = cursor.getString(2);
                    total += size;
                    
                    Log.e(TAG,"name:"+displayName+",size:"+size+",path:"+filePath);
                }
                //记得关闭cursor
                cursor.close();
                Log.e(TAG,"video total size:"+total);
            }
            return total;
        }
    
        // 格式化SD卡以及挂载
        private static void format(String id) {
            try {
                Method format = StorageManager.class.getDeclaredMethod("format", String.class);
                Method mount = StorageManager.class.getDeclaredMethod("mount", new Class[]{String.class});
                format.invoke(storageManager, id);
                mount.invoke(storageManager, id);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
    
        private static final String[] units = {"B", "KB", "MB", "GB", "TB"};
    
        /**
         * 进制转换
         */
        public static String getUnit(float size, float base) {
            int index = 0;
            while (size > base && index < 4) {
                size = size / base;
                index++;
            }
            return String.format(Locale.getDefault(), " %.2f %s ", size, units[index]);
        }
    
    }
    

    相关文章

      网友评论

          本文标题:Android版本6.0以上SD卡相关方法

          本文链接:https://www.haomeiwen.com/subject/funfgltx.html