简述
我想通过FileProvider
获取(读取/生成)以下路径的文件Uri
,但不知道如何操作:
val file = File("/external/file/9359") // how do I get its Uri then?
我知道的只有 FileProvider.getUriForFile
方法,但它会抛出异常。
我的操作
我试图模拟下载进度 -- 在 Download
文件夹中创建一个文件,然后传递给 ShareSheet
让用户做任何想做的事情。
我已经完成的工作:
- 使用
MediaStore
和ContentResolver
在Download
中创建文件。 - 有一个
ShareSheet
实用函数。 - 注册了
FileProvider
和filepath.xml
。
在我的情况下,我想通过 ShareSheet
函数共享该文件,需要:
File
的 Uri
但是通常的 file.toUri()
在 SDK 29 以上会抛出上面提到的异常。因此,我将其改为 FileProvider.getUriForFile()
,这是 Google 官方推荐的方法。
直接导致问题的代码
val fileUri: Uri = FileProvider.getUriForFile(context, "my.provider", file)
会抛出异常:
java.lang.IllegalArgumentException: Failed to find configured root that contains /external/file/9359
我的文件创建代码
val fileUri: Uri? = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, "test.txt")
put(MediaStore.MediaColumns.MIME_TYPE, "text/plain")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
// create file in download directory.
put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS)
}
}.let { values ->
context.contentResolver.insert(MediaStore.Files.getContentUri("external"), values)
}
if (fileUri == null) return
context.contentResolver.openOutputStream(fileUri)?.use { fileOut ->
fileOut.write("Hello, World!".toByteArray())
}
val file = File(fileUri.path!!) // File("/external/file/9359")
我可以保证代码是正确的,因为我可以在下载
文件夹中看到正确的文件。
我的FileProvider设置
我已在AndroidManifest.xml中注册提供程序:
<application>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="my.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepath" />
</provider>
</application>
以下是filepath.xml文件的内容:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="external"
path="." />
</paths>
我也尝试了很多路径变量,一个接一个地:
<external-files-path name="download" path="Download/" />
<external-files-path name="download" path="." />
<external-path name="download" path="Download/" />
<external-path name="download" path="." />
<external-path name="external" path="." />
<external-files-path name="external_files" path="." />
我甚至还注册了外部存储读取权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
我哪部分做错了?
编辑1
发布后,我认为 File
的初始化可能是问题所在:
File(fileUri.path!!)
所以我把它改成了
File(fileUri.toString())
但仍然无法正常工作。
它们的内容差异如下:
fileUri.path -> /external/file/9359
(file.path) -> /external/file/9359
error -> /external/file/9359
fileUri.toString() -> content://media/external/file/9359
(file.path) -> content:/media/external/file/9359
error -> /content:/media/external/file/9359
编辑2
我最初想要实现的是向其他应用程序发送二进制数据。根据官方文档,似乎只接受文件Uri
。
如果有其他方法可以实现此目的,例如直接共享文件File
等,我会非常感激。
但我现在想知道的很简单——如何使FileProvider
可用以获取/读取/生成文件Uri
,例如/external/file/9359
等?这不仅可以帮助解决当前问题,对我来说似乎是更一般/基本的知识点。
val tempFile: File = createFileFromContentUri(contentUri)
-val filePath = tempFile.path
和val fileUri = tempFile.getUri()
。因此,您无需编辑内容uri。向内容uri添加方案可能不起作用。 - alpertign