Android中 MediaStore介绍

不得不说一下,android适配真的是一个大坑。

在使用文件管理器打开本地文件时,刚开始以为超级简单,就像下面:

// 打开文件管理器选择文件
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
//        intent.setType("image/*");//选择图片
//        intent.setType("audio/*"); //选择音频
//        intent.setType("video/*"); //选择视频 (mp4 3gp 是android支持的视频格式)
//        intent.setType("video/*;image/*");//同时选择视频和图片
        intent.setType("*/*");//无类型限制
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        startActivityForResult(intent, mTag);

在回调方法,获取选中文件的路径:

 @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == mTag) {
                Uri uri = data.getData();
                if (uri != null) {
                    try {
                        String[] filePathColumn = {MediaStore.Images.Media.DATA};
                        @SuppressLint("Recycle") Cursor cursor = this.getContentResolver().query(uri,
                                filePathColumn, null, null, null);//从系统表中查询指定Uri对应的照片
                        cursor.moveToFirst();
                        int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
                        String path = cursor.getString(columnIndex); //获取照片路径
                        if (path == null) {
                            /**
                             * 2022年6月14日12:11:56
                             * 加入这个是当选址最近使用的文件的时候,上面的会没有找到这个文件路径,所以加上这个
                             */
                            if (Build.VERSION.SDK_INT >= 19) {
                                path = handleImageOnKitKat(this, data);
                            } else {
                                path = handleImageBeforeKitKat(this, data);
                            }

                        }
                    } catch (Exception e){
                        
                    }
                }
        }

}

其中 handleImageOnKitKat 方法为:

 @TargetApi(Build.VERSION_CODES.KITKAT)
    public static String handleImageOnKitKat(Context context, Intent data) {
        Uri uri = data.getData();
        if (DocumentsContract.isDocumentUri(context, uri)) {
            String docId = DocumentsContract.getDocumentId(uri);
            if ("com.android.externalstorage.documents".equals(uri.getAuthority())) {
                final String[] split = docId.split(":");
                final String type = split[0];

                if ("primary".equalsIgnoreCase(type)) {
                    return Environment.getExternalStorageDirectory() + "/" + split[1];
                }
            } else if ("com.android.providers.media.documents".equals(uri.getAuthority())) {
                String id = docId.split(":")[1];
                String selection = MediaStore.Images.Media._ID + "=" + id;
                String type = docId.split(":")[0];
                Uri contentUri = null;
                if (type.equalsIgnoreCase("image")) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if (type.equalsIgnoreCase("video")) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if (type.equalsIgnoreCase("audio")) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }
                return getPath(context, contentUri, selection);
            } else if ("com.android.providers.media.downloads.documents".equals(uri.getAuthority())) {
                Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"),
                        Long.valueOf(docId));
                return getPath(context, contentUri, null);
            } else if ("content".equals(uri.getAuthority())) {
                return getPath(context, uri, null);
            } else if ("file".equals(uri.getAuthority())){
                return uri.getPath();
            }
        } else {
            return uri.getPath();
        }
        return "";
    }
handleImageBeforeKitKat 方法为:
public static String handleImageBeforeKitKat(Context context, Intent data) {
        Uri uri = data.getData();
        return getPath(context, uri, null);
    }

到此,就可以拿到本地文件的路径了。 

结果在不同手机上就出现了适配问题。有的手机在文件管理器的最近文件中可以看到 音频、视频、图片以外的文件,当我们去选择这些文件时,上面的代码就会报错。

debug调试了许久,发现了问题是所在:

DocumentsContract.getDocumentId(uri);

该行代码在大多数情况下返回的是:image、video、audio,但是在我们这里返回的却是 document。所在我们在解析时,就会找不到对应的,就会报错。

解决方法:

可能有些人已经注意到了,我们在判断类型时,用的都是同一个对象 MediaStore

MediaStore是android系统提供的一个多媒体数据库,专门用于存放多媒体信息的,通过ContentResolver即可对数据库进行操作。

  1. MediaStore.Files: 共享的文件,包括多媒体和非多媒体信息;
  2. MediaStore.Audio: 存放音频信息;
  3. MediaStore.Image: 存放图片信息;
  4. MediaStore.Vedio: 存放视频信息;

我们就可以去使用 MediaStore.Files 来获取刚刚返回 document 时的问题。具体代码:

Uri contentUri = null;
                if (type.equalsIgnoreCase("image")) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if (type.equalsIgnoreCase("video")) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if (type.equalsIgnoreCase("audio")) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                } else {
                    contentUri = MediaStore.Files.getContentUri("external");
                }

这样就可以正常的解析文件路径了。

猜你喜欢

转载自blog.csdn.net/minusn/article/details/126298497
今日推荐