如何从指向PDF文档的URI获取文件路径?

20

目前我的代码打开了默认的下载视图,并且只显示我下载的PDF文件。我选择一个PDF文件,然后得到了以下内容:

content://com.android.providers.downloads.documents/document/1171

我希望得到以下内容:

/storage/emulated/0/Download/ch22Databases.pdf

我的问题是如何在Android中实现这个功能?

我的代码:

public void PDF() {
    PDF = (Button) findViewById(R.id.FindPDFBtn);//Finds the button in design and put it into a button variable.
    PDF.setOnClickListener(//Listens for a button click.
        new View.OnClickListener() {//Creates a new click listener.
            @Override
            public void onClick(View v) {//does what ever code is in here when the button is clicked
                Intent intent = new Intent();
                intent.setType("application/pdf");
                intent.setAction(Intent.ACTION_GET_CONTENT);
                startActivityForResult(Intent.createChooser(intent, "Select a PDF "), SELECT_PDF);
            }
        }
    );
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    //PDF
    if (resultCode == RESULT_OK) {
        if (requestCode == SELECT_PDF) {
            Uri selectedUri_PDF = data.getData();
            SelectedPDF = getPDFPath(selectedUri_PDF);
        }
    }
}

public String getPDFPath(Uri uri) {
    String[] projection = { MediaStore.Images.Media.DATA };
    Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
    int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
    cursor.moveToFirst();
    return cursor.getString(column_index);
}

1
你绝对不能使用MediaStore.Images来查找PDF文件。如果Android将PDF索引为图像,我会感到震惊。通常情况下,当你获取内容URI时,由于安全原因,你无法访问路径。相反,你应该使用ContentResolver打开一个流来读取文件内容。由于安全原因,直接访问文件在Android上变得越来越困难。 - Doug Stevenson
你的问题解决了吗?如果你觉得我的帮助有价值,请标记问题为已解决 ;) - Gueorgui Obregon
是的,我知道它们进行了很多更改,现在很难获取路径,我可能不得不在我的应用程序中创建自己的文件管理器。@DougStevenson - Lazar Kukolj
在我的HTC 816 Desire手机上[注:该设备已升级到MarshMallow,但仍存在KitKat的崩溃。作为开发人员,我发现由意图打开的相机捕获的图像从未释放其资源。这使得当我尝试拍摄第二张照片时出现内部崩溃。],返回的路径以“/document/primary:”开头,并在'pdfUri.getPath()'中保留,导致文件未找到异常。此外,当我在'MediaStore.Images.Media.DATA'中搜索时,列索引返回为-1。 - Abhinav Saxena
8个回答

7
在您的getPDFPath方法中添加以下代码片段:
public String getPDFPath(Uri uri){

     final String id = DocumentsContract.getDocumentId(uri);
     final Uri contentUri = ContentUris.withAppendedId(
                    Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

     String[] projection = { MediaStore.Images.Media.DATA };
     Cursor cursor = getContentResolver().query(contentUri, projection, null, null, null);
     int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
     cursor.moveToFirst();
     return cursor.getString(column_index);
}

在您的情况下,这段代码是专门用于从DownloadProvider下载文档的,如需进一步实现,请查看Paul Burke的答案。我个人使用他的aFileChooser库来避免这种问题。

我尝试了 .getpath() 方法,但它没有起作用。我只得到了 /storage/emulated/0/Download/ch22Databases.pdf。 - Lazar Kukolj
2
如果我使用那个方法,我会得到 /document/1384 - Lazar Kukolj
所以,通过 data.getData().getPath(),你得到的是 /storage/emulated/0/Download/ch22Databases.pdf? - Gueorgui Obregon
1
我编辑了我的答案。如果您有任何其他问题,请告诉我。 - Gueorgui Obregon
好的,这样对我来说已经解决了下载的问题,谢谢你!但是如果它在一个不同的文件夹里怎么办?当我打开意图时,会有一个从左边滑入的菜单,在那里我可以看到其他目录?再次感谢你!! - Lazar Kukolj
显示剩余4条评论

6
我的问题是如何在Android上实现这个功能?
你不能使用ACTION_GET_CONTENT来处理文件。
如果你确实需要一个文件,请使用文件选择库,而不是ACTION_GET_CONTENT。
如果你想使用ACTION_GET_CONTENT,请停止尝试获取内容的文件系统路径。如果URI具有file、content或android.resource方案,请使用ContentResolver和openInputStream()读取内容。如果URI具有http或https方案,请使用HTTP客户端API。

2
以下是两种解决方案:
1) 您可以使用以下代码。它可以处理任何类型的文件并来自任何文件夹。
private String getPath(final Uri uri) {

    final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
    if(isKitKat) {
        // MediaStore (and general)
        return getForApi19(uri);
    } else if ("content".equalsIgnoreCase(uri.getScheme())) {

        // Return the remote address
        if (isGooglePhotosUri(uri))
            return uri.getLastPathSegment();

        return getDataColumn(uri, null, null);
    }
    // File
    else if ("file".equalsIgnoreCase(uri.getScheme())) {
        return uri.getPath();
    }

    return null;
}

@TargetApi(19)
private String getForApi19(Uri uri) {
    Log.e(tag, "+++ API 19 URI :: " + uri);
    if (DocumentsContract.isDocumentUri(this, uri)) {
        Log.e(tag, "+++ Document URI");
        // ExternalStorageProvider
        if (isExternalStorageDocument(uri)) {
            Log.e(tag, "+++ External Document URI");
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            final String type = split[0];

            if ("primary".equalsIgnoreCase(type)) {
                Log.e(tag, "+++ Primary External Document URI");
                return Environment.getExternalStorageDirectory() + "/" + split[1];
            }

            // TODO handle non-primary volumes
        }
        // DownloadsProvider
        else if (isDownloadsDocument(uri)) {
            Log.e(tag, "+++ Downloads External Document URI");
            final String id = DocumentsContract.getDocumentId(uri);
            final Uri contentUri = ContentUris.withAppendedId(
                    Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

            return getDataColumn(contentUri, null, null);
        }
        // MediaProvider
        else if (isMediaDocument(uri)) {
            Log.e(tag, "+++ Media Document URI");
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            final String type = split[0];

            Uri contentUri = null;
            if ("image".equals(type)) {
                Log.e(tag, "+++ Image Media Document URI");
                contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
            } else if ("video".equals(type)) {
                Log.e(tag, "+++ Video Media Document URI");
                contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
            } else if ("audio".equals(type)) {
                Log.e(tag, "+++ Audio Media Document URI");
                contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
            }

            final String selection = "_id=?";
            final String[] selectionArgs = new String[] {
                    split[1]
            };

            return getDataColumn(contentUri, selection, selectionArgs);
        }
    } else if ("content".equalsIgnoreCase(uri.getScheme())) {
        Log.e(tag, "+++ No DOCUMENT URI :: CONTENT ");

        // Return the remote address
        if (isGooglePhotosUri(uri))
            return uri.getLastPathSegment();

        return getDataColumn(uri, null, null);
    }
    // File
    else if ("file".equalsIgnoreCase(uri.getScheme())) {
        Log.e(tag, "+++ No DOCUMENT URI :: FILE ");
        return uri.getPath();
    }
    return null;
}

/**
 * Get the value of the data column for this Uri. This is useful for
 * MediaStore Uris, and other file-based ContentProviders.
 *
 * @param uri The Uri to query.
 * @param selection (Optional) Filter used in the query.
 * @param selectionArgs (Optional) Selection arguments used in the query.
 * @return The value of the _data column, which is typically a file path.
 */
public String getDataColumn(Uri uri, String selection,
                            String[] selectionArgs) {

    Cursor cursor = null;
    final String column = "_data";
    final String[] projection = {
            column
    };

    try {
        cursor = getContentResolver().query(uri, projection, selection, selectionArgs,
                null);
        if (cursor != null && cursor.moveToFirst()) {
            final int index = cursor.getColumnIndexOrThrow(column);
            return cursor.getString(index);
        }
    } finally {
        if (cursor != null)
            cursor.close();
    }
    return null;
}


/**
 * @param uri The Uri to check.
 * @return Whether the Uri authority is ExternalStorageProvider.
 */
public static boolean isExternalStorageDocument(Uri uri) {
    return "com.android.externalstorage.documents".equals(uri.getAuthority());
}

/**
 * @param uri The Uri to check.
 * @return Whether the Uri authority is DownloadsProvider.
 */
public static boolean isDownloadsDocument(Uri uri) {
    return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}

/**
 * @param uri The Uri to check.
 * @return Whether the Uri authority is MediaProvider.
 */
public static boolean isMediaDocument(Uri uri) {
    return "com.android.providers.media.documents".equals(uri.getAuthority());
}

/**
 * @param uri The Uri to check.
 * @return Whether the Uri authority is Google Photos.
 */
public static boolean isGooglePhotosUri(Uri uri) {
    return "com.google.android.apps.photos.content".equals(uri.getAuthority());
}

这是我找到的最佳浏览文件的解决方案。

希望能对您有所帮助。

另一种方法

2) 我找到的另一种解决方案是:

在模块“app”的build.gradle中添加依赖项。

compile 'in.gauriinfotech:commons:1.0.8'

那么在您的代码中使用:

String fullPath = Commons.getPath(uri, context);

请确保在Manifest.xml中添加以下权限:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

谢谢,我会看一下的!我标记为正确的代码只适用于下载,但我还没有尝试过这段代码! - Lazar Kukolj
2
两种解决方案都出现了异常:方法抛出了'java.lang.NumberFormatException'异常。 - Asadullah Mumtaz
两个解决方案都出现了相同的错误,'java.lang.IllegalArgumentException: Unknown URI: content://downloads/public_downloads/2250'。 - Annie
1
有人解决了这个问题吗?在一些手机上它可以工作,但在一些手机上会出现错误。 - Annie

2

虽然我来晚了,但希望这能帮到有需要的人。我在Android 10和11上遇到了同样的问题。下面逐步介绍如何获取PDF路径:

1)打开文件以选择PDF

fun openPdfSelector(){
        val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
            type = "application/pdf"
            addCategory(Intent.CATEGORY_OPENABLE)
        }
        startActivityForResult(intent, 101)
    }   

2)在activity的Override onActivityResult()方法中,使用以下代码:

 data?.data?.also { documentUri ->
                    contentResolver.takePersistableUriPermission(
                        documentUri,
                        Intent.FLAG_GRANT_READ_URI_PERMISSION
                    )
                    val filePathHelper = FilePathHelper()
                    var uriString: String = ""
                    if (filePathHelper.getPathnew(documentUri, this) != null) {
                        uriString = filePathHelper.getPathnew(documentUri, this).toLowerCase()
                    } else {
                        uriString =
                            filePathHelper.getFilePathFromURI(documentUri, this).toLowerCase()
                    }
                    //uriString-> this is original path 
}  

3) FilePathHelper是我们使用的类,用于解析URI以获取路径

public class FilePathHelper {

public FilePathHelper(){

}

public String getMimeType(String url) {
    String type = null;
    String extension = MimeTypeMap.getFileExtensionFromUrl(url.replace(" ", ""));
    if (extension != null) {
        type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
    }
    return type;
}

public String getFilePathFromURI(Uri contentUri, Context context) {
    //copy file and send new file path
    String fileName = getFileName(contentUri);
    if (!TextUtils.isEmpty(fileName)) {
        File copyFile = new File(context.getExternalCacheDir() + File.separator + fileName);
        copy(context, contentUri, copyFile);
        return copyFile.getAbsolutePath();
    }
    return null;
}

public void copy(Context context, Uri srcUri, File dstFile) {
    try {
        InputStream inputStream = context.getContentResolver().openInputStream(srcUri);
        if (inputStream == null) return;
        OutputStream outputStream = new FileOutputStream(dstFile);
        inputStream.close();
        outputStream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public String getPath(Uri uri, Context context) {
    String filePath = null;
    final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
    if (isKitKat) {
        filePath = generateFromKitkat(uri, context);
    }

    if (filePath != null) {
        return filePath;
    }

    Cursor cursor = context.getContentResolver().query(uri, new String[]{MediaStore.MediaColumns.DATA}, null, null, null);

    if (cursor != null) {
        if (cursor.moveToFirst()) {
            int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
            filePath = cursor.getString(columnIndex);
        }
        cursor.close();
    }
    return filePath == null ? uri.getPath() : filePath;
}

@TargetApi(19)
private String generateFromKitkat(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;
}

public String getFileName(Uri uri) {
    if (uri == null) return null;
    String fileName = null;
    String path = uri.getPath();
    int cut = path.lastIndexOf('/');
    if (cut != -1) {
        fileName = path.substring(cut + 1);
    }
    return fileName;
}

@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public String getPathnew(Uri uri, Context context) {
    final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

    // DocumentProvider
    if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
        // ExternalStorageProvider
        if (isExternalStorageDocument(uri)) {
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            final String type = split[0];

            if ("primary".equalsIgnoreCase(type)) {
                return Environment.getExternalStorageDirectory() + "/" + split[1];
            }
            // TODO handle non-primary volumes
        }
        // DownloadsProvider
        else if (isDownloadsDocument(uri)) {
            final String id = DocumentsContract.getDocumentId(uri);
            final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
            return getDataColumn(context, contentUri, null, null);
        }
        // MediaProvider
        else if (isMediaDocument(uri)) {
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            final String type = split[0];
            Uri contentUri = null;
            if ("image".equals(type)) {
                contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
            } else if ("video".equals(type)) {
                contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
            } else if ("audio".equals(type)) {
                contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
            }
            final String selection = "_id=?";
            final String[] selectionArgs = new String[]{split[1]};
            return getDataColumn(context, contentUri, selection, selectionArgs);
        }
    }
    // MediaStore (and general)
    else if ("content".equalsIgnoreCase(uri.getScheme())) {
        // Return the remote address
        if (isGooglePhotosUri(uri))
            return uri.getLastPathSegment();
        return getDataColumn(context, uri, null, null);
    }
    // File
    else if ("file".equalsIgnoreCase(uri.getScheme())) {
        return uri.getPath();
    }
    return null;
}

public String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
    Cursor cursor = null;
    final String column = "_data";
    final String[] projection = {column};
    try {
        cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
        if (cursor != null && cursor.moveToFirst()) {
            final int index = cursor.getColumnIndexOrThrow(column);
            return cursor.getString(index);
        }
    } catch (Exception e) {
        e.printStackTrace();
        System.out.println("Something with exception - " + e.toString());
    } finally {
        if (cursor != null)
            cursor.close();
    }
    return null;
}

public boolean isExternalStorageDocument(Uri uri) {
    return "com.android.externalstorage.documents".equals(uri.getAuthority());
}

/**
 * @param uri The Uri to check.
 * @return Whether the Uri authority is DownloadsProvider.
 */
public boolean isDownloadsDocument(Uri uri) {
    return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}

/**
 * @param uri The Uri to check.
 * @return Whether the Uri authority is MediaProvider.
 */
public boolean isMediaDocument(Uri uri) {
    return "com.android.providers.media.documents".equals(uri.getAuthority());
}

/**
 * @param uri The Uri to check.
 * @return Whether the Uri authority is Google Photos.
 */
public boolean isGooglePhotosUri(Uri uri) {
    return "com.google.android.apps.photos.content".equals(uri.getAuthority());
}}

注意:如果您使用的是Android 11,请为您的应用程序提供作用域存储权限
-> 您可以使用以下代码来请求权限

 btn_select_file.setOnClickListener {
        if (isScopedStoragePermissionNeeded()) {
            askForExternalStoragePermission()
        } else {
            openPdfSelector()
        }}  



private fun isScopedStoragePermissionNeeded(): Boolean {
        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && !Environment.isExternalStorageManager()
    }  

private fun askForExternalStoragePermission() {
        requestPermissions(
            arrayOf(Manifest.permission.MANAGE_EXTERNAL_STORAGE),
            102
        )
}  

-> 在onRequestPermissionResultI()方法中打开到权限界面的意图

 if (requestCode == 102) {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            val intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION)
            intent.data = Uri.parse("package:com.example.pdfselector")
            startActivityForResult(intent, 103)
        }
    }  

-> 在清单文件中添加 android:requestLegacyExternalStorage="true" 一行。


嗨,现在的managePermission是很危险的,你有没有办法通过mediastore获取PDF文件呢?我无法从设备中获取PDF列表。 - undefined

0

Uri uri = intent.getData();

                String uriString = uri.toString();

                File myFile = new File(uriString);

                final String path = myFile.getAbsolutePath();

                String displayName = null;

                if (uriString.startsWith("content://")) {
                    Cursor cursor = null;
                    try {
                        cursor = getActivity().getContentResolver().query(uri, null, null, null, null);
                        if (cursor != null && cursor.moveToFirst()) {
                            displayName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
                            tvFile.setVisibility ( View.VISIBLE );
                            tvFile.setText ( displayName );

                            final String finalDisplayName = displayName;
                            tvFile.setOnClickListener ( new View.OnClickListener () {
                                @Override
                                public void onClick(View v) {
                                    File dir = Environment.getExternalStorageDirectory();
                                    File yourFile = new File(dir, path+ finalDisplayName );

                                    Toast.makeText ( getActivity (),"hiiiii"+yourFile,Toast.LENGTH_SHORT ).show ();
                                }
                            } );
                            //Toast.makeText ( getActivity (),"hii"+displayName,Toast.LENGTH_LONG ).show ();
                        }
                    } finally {
                        cursor.close();
                    }
                } else if (uriString.startsWith("file://")) {
                    displayName = myFile.getName();
                   // Toast.makeText ( getActivity (),"hii"+displayName,Toast.LENGTH_LONG ).show ();
                }

0

我尝试了各种解决方案,但都没有起作用。我认为最好的方法是使用URI获取文件的输出流,然后将内容写入本地文件(已知路径)。

@Throws(IOException::class)
private fun copyPdfToLocalFile(uri: Uri) {
    val stringBuilder = StringBuilder()
    contentResolver.openInputStream(uri)?.use { inputStream ->
        BufferedReader(InputStreamReader(inputStream)).use { reader ->
            var line: String? = reader.readLine()
            while (line != null) {
                writeDocument(line)
                line = reader.readLine()
            }
        }
    }
}


private fun writeDocument(line: String) {
    val outputFileUri: Uri = /*Uri of the local file */
    try {
        contentResolver.openFileDescriptor(outputFileUri, "wa")?.use {
            FileOutputStream(it.fileDescriptor).use {
                it.write(line.toByteArray())
            }
        }
    } catch (e: FileNotFoundException) {
        e.printStackTrace()
    } catch (e: IOException) {
        e.printStackTrace()
    }
}

以上代码将共享文件复制到本地文件,您知道该文件的路径。稍后,一旦不需要复制的文件,您可以删除该文件。

由于文件是重复的,所以在存在内存限制的情况下无法使用,但对于一般用途来说,它可以正常工作。


0
请使用以下文件从URI获取路径。
public class FileUtils {
    private static Uri filePathUri = null;


    public static String getPath(final Context context, final Uri uri) {
        filePathUri=uri;
        final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
        final boolean isOreo=Build.VERSION.SDK_INT >= 26;
        // DocumentProvider
        if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
            // ExternalStorageProvider
            if (isExternalStorageDocument(uri)) {
                final String docId = getDocumentId(DocumentsContract.getDocumentId(uri));
                final String[] split = docId.split(":");
                final String type = split[0];

                if ("primary".equalsIgnoreCase(type)) {
                    return Environment.getExternalStorageDirectory() + "/" + split[1];
                }
                // TODO handle non-primary volumes
            }
            // DownloadsProvider
            else if (isDownloadsDocument(uri)) {

                final String id = getDocumentId(DocumentsContract.getDocumentId(uri));


                final Uri contentUri = ContentUris.withAppendedId(
                        Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));


                return getDataColumn(context, contentUri, null, null);
            }
            // MediaProvider
            else if (isMediaDocument(uri)) {
                final String docId = getDocumentId(DocumentsContract.getDocumentId(uri));
                final String[] split = docId.split(":");
                final String type = split[0];

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

                final String selection = "_id=?";
                final String[] selectionArgs = new String[]{
                        split[1]
                };

                return getDataColumn(context, contentUri, selection, selectionArgs);
            }
        }
        // MediaStore (and general)
        else if ("content".equalsIgnoreCase(uri.getScheme())) {
            return getDataColumn(context, uri, null, null);
        }
        // File
        else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }

        return null;
    }

    /**
     * Get the value of the data column for this Uri. This is useful for
     * MediaStore Uris, and other file-based.
     *
     * @param context       The context.
     * @param uri           The Uri to query.
     * @param selection     (Optional) Filter used in the query.
     * @param selectionArgs (Optional) Selection arguments used in the query.
     * @return The value of the _data column, which is typically a file path.
     */
    public static String getDataColumn(Context context, Uri uri, String selection,
                                       String[] selectionArgs) {

        Cursor cursor = null;**strong text**
        final String column = "_data";
        final String[] projection = {
                column
        };
        FileInputStream input = null;
        FileOutputStream output = null;

        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
            if (cursor != null && cursor.moveToFirst()) {
                final int index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(index);
            }
        } catch (IllegalArgumentException e){
            e.printStackTrace();

            File file = new File(context.getCacheDir(), "tmp");
            String filePath = file.getAbsolutePath();

            try {
                ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(filePathUri, "r");
                if (pfd == null)
                    return null;

                FileDescriptor fd = pfd.getFileDescriptor();
                input = new FileInputStream(fd);
                output = new FileOutputStream(filePath);
                int read;
                byte[] bytes = new byte[4096];
                while ((read = input.read(bytes)) != -1) {
                    output.write(bytes, 0, read);
                }

                input.close();
                output.close();
                return new File(filePath).getAbsolutePath();
            } catch (IOException ignored) {
                ignored.printStackTrace();
            }
        } finally{
            if (cursor != null)
                cursor.close();
        }
        return null;
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is ExternalStorageProvider.
     */
    public static boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is DownloadsProvider.
     */
    public static boolean isDownloadsDocument(Uri uri) {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is MediaProvider.
     */
    public static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }


    private static String getDocumentId(String id) {
        if (!TextUtils.isEmpty(id)) {
            if (id.startsWith("raw:")) {
                return id.replaceFirst("raw:", "");
            }

        }
        return id;
    }
}

1
请使用以下链接获取完整的解释和代码 https://gist.github.com/HBiSoft/15899990b8cd0723c3a894c1636550a8 - Chandela

-1

这两行代码对我有用

File dir = Environment.getExternalStorageDirectory();
File yourFile = new File(dir, path+ finalDisplayName );

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