来自 Room 的小部件中的 setImageViewUri

Posted

技术标签:

【中文标题】来自 Room 的小部件中的 setImageViewUri【英文标题】:setImageViewUri in widget from Room 【发布时间】:2021-12-28 00:01:34 【问题描述】:

我有一个允许用户拍照的应用程序。然后我将图像存储在本地文件中并将 URI 保存到 Room。然后,我有一个与具有图像视图的应用程序关联的小部件。我使用 Dagger-Hilt 将我的数据库注入到小部件中,并成功将该 URI 传递给我的 updateAppWidget 方法

有问题的 URI:

file:///storage/emulated/0/android/media/com.sudharsanravikumar.myapplication/AlbumExpo/2021-11-08-07-37-55-596.jpg

问题是应用程序崩溃并出现以下错误:

java.lang.IllegalArgumentException: Failed to find configured root that contains /file:/storage/emulated/0/Android/media/com.sudharsanravikumar.myapplication/AlbumExpo/2021-11-08-07-37-55-596.jpg

我在类似的 SO 问题上尝试了很多东西,但感觉好像我错过了一些重要信息。我想我只是不清楚如何在清单上使用文件提供程序标签来正确地将应用程序指向应用程序存储我的图像的目录。我不确定在代码方面要显示什么,所以如果您需要任何内容​​,请在 cmets 中询问。

原来我的错误是:

    android.os.FileUriExposedException: file:///storage/emulated/0/Android/media/com.sudharsanravikumar.myapplication/AlbumExpo/2021-11-08-07-37-55-596.jpg exposed beyond app through RemoteViews.setUri()

我直接调用时生成的

 views.setImageViewUri(R.id.img_1, Uri.parse(uri.uri))

使用上面的原始 uri。为了尝试解决这个问题,我遵循了这个接受的答案 So question

这导致我这样做:

val photoURI = FileProvider.getUriForFile(
    context,
    "com.sudharsanravikumar.myapplication.provider",
    File(uri.uri)
)
 views.setImageViewUri(R.id.img_1, photoURI)

我假设从我的原始 uri 创建文件然后使用文件提供程序将其重新转换为 uri 的过程使其路径变为错误所说的内容。

【问题讨论】:

“有问题的 URI”——这不是有效的 Uri。出于某种原因,您有一个不应该存在的领先 / 对不起,我粘贴了错误的文字,我已经更新了问题,错误上的额外/来自记录器 该错误表明您的原始文本是您实际使用的 FileProvider。错误消息显示相同的前导/ 我添加了更多信息 【参考方案1】:
val photoURI = FileProvider.getUriForFile(
    context,
    "com.sudharsanravikumar.myapplication.provider",
    File(uri.uri)
)

uri.uri 似乎是 String,其值为:file:///storage/emulated/0/Android/media/com.sudharsanravikumar.myapplication/AlbumExpo/2021-11-08-07-37-55-596.jpg

这是Uri 的字符串表示形式,采用file 方案。它不是文件系统路径。你不能将它传递给File 构造函数并获得有用的东西。

您似乎最初通过getExternalMediaDirs() 获得了您的价值。您可能会考虑保留该文件系统路径值,而不是使用您无法使用的 file 方案将其转换为 Uri(通过 Uri.fromFile())。

但是,鉴于您当前的 uri.uri 值,您需要将代码更改为:

val photoURI = FileProvider.getUriForFile(
    context,
    "com.sudharsanravikumar.myapplication.provider",
    File(Uri.parse(uri.uri).path)
)

Uri.parse(uri.uri) 将把String 重新变成Uri,尽管它使用了最没用的file 方案。 Uri.parse(uri.uri).path 将提取文件系统路径 (/storage/emulated/0/Android/media/com.sudharsanravikumar.myapplication/AlbumExpo/2021-11-08-07-37-55-596.jpg)。然后你将 that 传递给 File 构造函数。始终将文件系统路径传递给 File 构造函数。

【讨论】:

这行得通,但现在我的小部件显示“加载小部件时出现问题”,我在日志中得到了这个,尽管没有标记为错误:2021-11-17 00:15:56.962 1545-4759/? W/ActivityManager: Permission Denial: 从未从 UID 10448 导出的 ProcessRecordea978f1 2178:com.google.android.apps.nexuslauncher/u0a152 (pid=2178, uid=10152) 打开提供程序 androidx.core.content.FileProvider @barryalan2633:其他应用需要权限才能使用您的FileProvider。通常,您可以通过在 Intent 上使用标志来做到这一点(例如,FLAG_GRANT_READ_URI_PERMISSION)。不过,我不确定RemoteViews 和应用小部件的解决方案是什么。

以上是关于来自 Room 的小部件中的 setImageViewUri的主要内容,如果未能解决你的问题,请参考以下文章

在 Qt 中的小部件内部绘画

处理来自引用未知的小部件的信号

在 MarshMallow 的小部件中显示来自 SDCard 的图像

如何禁用来自另一个站点的小部件上的链接?

如何从python中的小部件在任何窗口上绘制

Wordpress:如何仅将 widget_title 过滤器应用于某个侧边栏中的小部件?