手记

Android获取本机各种类型文件列表(音乐、视频、图片、文档等)

介绍

本篇介绍Android获取本机各种类型文件的方法,已经封装成工具类,末尾有源码下载地址。

提示

获取音乐、视频、图片、文档等文件是需要有读取SD卡的权限的,如果是6.0以下的系统,则直接在清单文件中声明SD卡读取权限即可;如果是6.0或以上,则需要动态申请权限。

FileManager的使用

FileManager是封装好的用于获取本机各类文件的工具类,使用方式如:FileManager.getInstance(Context context).getMusics(),使用的是单例模式创建:

    private static FileManager mInstance;
    private static Context mContext;
    public static ContentResolver mContentResolver;
    private static Object mLock = new Object();

    public static FileManager getInstance(Context context){
         if (mInstance == null){
             synchronized (mLock){
                 if (mInstance == null){
                     mInstance = new FileManager();
                     mContext = context;
                     mContentResolver = context.getContentResolver();
                 }
             }
         }
        return mInstance;
    }

获取音乐列表

    /**
     * 获取本机音乐列表
     * @return
     */
    private static List<Music> getMusics() {
        ArrayList<Music> musics = new ArrayList<>();
        Cursor c = null;
        try {
            c = mContentResolver.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null,
                    MediaStore.Audio.Media.DEFAULT_SORT_ORDER);

            while (c.moveToNext()) {
                String path = c.getString(c.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA));// 路径

                if (FileUtils.isExists(path)) {
                    continue;
                }

                String name = c.getString(c.getColumnIndexOrThrow(MediaStore.Audio.Media.DISPLAY_NAME)); // 歌曲名
                String album = c.getString(c.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM)); // 专辑
                String artist = c.getString(c.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST)); // 作者
                long size = c.getLong(c.getColumnIndexOrThrow(MediaStore.Audio.Media.SIZE));// 大小
                int duration = c.getInt(c.getColumnIndexOrThrow(MediaStore.Audio.Media.DURATION));// 时长
                int time = c.getInt(c.getColumnIndexOrThrow(MediaStore.Audio.Media._ID));// 歌曲的id
                // int albumId = c.getInt(c.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM_ID));

                Music music = new Music(name, path, album, artist, size, duration);
                musics.add(music);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (c != null) {
                c.close();
            }
        }
        return musics;
    }

FileUtils中判断文件是否存在的方法isExists(String path),代码为:

    /**
     * 判断文件是否存在
     * @param path 文件的路径
     * @return
     */
    public static boolean isExists(String path) {
        File file = new File(path);
        return file.exists();
    }

音乐的bean类Music代码为:

    public class Music implements Comparable<Music> {
        /**歌曲名*/
        private String name;
        /**路径*/
        private String path;
        /**所属专辑*/
        private String album;
        /**艺术家(作者)*/
        private String artist;
        /**文件大小*/
        private long size;
        /**时长*/
        private int duration;
        /**歌曲名的拼音,用于字母排序*/
        private String pinyin;

        public Music(String name, String path, String album, String artist, long size, int duration) {
            this.name = name;
            this.path = path;
            this.album = album;
            this.artist = artist;
            this.size = size;
            this.duration = duration;
            pinyin = PinyinUtils.getPinyin(name);
        }

        ... //此处省略setter和getter方法
    }

PinyinUtils根据名字获取拼音,主要是用于音乐列表A-Z的排序,需要依赖pinyin4j.jar,获取拼音的方法getPinyin(String name)代码为:

    public static String getPinyin(String str) {
        // 设置拼音结果的格式
        HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
        format.setCaseType(HanyuPinyinCaseType.UPPERCASE);// 设置为大写形式
        format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);// 不用加入声调

        StringBuilder sb = new StringBuilder();

        char[] charArray = str.toCharArray();

        for (int i = 0; i < charArray.length; i++) {
            char c = charArray[i];

            if (Character.isWhitespace(c)) {// 如果是空格则跳过
                continue;
            }

            if (isHanZi(c)) {// 如果是汉字
                String s = "";
                try {
                    // toHanyuPinyinStringArray 返回一个字符串数组是因为该汉字可能是多音字,此处只取第一个结果
                    s = PinyinHelper.toHanyuPinyinStringArray(c, format)[0];
                    sb.append(s);
                } catch (BadHanyuPinyinOutputFormatCombination e) {
                    e.printStackTrace();
                    sb.append(s);
                }

            } else {
                // 不是汉字
                if (i == 0) {
                    if (isEnglish(c)) {// 第一个属于字母,则返回该字母
                        return String.valueOf(c).toUpperCase(Locale.ENGLISH);
                    }
                    return "#"; // 不是的话返回#号
                }
            }
        }
        return sb.toString();
    }

获取视频列表

    /**
     * 获取本机视频列表
     * @return
     */
    private static List<Video> getVideos() {

        List<Video> videos = new ArrayList<Video>();

        Cursor c = null;
        try {
            // String[] mediaColumns = { "_id", "_data", "_display_name",
            // "_size", "date_modified", "duration", "resolution" };
            c = mContentResolver.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, null, null, null, MediaStore.Video.Media.DEFAULT_SORT_ORDER);
            while (c.moveToNext()) {
                String path = c.getString(c.getColumnIndexOrThrow(MediaStore.Video.Media.DATA));// 路径
                if (!FileUtils.isExists(path)) {
                    continue;
                }

                int id = c.getInt(c.getColumnIndexOrThrow(MediaStore.Video.Media._ID));// 视频的id
                String name = c.getString(c.getColumnIndexOrThrow(MediaStore.Video.Media.DISPLAY_NAME)); // 视频名称
                String resolution = c.getString(c.getColumnIndexOrThrow(MediaStore.Video.Media.RESOLUTION)); //分辨率
                long size = c.getLong(c.getColumnIndexOrThrow(MediaStore.Video.Media.SIZE));// 大小
                long duration = c.getLong(c.getColumnIndexOrThrow(MediaStore.Video.Media.DURATION));// 时长
                long date = c.getLong(c.getColumnIndexOrThrow(MediaStore.Video.Media.DATE_MODIFIED));//修改时间

                Video video = new Video(id, path, name, resolution, size, date, duration);
                videos.add(video);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (c != null) {
                c.close();
            }
        }
        return videos;
    }

其中,视频的bean类Video代码为:

    public class Video {
        private int id = 0;
        private String path = null;
        private String name = null;
        private String resolution = null;// 分辨率
        private long size = 0;
        private long date = 0;
        private long duration = 0;

        public Video(int id, String path, String name, String resolution, long size, long date, long duration) {
            this.id = id;
            this.path = path;
            this.name = name;
            this.resolution = resolution;
            this.size = size;
            this.date = date;
            this.duration = duration;
        }

        ... //此处省略setter和getter方法
    }

通过本地视频id获取视频缩略图

    // 获取视频缩略图
    private static Bitmap getVideoThumbnail(int id) {
        Bitmap bitmap = null;
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inDither = false;
        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
        bitmap = MediaStore.Video.Thumbnails.getThumbnail(mContentResolver, id, MediaStore.Images.Thumbnails.MICRO_KIND, options);
        return bitmap;
    }

上面获取视频列表的方法中,Video对象中有一个属性是id,通过传入这个id可以获取到视频缩略图的Bitmap对象。

### 获取本机所有图片文件夹

    /**
     * 得到图片文件夹集合
     */
    private static List<ImgFolderBean> getImageFolders() {
        List<ImgFolderBean> folders = new ArrayList<ImgFolderBean>();
        // 扫描图片
        Cursor c = null;
        try {
            c = mContentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null,
                    MediaStore.Images.Media.MIME_TYPE + "= ? or " + MediaStore.Images.Media.MIME_TYPE + "= ?",
                    new String[]{"image/jpeg", "image/png"}, MediaStore.Images.Media.DATE_MODIFIED);
            List<String> mDirs = new ArrayList<String>();//用于保存已经添加过的文件夹目录
            while (c.moveToNext()) {
                String path = c.getString(c.getColumnIndex(MediaStore.Images.Media.DATA));// 路径
                File parentFile = new File(path).getParentFile();
                if (parentFile == null)
                    continue;

                String dir = parentFile.getAbsolutePath();
                if (mDirs.contains(dir))//如果已经添加过
                    continue;

                mDirs.add(dir);//添加到保存目录的集合中
                ImgFolderBean folderBean = new ImgFolderBean();
                folderBean.setDir(dir);
                folderBean.setFistImgPath(path);
                if (parentFile.list() == null)
                    continue;
                int count = parentFile.list(new FilenameFilter() {
                    @Override
                    public boolean accept(File dir, String filename) {
                        if (filename.endsWith(".jpeg") || filename.endsWith(".jpg") || filename.endsWith(".png")) {
                            return true;
                        }
                        return false;
                    }
                }).length;

                folderBean.setCount(count);
                folders.add(folderBean);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (c != null) {
                c.close();
            }
        }

        return folders;
    }

其中,图片文件夹的bean类ImgFolderBean代码为:

    public class ImgFolderBean {
        /**当前文件夹的路径*/
        private String dir;
        /**第一张图片的路径,用于做文件夹的封面图片*/
        private String fistImgPath;
        /**文件夹名*/
        private String name;
        /**文件夹中图片的数量*/
        private int count;

        public ImgFolderBean(String dir, String fistImgPath, String name, int count) {
            this.dir = dir;
            this.fistImgPath = fistImgPath;
            this.name = name;
            this.count = count;
        }

        ... //此处省略setter和getter方法
    }

获取图片文件夹下的图片路径的集合

    /**
     * 通过图片文件夹的路径获取该目录下的图片
     */
    private static List<String> getImgListByDir(String dir) {
        ArrayList<String> imgPaths = new ArrayList<>();
        File directory = new File(dir);
        if (directory == null || !directory.exists()) {
            return imgPaths;
        }
        File[] files = directory.listFiles();
        for (File file : files) {
            String path = file.getAbsolutePath();
            if (FileUtils.isPicFile(path)) {
                imgPaths.add(path);
            }
        }
        return imgPaths;
    }

获取本机已安装应用列表

    /**
     * 获取已安装apk的列表
     */
    private static List<AppInfo> getAppInfos() {

        ArrayList<AppInfo> appInfos = new ArrayList<AppInfo>();
        //获取到包的管理者
        PackageManager packageManager = mContext.getPackageManager();
        //获得所有的安装包
        List<PackageInfo> installedPackages = packageManager.getInstalledPackages(0);

        //遍历每个安装包,获取对应的信息
        for (PackageInfo packageInfo : installedPackages) {

            AppInfo appInfo = new AppInfo();

            appInfo.setApplicationInfo(packageInfo.applicationInfo);
            appInfo.setVersionCode(packageInfo.versionCode);

            //得到icon
            Drawable drawable = packageInfo.applicationInfo.loadIcon(packageManager);
            appInfo.setIcon(drawable);

            //得到程序的名字
            String apkName = packageInfo.applicationInfo.loadLabel(packageManager).toString();
            appInfo.setApkName(apkName);

            //得到程序的包名
            String packageName = packageInfo.packageName;
            appInfo.setApkPackageName(packageName);

            //得到程序的资源文件夹
            String sourceDir = packageInfo.applicationInfo.sourceDir;
            File file = new File(sourceDir);
            //得到apk的大小
            long size = file.length();
            appInfo.setApkSize(size);

            System.out.println("---------------------------");
            System.out.println("程序的名字:" + apkName);
            System.out.println("程序的包名:" + packageName);
            System.out.println("程序的大小:" + size);

            //获取到安装应用程序的标记
            int flags = packageInfo.applicationInfo.flags;

            if ((flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
                //表示系统app
                appInfo.setIsUserApp(false);
            } else {
                //表示用户app
                appInfo.setIsUserApp(true);
            }

            if ((flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
                //表示在sd卡
                appInfo.setIsRom(false);
            } else {
                //表示内存
                appInfo.setIsRom(true);
            }

            appInfos.add(appInfo);
        }
        return appInfos;
    }

其中,安装包信息的bean类AppInfo代码为:

    public class AppInfo {
        private ApplicationInfo applicationInfo;
        private int versionCode = 0;
        /**
         * 图片的icon
         */
        private Drawable icon;

        /**
         * 程序的名字
         */
        private String apkName;

        /**
         * 程序大小
         */
        private long apkSize;

        /**
         * 表示到底是用户app还是系统app
         * 如果表示为true 就是用户app
         * 如果是false表示系统app
         */
        private boolean isUserApp;

        /**
         * 放置的位置
         */
        private boolean isRom;

        /**
         * 包名
         */
        private String apkPackageName;

        ... //此处省略setter和getter方法
    }

获取文档、压缩包、apk安装包等

    /**
     * 通过文件类型得到相应文件的集合
     **/
    private static List<FileBean> getFilesByType(int fileType) {
        List<FileBean> files = new ArrayList<FileBean>();
        // 扫描files文件库
        Cursor c = null;
        try {
            c = mContentResolver.query(MediaStore.Files.getContentUri("external"), new String[]{"_id", "_data", "_size"}, null, null, null);
            int dataindex = c.getColumnIndex(MediaStore.Files.FileColumns.DATA);
            int sizeindex = c.getColumnIndex(MediaStore.Files.FileColumns.SIZE);

            while (c.moveToNext()) {
                String path = c.getString(dataindex);

                if (FileUtils.getFileType(path) == fileType) {
                    if (!FileUtils.isExists(path)) {
                        continue;
                    }
                    long size = c.getLong(sizeindex);
                    FileBean fileBean = new FileBean(path, FileUtils.getFileIconByPath(path));
                    files.add(fileBean);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (c != null) {
                c.close();
            }
        }
        return files;
    }

传入的fileType文件类型是在FileUtils定义的文件类型声明:

    /**文档类型*/
    public static final int TYPE_DOC = 0;
    /**apk类型*/
    public static final int TYPE_APK = 1;
    /**压缩包类型*/
    public static final int TYPE_ZIP = 2;

其中,FileUtils根据文件路径获取文件类型的方法getFileType(String path)为:

     public static int getFileType(String path) {
        path = path.toLowerCase();
        if (path.endsWith(".doc") || path.endsWith(".docx") || path.endsWith(".xls") || path.endsWith(".xlsx")
                || path.endsWith(".ppt") || path.endsWith(".pptx")) {
            return TYPE_DOC;
        }else if (path.endsWith(".apk")) {
            return TYPE_APK;
        }else if (path.endsWith(".zip") || path.endsWith(".rar") || path.endsWith(".tar") || path.endsWith(".gz")) {
            return TYPE_ZIP;
        }else{
            return -1;
        }
    }

文件的bean类FileBean代码为:

    public class FileBean {
       /** 文件的路径*/
        public String path;
        /**文件图片资源的id,drawable或mipmap文件中已经存放doc、xml、xls等文件的图片*/
        public int iconId;

        public FileBean(String path, int iconId) {
            this.path = path;
            this.iconId = iconId;
        }
    }

FileUtils根据文件类型获取图片资源id的方法,getFileIconByPath(path)代码为:

    /**通过文件名获取文件图标*/
    public static int getFileIconByPath(String path){
        path = path.toLowerCase();
        int iconId = R.mipmap.unknow_file_icon;
        if (path.endsWith(".txt")){
            iconId = R.mipmap.type_txt;
        }else if(path.endsWith(".doc") || path.endsWith(".docx")){
            iconId = R.mipmap.type_doc;
        }else if(path.endsWith(".xls") || path.endsWith(".xlsx")){
            iconId = R.mipmap.type_xls;
        }else if(path.endsWith(".ppt") || path.endsWith(".pptx")){
            iconId = R.mipmap.type_ppt;
        }else if(path.endsWith(".xml")){
            iconId = R.mipmap.type_xml;
        }else if(path.endsWith(".htm") || path.endsWith(".html")){
            iconId = R.mipmap.type_html;
        }
        return iconId;
    }

上述各种文件类型的图片放置在mipmap中,用于展示文件列表时展示。

FileManager以及其他类的源码,可以点击下面的网址跳转查看和下载:

点击查看源码(phone目录下的文件)

0人推荐
随时随地看视频
慕课网APP