Media Data之多媒体扫描过程分析(三)

此分析代码基于Android 6.0源码,转载请注明来源地址http://blog.csdn.net/lemon_blue/article/details/52262085

Media Data之多媒体扫描过程分析(一)
Media Data之多媒体扫描过程分析(二)

3. 如何使用多媒体扫描

介绍完多媒体的分析过程之后,接下来介绍一下我们怎么用多媒体扫描。

3.1发送广播

发送广播的方式比较简单,设置Intent并且传入要扫描的Uri即可。缺点是无法获取实时获取扫描状态,不利于更新操作,而且只能扫描单一文件。下面的例子是在下载应用中,对扫描的处理。

if (shouldScan) {
    final Intent intent = new Intent(
            Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
    intent.setData(Uri.fromFile(file));
    getContext().sendBroadcast(intent);
}

另外,对于其他项目使用此方法扫描,如下图:
这里写图片描述

3.2实现接口

实现接口的方法适合扫描实时返回结果的情况,例如下载文件时需要及时扫描下载成功的文件,并且更新UI;或者是蓝牙传输文件时,同样需要及时去扫描。下面的例子是在蓝牙功能中,对扫描的处理。其中MediaScannerNotifier是内部类,实现了
MediaScannerConnectionClient接口。

private static class MediaScannerNotifier implements MediaScannerConnectionClient {

    private MediaScannerConnection mConnection;
    private BluetoothOppShareInfo mInfo;
    private Context mContext;
    private Handler mCallback;
    public MediaScannerNotifier(Context context, BluetoothOppShareInfo info, Handler handler) {
        mContext = context;
        mInfo = info;
        mCallback = handler;
        mConnection = new MediaScannerConnection(mContext, this);
        if (V) Log.v(TAG, "Connecting to MediaScannerConnection ");
        mConnection.connect();
    }
    public void onMediaScannerConnected() {
        if (V) Log.v(TAG, "MediaScannerConnection onMediaScannerConnected");
        mConnection.scanFile(mInfo.mFilename, mInfo.mMimetype);
    }
    public void onScanCompleted(String path, Uri uri) {
        try {
            if (uri != null) {
                Message msg = Message.obtain();
                msg.setTarget(mCallback);
                msg.what = MEDIA_SCANNED;
                msg.arg1 = mInfo.mId;
                msg.obj = uri;
                msg.sendToTarget();
            } else {
                Message msg = Message.obtain();
                msg.setTarget(mCallback);
                msg.what = MEDIA_SCANNED_FAILED;
                msg.arg1 = mInfo.mId;
                msg.sendToTarget();
            }
        } catch (Exception ex) {
            Log.v(TAG, "!!!MediaScannerConnection exception: " + ex);
        } finally {
            if (V) Log.v(TAG, "MediaScannerConnection disconnect");
            mConnection.disconnect();
        }
    }
}

另外,对于其他项目使用此方法扫描,如下图:
这里写图片描述

3.3使用静态方法

使用静态方法比较简单,不用调用connect方法,不用连接情况,可以传入路径数组,如果实现监听器会收到扫描结果。传入的参数分别为:上下文,路径数组,文件类型和监听器。

MediaScannerConnection.scanFile(this,
          new String[] { path }, null,
          new MediaScannerConnection.OnScanCompletedListener() {
      //实现回调方法
      public void onScanCompleted(String path, Uri uri) {
          //回调方法中的参数即扫描结果
      }
 });

另外,对于其他项目使用此方法扫描,如下图:
这里写图片描述

4. 常见问题

4.1发送广播扫描无效

需要注意的是在MediaScannerReceiver.java中,对传入的路径有个判断,如下代码所示。可以看出对路径的判断是判断是否以/storage/emulated/0开头,如果不是不会去调用扫描操作的,所以在传入文件路径时要注意路径的问题。

if (Intent.ACTION_MEDIA_SCANNER_SCAN_FILE.equals(action) &&
        path != null && path.startsWith(externalStoragePath + "/")) {
    scanFile(context, path);
}

4.2 发送广播扫描文件夹

Uri data 必须是文件的Uri ,如果是文件夹的则不会起作用的,需要注意。如果有扫描文件夹的需求,需要先遍历文件夹所有文件然后循环发送广播,如果是子文件夹则继续循环迭代,下面的代码是示例。

    public void fileScan(String file){
         Uri data = Uri.parse("file://"+file);
         sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, data));
     }
    public void folderScan(String path){
         File file = new File(path);
         if(file.isDirectory()){
            File[] array = file.listFiles();
            for(int i=0;i<array.length;i++){
                 File f = array[i];
                 if(f.isFile()){//FILE TYPE
                     String name = f.getName();
                     if(name.contains(".mp3")){
                         fileScan(f.getAbsolutePath());
                     }
                 }
                else {//FOLDER TYPE
                     folderScan(f.getAbsolutePath());
                 }
             }
         }
     }

4.3是否阻塞当前线程

无论哪种扫描方式,其具体的扫描过程都是在MediaScannerService中进行的,MediaScannerService已经新建了工作线程处理,所以在调用扫描过程时,不必担心其阻塞当前线程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值