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

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

具体路径

可以导出来研究一下结构

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 137,092评论 19 139
  • ¥开启¥ 【iAPP实现进入界面执行逐一显】 〖2017-08-25 15:22:14〗 《//首先开一个线程,因...
    小菜c阅读 7,513评论 0 17
  • 2017年5月17日 Kylin_Wu 标注(★☆)为考纲明确给出考点(必考) 常见手机系统(★☆) And...
    Azur_wxj阅读 2,008评论 0 10
  • 2017.02.11 姓名:唐利葵 公司:广东维锐科技股份有限公司 组别:第161期谦虚二组,211期利他一组 【...
    向日葵之乌托邦阅读 308评论 0 0
  • 我今年22岁。 这意味着我的父母在我身上花费了至少23年的时光。 有什说我太小孩太幼稚,但是我是独生女,我的父母只...
    帅莫愁阅读 241评论 0 0

友情链接更多精彩内容