I have an app that allows the users to take images. I then store the image in a local file and save the URI to Room. I then have a widget associated with the app that has an image view. I inject my database into the widget using Dagger-Hilt and successfully pass that URI to my updateAppWidget method
The URI in question:
file:///storage/emulated/0/Android/media/com.sudharsanravikumar.myapplication/AlbumExpo/2021-11-08-07-37-55-596.jpg
the problem is that the app crashes with the following error:
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
I have tried many things on similar SO questions, but it feels like I am missing some important information. I think I just don't clearly understand how to use File provider tags on my manifest to correctly point the app to the directory where the app stores my images. I am not sure what to show in terms of code so if you need anything please ask in the comments.
Originally my error was:
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()
which was generated when I directly called
views.setImageViewUri(R.id.img_1, Uri.parse(uri.uri))
with my original uri from above. To attempt to solve this issue I followed the accepted answer in this So question
that lead me to do:
val photoURI = FileProvider.getUriForFile(
context,
"com.sudharsanravikumar.myapplication.provider",
File(uri.uri)
)
views.setImageViewUri(R.id.img_1, photoURI)
I am assuming that the process of creating a file from my original uri then re-transforming it to a uri using the file provider makes it's path mutate to what the error says.
val photoURI = FileProvider.getUriForFile(
context,
"com.sudharsanravikumar.myapplication.provider",
File(uri.uri)
)
uri.uri
appears to be a String
, with a value of: file:///storage/emulated/0/Android/media/com.sudharsanravikumar.myapplication/AlbumExpo/2021-11-08-07-37-55-596.jpg
.
This is a string representation of a Uri
, one with the file
scheme. It is not a filesystem path. You cannot pass it to the File
constructor and get something useful.
You seem to have originally gotten your value via getExternalMediaDirs()
. You might consider persisting that filesystem path value, rather than converting it into a Uri
(via Uri.fromFile()
) with a file
scheme that you cannot use.
But, given your current uri.uri
value, you would need to change your code to:
val photoURI = FileProvider.getUriForFile(
context,
"com.sudharsanravikumar.myapplication.provider",
File(Uri.parse(uri.uri).path)
)
Uri.parse(uri.uri)
will turn that String
back into a Uri
, albeit one with the mostly-useless file
scheme. Uri.parse(uri.uri).path
will extract the filesystem path (/storage/emulated/0/Android/media/com.sudharsanravikumar.myapplication/AlbumExpo/2021-11-08-07-37-55-596.jpg
). And you pass that to the File
constructor. Always pass filesystem paths to the File
constructor.