Search code examples
androidimageandroid-jetpack-composeandroid-glidecoil

Unable to load image using Coil from content URI


I am trying to load an image who's (mimeType is video/mp4) using coil in my Android app from a content URI.

Here is the code snippet I am using:


val mediaPath = "content://media/external/file/252819" // its mimeType is video/mp4

AsyncImage(
    model = mediaPath,
    contentDescription = stringResource(id = R.string.thumbnail),
    placeholder = painterResource(id = R.drawable.ic_default_thumbnail),
    error = painterResource(id = R.drawable.ic_default_thumbnail),
    modifier = Modifier
        .fillMaxWidth()
        .aspectRatio(1f),
    contentScale = ContentScale.Crop
)

Even i also try to load it using rememberAsyncImagePainter:

val imagePainter = 
            rememberAsyncImagePainter(
                ImageRequest.Builder(LocalContext.current).data(data = media.mediaPath).apply(block = fun ImageRequest.Builder.() {
                    placeholder(R.drawable.ic_default_thumbnail)
                    error(R.drawable.ic_default_thumbnail)
                }).build()
            )

        Image(
            painter = imagePainter,
            contentDescription = stringResource(id = R.string.thumbnail),
            modifier = Modifier
                .fillMaxWidth()
                .aspectRatio(1f),
            contentScale = ContentScale.Crop
        )

Despite using the correct content URI and providing the necessary placeholder and error resources, I am unable to successfully load the thumbnail image. I have verified that the content URI is valid and refers to an existing video file.

Note: I have the required permissions to access the content URI and have ensured that the content URI is correct.


Solution

  • Use this LoadThumbnail method to load the image/video thumbnail by using coil:

    @Composable
    fun LoadThumbnail(
        mediaPath: String,
        isVideo: Boolean,
        modifier: Modifier = Modifier
    ) {
        val context = LocalContext.current
        if (isVideo) {
            val imageLoader = remember {
                ImageLoader.Builder(context)
                    .memoryCachePolicy(CachePolicy.ENABLED)
                    .diskCachePolicy(CachePolicy.ENABLED)
                    .respectCacheHeaders(true)
                    .components {
                        add(VideoFrameDecoder.Factory())
                    }
                    .crossfade(true)
                    .build()
            }
        val painter = rememberAsyncImagePainter(
            model = mediaPath,
            imageLoader = imageLoader,
        )
    
        if (painter.state is AsyncImagePainter.State.Loading) {
            Image(
                painter = painterResource(id = R.drawable.ic_default_thumbnail),
                contentDescription = null,
                modifier = modifier,
                contentScale = ContentScale.Crop,
            )
        }
    
        Image(
            painter = painter,
            contentDescription = stringResource(id = R.string.thumbnail),
            contentScale = ContentScale.Crop,
            modifier = modifier
        )
    } else {
        AsyncImage(
            model = mediaPath,
            contentDescription = stringResource(id = R.string.thumbnail),
            modifier = modifier,
            contentScale = ContentScale.Crop,
            placeholder = painterResource(id = R.drawable.ic_default_thumbnail),
            error = painterResource(id = R.drawable.ic_default_thumbnail)
        )
    }
    }