I have a caller app that allows the user to pick up photos for the contacts and audio files for the ringtones from their mobile. When I pick up the photo, it can be displayed correctly using the URI on the interface. on both the main page and contact page. and i save it inside the room database...
if i close the app and reopen it, it gets the same URI from db. but no image is displayed. neither on the main page or contact page.
i tried to insert the URI code manually it didn't display anything as well... also change the image loader to GlideImage
from rememberImagePainter
(another implementation) but same issue...
the URI i have from db and image picker looks like this
val uri2:Uri = "content://com.android.providers.media.documents/document/image%3A34".toUri()
the code the pick up the image Uri is this
class GetContentActivityResult(
private val launcher: ManagedActivityResultLauncher<String, Uri>,
val uri: Uri?
) {
fun launch(mimeType: String) {
launcher.launch(mimeType)
}
}
@Composable
fun rememberGetContentActivityResult(): GetContentActivityResult {
var uri by rememberSaveable { mutableStateOf<Uri?>(null) }
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.GetContent(), onResult = {
uri = it
})
return remember(launcher, uri) { GetContentActivityResult(launcher, uri) }
}
i display the image in the contact page like this
val getContent = rememberGetContentActivityResult() <-- to access the class of pickup files
if (roomViewModel.photoUri.value.isBlank()){ <-- if no image from db display the picked image using image picker
getContent.uri?.let {
Image(
modifier = Modifier
.align(Alignment.TopCenter)
.fillMaxSize(1f),
contentDescription = "UserImage",
contentScale = ContentScale.Crop,
painter = rememberImagePainter(data = it))
}
}else{
Image(
modifier = Modifier
.align(Alignment.TopCenter)
.fillMaxSize(1f),
contentDescription = "UserImage",
contentScale = ContentScale.Crop,
painter = rememberImagePainter(data = roomViewModel.photoUri.value))
}
}
TextButton(
onClick = { getContent.launch("image/*") }, <-- launching the class to get the image URI by defining the Mime as image/*
modifier = Modifier.layoutId("changePhoto")
) {
Text(
text = "Change Photo",
color = Color.Black)}
inside the main page. there is no image picker, i just display the data that i have in the Database, and i display the image this way
@OptIn(ExperimentalCoilApi::class)
@Composable
fun ProfilePicture(uri : Uri, imageSize: Dp) {
Card(
shape = CircleShape,
border = BorderStroke(
width = 2.dp,
color = Color.Red ),
modifier = Modifier.padding(16.dp),
elevation = 4.dp) {
val uri2:Uri = "content://com.android.providers.media.documents/document/image%3A34".toUri() //<-- i tried to load the image this way also it didn't work.
val painter = rememberImagePainter(
data = uri,
builder = {
placeholder(R.drawable.yara) <-- the placeholder image blinks quickly when app is loaded and then disappear...
}
)
Image(
painter = painter,
contentDescription = "User Image",
modifier = Modifier.size(imageSize) )
}
}
Is it an issue with the Uri picker or image display?
other content from room db are displayed correctly (strings)
i tried to use the code on emulator and real device and it is the same for both cases...
one thing i just noticed... if i used the image picker and pick a previously picked image (it's uri is in the db) the image is displayed on the other locations in the app automatically without doing anything else... just picking the image and displaying it without saving it even...
Uri
values in a database (or any other sort of file). Or, switch toOpenDocument
instead ofGetContent
and usetakePersistableUriPermission()
to get durable access to the content. Otherwise, your rights to access the content will be short-lived. – SabbaticalActivityResultContracts.GetContent()
, system will give you a temporary URL. It's fine to use it during one session, but if you wanna store it - you need to copy it into your app storage – LandberttakePersistableUriPermission()
or to add a flag as the link suggests? – Autoclave