zhihu / Matisse

:fireworks: A well-designed local image and video selector for Android
Apache License 2.0
12.52k stars 2.06k forks source link

Demo中根据Uri去获取拍照的图片路径报错 #116

Open vivian688 opened 7 years ago

vivian688 commented 7 years ago

从图库选择的没问题,但是拍照返回的Uri再调用PhotoMetadataUtils.getPath()获取路径报错。cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA)总返回-1。

jklwan commented 7 years ago

自己拍照的图片需要通知系统进行对该图片进行信息收集,否则数据库是没有数据的。 例如sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(file));); 当然还有其他方式

vivian688 commented 7 years ago

建议添加获取绝对路径的方法。

fuyoutianxia commented 7 years ago

拍照返回的uri,我根本显示不了啊,怎么解决的

jaysonShao commented 7 years ago

花了,半天时间找到的 http://www.jianshu.com/p/f9a63fcc0b91

fuyoutianxia commented 7 years ago

我选择图片返回的uri是正常的: content://media/external/images/media/190403 但是拍照之后返回的uri是这种格式的: content://com.example.yangqi.zhihuphoto.fileprovider/my_images/PicturesJPEG_20170712091444.jpg 以.jpg结尾的

jaysonShao commented 7 years ago

/storage/emulated/0/DCIM/Camera/IMG_20170625_154426R.jpg 这种格式才是可以给 file的。 content://media/external/images/media/198609 这种事 file 无法获取的格式。

jaysonShao commented 7 years ago

@Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); Log.v("resultCode", resultCode+""); Log.v("requestCode", requestCode+""); if (resultCode == -1 && requestCode == REQUEST_CODE_CHOOSE){ List s = new ArrayList(); s = Matisse.obtainResult(data); for (int i = 0; i < s.size(); i++) { Log.v("data", s.get(i)+""); String ss =handleImageOnKitKat(s.get(i)); mSelected.add(ss); Log.v("after", ss); } img1.setImageURI(Uri.parse(mSelected.get(0))); } }

private String handleImageOnKitKat(Uri uri) {
    String imagePath = null;

// Uri uri = data.getData();

    if (DocumentsContract.isDocumentUri(getContext(), uri)) {
        String docId = DocumentsContract.getDocumentId(uri);
        if ("com.android.providers.media.documents".equals(uri.getAuthority())) {
            //Log.d(TAG, uri.toString());
            String id = docId.split(":")[1];
            String selection = MediaStore.Images.Media._ID + "=" + id;
            imagePath = getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection);
        } else if ("com.android.providers.downloads.documents".equals(uri.getAuthority())) {
            //Log.d(TAG, uri.toString());
            Uri contentUri = ContentUris.withAppendedId(
                    Uri.parse("content://downloads/public_downloads"),
                    Long.valueOf(docId));
            imagePath = getImagePath(contentUri, null);
        }
    } else if ("content".equalsIgnoreCase(uri.getScheme())) {
        //Log.d(TAG, "content: " + uri.toString());
        imagePath = getImagePath(uri, null);
    }
    return imagePath;
}

private String getImagePath(Uri uri, String selection) {
    String path = null;
    Cursor cursor = getContext().getContentResolver().query(uri, null, selection, null, null);
    if (cursor != null) {
        if (cursor.moveToFirst()) {
            path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
        }

        cursor.close();
    }
    return path;
}
jaysonShao commented 7 years ago

大家 复制 粘贴 就可以

fuyoutianxia commented 7 years ago

感谢你回答的这么详细,我选择的图片能够转成路径: /storage/emulated/0/DCIM/Camera/20170629_135631.jpg 但是拍照之后获取的uri是 content://com.example.yangqi.zhihuphoto.fileprovider/my_images/PicturesJPEG_20170712155600.jpg 按照你的方法 也无法转换成路径,还有拍照的照片是存在根目录的,如何改变存储路径呢

Orangewei commented 7 years ago

Matisse.from(MainActivity.this) .choose(MimeType.allOf()) // 选择 mime 的类型 .countable(true) .maxSelectable(1) // 图片选择的最多数量 .spanCount(3)//展示图片列数 .capture(true) .captureStrategy(new CaptureStrategy(true,"")) 求教,请问CaptureStrategy这里面怎么设置,我选择图片没问题,但是一点击相机就崩溃

alex2390 commented 7 years ago

拍照之后返回的uri是这种格式的: content://com.example.yangqi.zhihuphoto.fileprovider/my_images/PicturesJPEG_20170712091444.jpg 以.jpg结尾上面方法 按照上面的方法还是ursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA)总返回-1。

qdxxxx commented 7 years ago
private static String uri2path(Uri uri) {
        String sdCardPath = Environment.getExternalStorageDirectory().getPath();
        String coverStr = sdCardPath.substring(sdCardPath.lastIndexOf(File.separator) + 1);
        List<String> uriPaths = uri.getPathSegments();

        for (int i = 0; i < uriPaths.size(); i++) {
            if (uriPaths.get(i).equals(coverStr)) {
                for (int j = i + 1; j < uriPaths.size(); j++) {
                    sdCardPath += File.separator + uriPaths.get(j);
                }
                break;
            }
        }
        return sdCardPath;
    }

    public static String getRealFilePath(final Uri uri) {
        if (null == uri) return null;
        final String scheme = uri.getScheme();
        String data = null;
        if (scheme == null)
            data = uri.getPath();
        else if (ContentResolver.SCHEME_FILE.equals(scheme)) {
            data = uri.getPath();
        } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
            Cursor cursor = App.getAppContext().getContentResolver().query(uri, new String[]{MediaStore.Images.ImageColumns.DATA}, null, null, null);
            if (null != cursor) {
                if (cursor.moveToFirst()) {
                    int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
                    if (index > -1) {
                        data = cursor.getString(index);
                    }
                }
                cursor.close();
            }
        }
        if (data == null) {
            data = uri2path(uri);
        }
        return data;
    }

通过getRealFilePath()方法去获取uri ,然后cursor数据获取空的时候另外拼接处理,此方法是我自己暴力写的,暂时还没发现其他手机有bug。如果出现问题可以艾特我。

忘了说一点,CaptureStrategy 要设置为true. 开放的。

vihuela commented 7 years ago

@qdxxxx 相册照片可获取,但是照相机的无法获取,小米3

vihuela commented 7 years ago

可以这样了,拍照的uri有回调,fileProvider的主机名,可以这样判断,拍照 相册都没有问题 https://gist.github.com/vihuela/ee973db7b43e085a1c197a4621847b65

xuwiller commented 6 years ago

针对这个问题,特意的去翻了下源码,发现拍照生成的图片文件是固定的,所以我们可以根据uri 自己拼凑出路径 直接上代码。当你通过其他方法拿不到路径时 可以这样 if (TextUtils.isEmpty(realFilePath)) { if(uri != null) { String uriString = uri.toString(); int index = uriString.lastIndexOf("/"); String imageName = uriString.substring(index); File storageDir;

                storageDir = Environment.getExternalStoragePublicDirectory(
                            Environment.DIRECTORY_PICTURES);
                File file = new File(storageDir, imageName);
                if(file.exists()) {
                    realFilePath = file.getAbsolutePath();
                } else {
                    storageDir = mContext.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
                    File file1 = new File(storageDir, imageName);
                    realFilePath = file1.getAbsolutePath();
                }
                //
            }
        }
icefree commented 6 years ago
   /**
    *  根据Uri获取文件真实地址
    */
    public static String getRealFilePath(Context context, Uri uri) {
        if (null == uri) return null;
        final String scheme = uri.getScheme();
        String realPath = null;
        if (scheme == null)
            realPath = uri.getPath();
        else if (ContentResolver.SCHEME_FILE.equals(scheme)) {
            realPath = uri.getPath();
        } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
            Cursor cursor = context.getContentResolver().query(uri,
                    new String[]{MediaStore.Images.ImageColumns.DATA},
                    null, null, null);
            if (null != cursor) {
                if (cursor.moveToFirst()) {
                    int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
                    if (index > -1) {
                        realPath = cursor.getString(index);
                    }
                }
                cursor.close();
            }
        }
        if (TextUtils.isEmpty(realPath)) {
            if (uri != null) {
                String uriString = uri.toString();
                int index = uriString.lastIndexOf("/");
                String imageName = uriString.substring(index);
                File storageDir;

                storageDir = Environment.getExternalStoragePublicDirectory(
                        Environment.DIRECTORY_PICTURES);
                File file = new File(storageDir, imageName);
                if (file.exists()) {
                    realPath = file.getAbsolutePath();
                } else {
                    storageDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
                    File file1 = new File(storageDir, imageName);
                    realPath = file1.getAbsolutePath();
                }
            }
        }
        return realPath;
    }

整合楼上各代码,matisse:0.4.3, Android5.1 测试可用,只测试了图片

kai123wen commented 5 years ago

请问楼主这个问题解决了吗?

vihuela commented 5 years ago

用次库的beta版即可。有对应api了

Ricky.yao手持设备

在 2019年3月30日,下午3:52,Guo Zhenhao notifications@github.com<mailto:notifications@github.com> 写道:

请问楼主这个问题解决了吗?

— You are receiving this because you commented. Reply to this email directly, view it on GitHubhttps://github.com/zhihu/Matisse/issues/116#issuecomment-478217862, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AGOvxOcj3LemgISZodVo3vDLb7KkQFvRks5vbxfEgaJpZM4OPbBC.