Experimenting with Jetpack Compose you might have trouble doing old things in the new cool way.
One of these things is opening a media picker where the user can select an image or a video: imagine the use case of a Social Media app where you want your users to publish their content.
Let’s make it simple for now: you want your users to be able to select an image from their gallery.
Working with Jetpack Compose, you can just do the following:
val pickMediaActivityResultLauncher = rememberLauncherForActivityResult(contract = ActivityResultContracts.GetContent()) { uri: Uri? ->//use the received Uri}Button(onClick = {pickMediaActivityResultLauncher.launch("image/*")}) {Text(text = "Pick media content")}
Now, imagine you want your users to be able to publish a video.
You can just change the MIME Type image/*
to video/*
, and keep the above code as it is.
In the picker which will appear, the users can only select a video from their gallery.
Cool, but this is a Social Media app and users want to publish both pictures and videos, and you don’t want to have two different buttons for them to choose what to pick from their gallery.
Unfortunately, the method launch()
doesn’t accept a List
of MIME Types as a parameter.
To solve this inconvenience, you can create a subclass of ActivityResultContracts.GetContent
and set the Intent
to handle both image/*
and video/*
MIME types.
class GetMediaActivityResultContract : ActivityResultContracts.GetContent() {override fun createIntent(context: Context, input: String): Intent {return super.createIntent(context, input).apply {// Force only images and videos to be selectableputExtra(Intent.EXTRA_MIME_TYPES, arrayOf("image/*", "video/*"))}}}
Once you made this new custom ActivityResultContract
you can just launch it like in the previous example:
val pickMediaActivityResultLauncher = rememberLauncherForActivityResult(contract = GetMediaActivityResultContract()) { uri: Uri? ->//use the received Uri}Button(onClick = {pickMediaActivityResultLauncher.launch("*/*")}) {Text(text = "Pick media content")}
Pay attention, you can’t just pass an empty String to pickMediaActivityResultLauncher.launch()
otherwise the system will raise an ActivityNotFoundException
because it doesn’t know how to handle that Intent
.
You can use the wildcard */*
MIME Type to launch the Intent
and then your users will be forced to choose only between an image or a video because those are the MIME types you specified in GetMediaActivityResultContract
.
Bonus: starting from Android 11 (API Level 30) a built-in Photo picker was introduced. I suggest you to check it out and use this picker on devices running on newer APIs handling different Android versions in your code.