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

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

推荐阅读更多精彩内容

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