API19以上关于发送广播刷新SD卡的替代方案MediaScannerConnection

Android4.4以上只能由系统应用发送广播通知系统扫描SD卡进而更新contentprovider的数据库,这个数据库在

API19以上关于发送广播刷新SD卡的替代方案MediaScannerConnection_第1张图片
具体路径

可以导出来研究一下结构

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,具体是

  1. 先创建MediaScanner类实现MediaScannerConnection.MediaScannerConnectionClient的俩个方法
    @Override
    public void onMediaScannerConnected() {
    }
    @Override
    public void onScanCompleted(String path, Uri uri) {
    }
  1. 在MediaScanner类中创建MediaScannerConnection的对象
    并在构造函数中初始化
  2. 在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);


MimeTypes说明
MimeTypes大全集
MediaScannerConnection


end

你可能感兴趣的:(API19以上关于发送广播刷新SD卡的替代方案MediaScannerConnection)