可以导出来研究一下结构

4.4以及以下的通知系统刷新SD卡
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MEDIA_SCANNER_STARTED);
        intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED);
        intentFilter.addDataScheme("file");
        App.getINSTANCE().sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" +
                Environment.getExternalStorageDirectory())));

4.4以上替代广播的方案

可以用MediaScannerConnection类,有俩种使用方式

一 用MediaScannerConnection的静态方法

* @param context 上下文 * @param 查询的路径数组(这里也没说目录行不行,试了目录的好像不行,个人觉得还是用具体文件,下面会有解决方案) * @param mimeTypes 文件类型,具体对应表看文底部,这个可选,如果为null,则用扫到的后缀名作为mimeTypes * @param callback 扫描监听器,可选 * 更多内容看官方API public static void scanFile(Context context, String[] paths, String[] mimeTypes, OnScanCompletedListener callback) { ....隐藏内部实现...

上面也说了,第二个参数填目录名时不能正确扫描更新SD卡,不知道为啥,有知道的老铁麻烦告知,个人的替代方案是用具体的文件名来代替,先用File扫描所有的文件,然后再把扫到的文件的数组传入那个MediaScannerConnection.scanFile()中进行更新。
例如这里以扫描歌曲为例子,

//保存歌曲绝对路径的数组,这个用于MediaScannerConnection.scanFile()第二个参数 String[] songTotalPath = null; //现在假设要扫描sd卡下的opo目录,“/”这个斜杠别丢了,接下来用到的file相关方法啊啥的建议参考下File的类文档 File f = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/opo"); if (f.isDirectory()) { //测试f这个路径表示的文件是否是一个目录 File[] files = f.listFiles();//返回一个抽象(绝对)路径名数组,这些路径名表示此抽象路径名表示的目录中的文件 if (files != null) { //初始化数组长度 songTotalPath = new String[files.length]; for (int i = 0; i < songTotalPath.length; i++) { //默认路径,这里初始化数组每一项,只是单纯的防止后面用第二种方式扫描文件带来的空指针异常,无实际意义 songTotalPath[i] = Environment.getExternalStorageDirectory().getAbsolutePath(); for (int i = 0; i < files.length; i++) { if (files[i].isFile()) { //如果 扫到的是文件,那么把具体路径存到songTotalPath下 songTotalPath[i] = Environment.getExternalStorageDirectory().getAbsolutePath() + "/opo/" + files[i].getName(); //这里就可以直接用了,第三个这里用文件的后缀名,为空 MediaScannerConnection.scanFile(App.getINSTANCE(), songTotalPath, null, new MediaScannerConnection.OnScanCompletedListener() { @Override public void onScanCompleted(String path, Uri uri) { //扫描完成时逻辑

第二种 MediaScannerConnection.MediaScannerConnectionClient

这种方法就有点麻烦了,同样传入目录路径也是有问题,然后这里是
封装成了一个类MediaScanner,具体是

  • 先创建MediaScanner类实现MediaScannerConnection.MediaScannerConnectionClient的俩个方法
  •     @Override
        public void onMediaScannerConnected() {
        @Override
        public void onScanCompleted(String path, Uri uri) {
    
  • 在MediaScanner类中创建MediaScannerConnection的对象
    并在构造函数中初始化
  • 在onMediaScannerConnected方法中连接IMediaScannerService服务,只要调用就绑定了
  • mediaScannerConnection.connect();
    

    并且开始用参数扫描文件

    mediaScannerConnection.scanFile(filePaths[i], mimeTypes[i]);
    

    感觉第一种就是第二种的封装版

    MediaScanner类如下

    package com.minminaya.bogemusic.utils.localmusic;
    import android.content.Context;
    import android.media.MediaScannerConnection;
    import android.net.Uri;
     * Created by Niwa on 2017/5/29.
    public class MediaScanner implements MediaScannerConnection.MediaScannerConnectionClient {
        private MediaScannerConnection mediaScannerConnection = null;
        public MediaScanner(Context context) {
            mediaScannerConnection = new MediaScannerConnection(context, this);
        private String[] filePaths;
        private String[] mimeTypes;
        public void scanFiles(String[] filePaths, String[] mimeTypes) {
            this.filePaths = filePaths;
            this.mimeTypes = mimeTypes;
            mediaScannerConnection.connect();
        @Override
        public void onMediaScannerConnected() {
            for (int i = 0; i < filePaths.length; i++) {
                mediaScannerConnection.scanFile(filePaths[i], mimeTypes[i]);
            filePaths = null;
            mimeTypes = null;
        private int scanTimes = 0;
        @Override
        public void onScanCompleted(String path, Uri uri) {
    //        scanTimes++;
    //        if (scanTimes == filePaths.length) {
                mediaScannerConnection.disconnect();
    //            scanTimes = 0;
    //        }
    

    使用方法,在view(Activity或者Fragment)的启动生命周期中
    首先也是要扫描文件,这个和第一种的扫描文件基本复用的,只是中间加了防止后面调用mimeTypes数组空指针异常的初始化数组逻辑

     //保存歌曲绝对路径的数组,这个用于MediaScannerConnection.scanFile()第二个参数
            String[] songTotalPath = null;
            String[] mimeTypes = null;
            //现在假设要扫描sd卡下的opo目录,“/”这个斜杠别丢了,接下来用到的file相关方法啊啥的建议参考下File的类文档
            File f = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/opo");
            if (f.isDirectory()) {
                //测试f这个路径表示的文件是否是一个目录
                File[] files = f.listFiles();//返回一个抽象(绝对)路径名数组,这些路径名表示此抽象路径名表示的目录中的文件
                if (files != null) {
                    //初始化数组长度
                    songTotalPath = new String[files.length];
                    mimeTypes = new String[files.length];
                    for (int i = 0; i < songTotalPath.length; i++) {
                        //默认路径,这里初始化数组每一项,只是单纯的防止后面用第二种方式扫描文件带来的空指针异常,无实际意义
                        songTotalPath[i] = Environment.getExternalStorageDirectory().getAbsolutePath();
                        //只是单纯的防止后面用第二种方式扫描文件带来的空指针异常
                        mimeTypes[i] = null;
                    for (int i = 0; i < files.length; i++) {
                        if (files[i].isFile()) {
                            //如果 扫到的是文件,那么把具体路径存到songTotalPath下
                            songTotalPath[i] = Environment.getExternalStorageDirectory().getAbsolutePath() + "/opo/" + files[i].getName();
                            Log.e("file", files[i].getName());
     MediaScanner mediaScanner = new MediaScanner(App.getINSTANCE());
            String[] filePaths = songTotalPath;
            //MimeType文件也可以这个获取,如果不知道媒体文件对应的的值
    //        String[] mimeTypes = new String[]{MimeTypeMap.getSingleton().getMimeTypeFromExtension("mp3")};
    //        String[] mimeTypes = new String[]{null};
            mediaScanner.scanFiles(filePaths, mimeTypes);