【发布时间】:2022-07-04 17:14:18
【问题描述】:
TL;DR
我想通过FileProvider 获取(读取/生成)文件Uri -- 路径如下 -- 通过FileProvider,但不知道如何:
val file = File("/external/file/9359") // how do I get its Uri then?
我只知道FileProvider.getUriForFile 方法,但它会抛出异常。
我在做什么
我试图模拟下载进度——在Download 文件夹中创建一个文件,然后将其传递给ShareSheet 让用户做任何想做的事情。
我做了什么:
- 使用
MediaStore和ContentResolver在Download中创建文件。 - 有一个
ShareSheetutil 函数。 - 注册
FileProvider和filepath.xml。
就我而言,我想通过ShareSheet 函数共享文件,这需要
-
File的 Uri
但通常的 file.toUri() 会在 SDK 29 以上抛出异常。因此我按照 Google 官方的建议将其更改为 FileProvider.getUriForFile()。
直接问题代码
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")
我可以确保代码是正确的,因为我可以在 Download 文件夹中看到正确的文件。
我的 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
我最初想要实现的是sending binary data to other app。正如官方记录的那样,它似乎只接受文件Uri。
如果有任何其他方法可以实现这一点,我将不胜感激,例如直接分享 File 等。
但我现在想知道的很简单——我如何使FileProvider 可用于获取/读取/生成文件Uri 就像/external/file/9359 等等? 这可能会出现不仅在这种情况下有所帮助,而且对我来说似乎是更一般/基本的知识。
【问题讨论】:
标签: android uri mediastore android-fileprovider