什么是最简单的方法从android.net.Uri对象持有一个文件:类型转换为java.io.File对象在Android?

我尝试了下面的方法,但不管用:

File file = new File(Environment.getExternalStorageDirectory(), "read.me");
Uri uri = Uri.fromFile(file);
File auxFile = new File(uri.toString());
assertEquals(file.getAbsolutePath(), auxFile.getAbsolutePath());

当前回答

@CommonsWare解释得很好。我们真的应该采用他提出的解决方案。

顺便说一下,当查询ContentResolver时,我们唯一可以依赖的信息是文件的名称和大小,如下所述: 检索文件信息| Android开发人员

正如您所看到的,这里有一个接口OpenableColumns,它只包含两个字段:DISPLAY_NAME和SIZE。

在我的例子中,我需要检索关于JPEG图像的EXIF信息,并在发送到服务器之前根据需要旋转它。为此,我使用ContentResolver和openInputStream()将文件内容复制到临时文件中。

其他回答

经过大量的搜索和尝试不同的方法,我发现这个方法适用于不同的Android版本: 首先复制这个函数:

    fun getRealPathFromUri(context: Context, contentUri: Uri): String {
        var cursor: Cursor? = null
        try {
            val proj: Array<String> = arrayOf(MediaStore.Images.Media.DATA)
            cursor = context.contentResolver.query(contentUri, proj, null, null, null)
            val columnIndex = cursor?.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
            cursor?.moveToFirst()
            return columnIndex?.let { cursor?.getString(it) } ?: ""
        } finally {
            cursor?.close()
        }
    }

然后,生成一个像这样的文件:

File(getRealPathFromUri(context, uri))

使用

InputStream inputStream = getContentResolver().openInputStream(uri);    

直接复制文件。还看到:

https://developer.android.com/guide/topics/providers/document-provider.html

这些对我都没用。我发现这是可行的解决方案。但我的情况仅限于图像。

String[] filePathColumn = { MediaStore.Images.Media.DATA };
Cursor cursor = getActivity().getContentResolver().query(uri, filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String filePath = cursor.getString(columnIndex);
cursor.close();

uri.toString()给我:"content://com.google.android.apps.nbu.files.provider/1/file%3A%2F%2F%2Fstorage%2Femulated%2F0%2FDownload%2Fbackup.file"

uri.getPath()给我:“/1/文件:///存储/模拟/0/下载/备份文件。”

new File(uri.getPath())给我“/1/ File:/storage/ emululated /0/Download/backup.file”。

所以如果你有一个文件的访问权限,想要避免使用ContentResolver或直接读取文件,答案是:

private String uriToPath( Uri uri )
{
    File backupFile = new File( uri.getPath() );
    String absolutePath = backupFile.getAbsolutePath();
    return absolutePath.substring( absolutePath.indexOf( ':' ) + 1 );
}

为简化回答,跳过错误处理

另一种方法是创建一个临时文件。做那件事:

fun createTmpFileFromUri(context: Context, uri: Uri, fileName: String): File? {
    return try {
        val stream = context.contentResolver.openInputStream(uri)
        val file = File.createTempFile(fileName, "", context.cacheDir)
        org.apache.commons.io.FileUtils.copyInputStreamToFile(stream,file)
        file
    } catch (e: Exception) {
        e.printStackTrace()
        null
    }
}

我们使用Apache公共库FileUtils类。将它添加到您的项目:

implementation "commons-io:commons-io:2.7"

注意,MAKE SURE在使用后调用file.delete()。 查阅更多资料。