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

介绍

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

提示

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

FileManager的使用

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

private static FileManager mInstance;
private static Context mContext;
private 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
 */
public 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
 */
public 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获取视频缩略图

// 获取视频缩略图
public 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对象。

获取本机所有图片文件夹

/**
 * 得到图片文件夹集合
 */
public 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方法
}

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

/**
 * 通过图片文件夹的路径获取该目录下的图片
 */
public 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的列表
 */
public 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安装包等

/**
 * 通过文件类型得到相应文件的集合
 **/
public 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目录下的文件)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 161,513评论 4 369
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,312评论 1 305
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 111,124评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,529评论 0 217
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,937评论 3 295
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,913评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,084评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,816评论 0 205
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,593评论 1 249
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,788评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,267评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,601评论 3 261
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,265评论 3 241
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,158评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,953评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,066评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,852评论 2 277

推荐阅读更多精彩内容

  • 最近想系统的学习一下Spring的相关知识,在这里分享一下。也希望能帮助那些对英文技术文档阅读比较困难的朋友。接下...
    Aiibai阅读 1,499评论 5 16
  • 那天在采采吃饭的时候,你说到了暗示一词。“我不习惯把想着的全部说出,而只是暗示着。” 当时并没有在意。因为我们只是...
    9198b4fcf27e阅读 92评论 0 0
  • 文/蒹葭 “奶奶,爸爸妈妈每次回家都只待两三天。也不带我玩,我和他们没有一点感情!” “瞎说,长大后你就懂了……”...
    一只蒹葭阅读 1,527评论 85 59
  • 事情分三类,喜,恶,平。 喜的,愿意为其付出时间,精力,愿意接受不好的结果。也许它没有太大的价值。但是差不多会忽略...
    安南美阅读 705评论 0 1
  • 保定出差第一天 安顿好之后已经是晚上了,很多以为的事只是以为,没有调查就没有发言权。
    翔子52双鱼阅读 213评论 0 1