如何从FileProvider URI获取真实路径?

6

我有一段用于解码content:// URI的代码:

Cursor cursor = null;
try {
    cursor = context.getContentResolver().query(contentUri,
                     new String[] { MediaStore.Files.FileColumns.DATA },
                     null, null, null);

    int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATA);
    cursor.moveToFirst();

    return cursor.getString(columnIndex);

} finally {
    if (cursor != null) {cursor.close()};
}

但是它不能用于FileProvider URI(例如Chrome Dev下载文件的URI:content://com.chrome.dev.FileProvider/downloads/)。有没有办法获取真实路径?


你需要真实路径做什么? - pskink
具备复制到新路径或删除文件的能力。 - proninyaroslav
请参见 ContentResolver#openInputStreamContentResolver#delete - pskink
是的,这是可能的,谢谢。 - proninyaroslav
不要 @shweta,这并没有帮助。 - pskink
显示剩余12条评论
4个回答

3
您可以尝试以下解决方案以获取文件提供程序URI的实际路径。
首先,您需要按照以下方式定义文件提供程序路径文件。

provider_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="/storage/emulated/0" path="."/>
</paths>

AndroidMenifest.xml 中声明文件提供程序如下所示。

AndroidMenifest.xml

<application>
    .
    .
    .
    <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="${applicationId}"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths"/>
    </provider>
 </application>

现在在活动页面上。

MyActivity.java

private Uri picUri;

    private void takePhotoFromCamera() {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        if (Utils.isNougat()) {
            picUri = FileProvider.getUriForFile(this, getPackageName(), imageHelper
                    .createImageFile());
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        }else {
            picUri = Uri.fromFile(imageHelper.createImageFile());
        }
        intent.putExtra(MediaStore.EXTRA_OUTPUT, picUri);
        startActivityForResult(intent, Const.ServiceCode.TAKE_PHOTO);
    }


    /**
     * This method is used for handel result after captured image from camera .
    */
    private void onCaptureImageResult() {
        if(Utils.isNougat()){
            documentImage = imageHelper.getRealPathFromURI(picUri.getPath());
        }else {
            documentImage = imageHelper.getRealPathFromURI(picUri);
        }
    }

遵循我的方法获取真实路径。
public String getRealPathFromURI(Uri contentURI) {
        String result;
        Cursor cursor = context.getContentResolver().query(contentURI, null,
                null, null, null);

        if (cursor == null) { // Source is Dropbox or other similar local file
            // path
            result = contentURI.getPath();
        } else {
            cursor.moveToFirst();
            try {
                int idx = cursor
                        .getColumnIndex(MediaStore.Images.ImageColumns.DATA);
                result = cursor.getString(idx);
            } catch (Exception e) {
                AppLog.handleException(ImageHelper.class.getName(), e);
                Toast.makeText(context, context.getResources().getString(
                        R.string.error_get_image), Toast.LENGTH_SHORT).show();

                result = "";
            }
            cursor.close();
        }
        return result;
    }

希望您解决问题。

4
你的重载方法 public String getRealPathFromURI(String contentUriPath) 在哪里? - Kirill Karmazin
1
这样做,我得到了idx = -1。在调试器中,URI字符串看起来很好,提供程序虚拟目录和所有内容都放在原处。 - Vito Valov
我遇到了以下错误:CursorIndexOutOfBoundsException: Requested column: -1, # of columns: 2。在这一行代码 result = cursor.getString(idx); - Raj Narayanan

0

试试这个:

@TargetApi(19)
 private static String generatePath(Uri uri,Context context){
    String filePath = null;
    if(DocumentsContract.isDocumentUri(context, uri)){
        String wholeID = DocumentsContract.getDocumentId(uri);

        String id = wholeID.split(":")[1];

        String[] column = { MediaStore.Video.Media.DATA };
        String sel = MediaStore.Video.Media._ID + "=?";

        Cursor cursor = context.getContentResolver().
                query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
                        column, sel, new String[]{ id }, null);



        int columnIndex = cursor.getColumnIndex(column[0]);

        if (cursor.moveToFirst()) {
            filePath = cursor.getString(columnIndex);
        }

        cursor.close();
    }
    return filePath;
}

0

我正在使用这个来获取所选文件的完整路径。也许它会对您有所帮助。

    final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
    intent.setType("application/zip");
    intent.addCategory(Intent.CATEGORY_OPENABLE);

    if (intent.resolveActivity(getPackageManager()) != null) {
        // file browser has been found on the device
        startActivityForResult(Intent.createChooser(intent, "Select File Browser"), SELECT_FILE_REQUEST_CODE);





@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            if (requestCode == SELECT_FILE_REQUEST_CODE) {

                final Uri uri = data.getData();

                if (uri.getScheme().equals("file")) {
                    // the direct path to the file has been returned
                    final String path = uri.getPath();
                    final File file = new File(path);
                    mFilePath = path;

                    updateFileInfo(file.getName(), file.length(), mFileType);
                } else if (uri.getScheme().equals("content")) {
                    // an Uri has been returned
                    mFileStreamUri = uri;

                    final Bundle extras = data.getExtras();
                    if (extras != null && extras.containsKey(Intent.EXTRA_STREAM))
                        mFileStreamUri = extras.getParcelable(Intent.EXTRA_STREAM);

                    // file name and size must be obtained from Content Provider
                    final Bundle bundle = new Bundle();
                    bundle.putParcelable(EXTRA_URI, uri);
                    getLoaderManager().restartLoader(SELECT_FILE_REQ, bundle, this);
                }
            }
        }
    }

 @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        final Uri uri = args.getParcelable(EXTRA_URI);

        return new CursorLoader(this, uri, null, null, null, null);
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        if (data != null && data.moveToNext()) {
            /*
             * Here we have to check the column indexes by name as we have requested for all. The order may be different.
             */
            final String fileName = data.getString(data.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME)/* 0 DISPLAY_NAME */);
            final int fileSize = data.getInt(data.getColumnIndex(MediaStore.MediaColumns.SIZE) /* 1 SIZE */);
            String filePath = null;
            final int dataIndex = data.getColumnIndex(MediaStore.MediaColumns.DATA);
            if (dataIndex != -1)
                filePath = data.getString(dataIndex /* 2 DATA */);
            if (!TextUtils.isEmpty(filePath))
                mFilePath = filePath;

            updateFileInfo(fileName, fileSize, mFileType);

0
你可以尝试这个。从URI获取真实路径。
File file = new File(getRealPathFromURI(selectedImageURI));

方法

private String getRealPathFromURI(Uri contentURI) {
    String result;
    Cursor cursor = getContentResolver().query(contentURI, null, null, null, null);
    if (cursor == null) { //checking
        result = contentURI.getPath();
    } else { 
        cursor.moveToFirst(); 
        int idx = cursor.getColumnIndex(MediaStore.Files.FileColumns.DATA); 
        result = cursor.getString(idx);
        cursor.close();
    }
    return result;
}

我遇到了以下错误:CursorIndexOutOfBoundsException: Requested column: -1, # of columns: 2。在这行代码 result = cursor.getString(idx); - Raj Narayanan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接