Search code examples
androidandroid-jetpack-composeandroid-sharingcoil

Convert Jetpack Compose Image into BitMap Image for Sharing Purpose


I am looking for help on how to share image binary content from my PhotoApp to external Social Media apps.

I load the image from an API using Coil and display the image in a composable.

@Composable
fun PhotoDetailsScreen( photo: AstroPhoto ... ) {
         
           val context = LocalContext.current
        
            val imgUri = photo.url.toUri()
                    .buildUpon()
                    .scheme("https")
                    .build()
        
    Column ( ...
                //Image
                Image(
                        painter = rememberImagePainter(
                                data = imgUri,
                                builder = {
                                    crossfade(true)
                                    placeholder(R.drawable.loading_animation)
                                }
                        ) ... 
                //Assist Chip
                  AssistChip(onClick = { shareAstroPhoto("", context) }

Clicking on the AssistChip calls the below shareAstroPhoto() fxn that takes the uri pointing to the image file to fire an ACTION_SEND Intent

 fun shareAstroPhoto(uri:String, context: Context){
        
        val intent = Intent().apply {
    
            action = Intent.ACTION_SEND
            putExtra(Intent.EXTRA_STREAM, uri)
            type = "image/jpg"
        }
        context.startActivity(Intent.createChooser(intent, null))
    }

I intend to get a Bitmap out of my composable, save the Bitmap in my own ContentProvider or MediaStore (I know how these 2 work) and then pass the uri of the saved BitMap to Intent.EXTRA_STREAM.

Have browsed through similar cases and videos but all I find is working with XML code.

Therefore my query is how to convert Jetpack Compose Image from a composable into a Bitmap to enable sharing the file with other external apps through Android Sharesheet.


Solution

  • I'm not sure if I understand your question. If you just want to share the image, then:

    Util function:

    fun Context.shareImage(title: String, image: Drawable, filename: String) {
        val file = try {
            val outputFile = File(cacheDir, "$filename.png")
            val outPutStream = FileOutputStream(outputFile)
            image.toBitmap().compress(CompressFormat.PNG, 100, outPutStream)
            outPutStream.flush()
            outPutStream.close()
            outputFile
        } catch (e: Throwable) {
            return toast(e)
        }
        val uri = file.toUriCompat(this)
        val shareIntent = Intent().apply {
            action = Intent.ACTION_SEND
            type = "image/png"
            putExtra(Intent.EXTRA_STREAM, uri)
        }
        startActivity(Intent.createChooser(shareIntent, title))
    }
    

    Share image with (Coil 2.0):

    val painter = rememberAsyncImagePainter(
        ImageRequest.Builder(LocalContext.current)
            .data(url)
            .build()
    )
    Button(
        onClick={
            val state = painter.state as? AsyncImagePainter.State.Success
            val drawable = state?.result.drawable
            context.shareImage(
                "Share image via",
                 drawable,
                "filename"
            )
        }
    )
    

    Updated

    Those are small helper functions, but if you want them:

    fun File.toUriCompat(context: Context): Uri {
        return FileProvider.getUriForFile(context, context.packageName + ".provider", this)
    }
    fun Context.toast(throwable: Throwable) =
        throwable.message?.let { toast(it) }
            ?: toast(R.string.unknown_error)
    fun Context.toast(message: String) {
        Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
    }