'Why local images saved in Room database are not displayed after i restart an app?

I'm saving uri's as a string in Room database, then the app is retrieving data and displaying all the images in the LazyVerticalGrid. When i add images, everything works fine, all the images are displayed correctly. The problem is when i restart an app. All the images disappears and when i add exactly the same image (with the same uri) - it appear in the first position, but also in all the positions before i restarted an app. When i check the logs, all uri's are also retrieved correctly from database as format:

content://com.android.providers.media.documents/document/image%3A9371

Here is the code for Image showing (using coil):

@Composable
fun ProfilePhotoView(photo: String, navController: NavHostController) {
    Image(
        painter = rememberImagePainter(photo),
        contentDescription = null,
        contentScale = ContentScale.Crop,
        modifier = Modifier
            .aspectRatio(1f)
            .padding(3.dp)
            .clip(RoundedCornerShape(10.dp))
            .clickable {},
        alignment = Alignment.Center
    )
    Log.i(TAG,"photo string = ${photo}")
}

And here is how i retrieve an uri before adding to database:

val selectImagelauncher = rememberLauncherForActivityResult(
        contract =
        ActivityResultContracts.GetContent()
    ) { uri: Uri? ->
        imageUriState = uri
    }
selectImagelauncher.launch("image/*")

Do you have any idea why i can't display images with "old" uri before adding the same image into database?



Solution 1:[1]

Create your own ActivityResultContract, for your case

contentResolver.takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION)
this is after pickup Uri

class GetPicturesContract : ActivityResultContract<String, Uri?>() {
override fun createIntent(context: Context, input: String?): Intent {
    return Intent(Intent.ACTION_OPEN_DOCUMENT)
        .addCategory(Intent.CATEGORY_OPENABLE)
        .setType(input)
}

override fun getSynchronousResult(
    context: Context,
    input: String
): SynchronousResult<Uri?>? {
    return null
}

override fun parseResult(resultCode: Int, intent: Intent?): Uri? {
    return if (intent == null || resultCode != Activity.RESULT_OK) null else intent.data
}

}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1