How do I start file chooser using intent in compose

Viewed 2240

I am trying to start file chooser on a button click (composable function). Unable to use startActivityForResult().

@Composable
fun SelectScreen() {

    Button(onClick = {
        val intent = Intent(Intent.ACTION_GET_CONTENT)
        startActivity(intent)
    }
    ) {
        Text("BUTTON")
    }
}
5 Answers

Here is my suggestion:

val pickPictureLauncher = rememberLauncherForActivityResult(
    ActivityResultContracts.GetContent()
) { imageUri ->
    if (imageUri != null) {
        // Update the state with the Uri
    }
}

// In your button's click
pickPictureLauncher.launch("image/*")

and in your composable which display the image, you can do the following

val image = remember {
   // Make sure to resize and compress
   // the image to avoid display a big bitmap
   ImageUtils.imageFromUri(imageUi)
}
Image(
   image,
   contentDescription = null
)

You can use rememberLauncherForActivityResult() to register a request to Activity#startActivityForResult, designated by the given ActivityResultContract.

This creates a record in the ActivityResultRegistry associated with this caller, managing request code, as well as conversions to/from Intent under the hood.

Something like:

val result = remember { mutableStateOf<Uri?>(null) }
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.OpenDocument()) {
    result.value = it
}

Button(onClick = { launcher.launch(arrayOf("image/*")) }) {
    Text(text = "Open Document")
}

result.value?.let {
   //...
}

to use "startActivityForResult()" in compose I found this solution and it worked for me

@Composable
fun SelectScreen() {
val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.type = "*/*";
intent.addCategory(Intent.CATEGORY_OPENABLE);
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) {}

Button(onClick = {
    launcher.launch(intent)
}) {
    Text(text = "Take a picture")
}

}

You will have to start an activity from a valid context, that could be either your application context or activity. If you don't need results back from an activity, meaning that you are not starting the activity for the result then you can start from the application context as well.

companion object{

   var mContext : Context? = null

   /*
   * should set your mContext variable value to this in your activity onCreate,    onStart
   * and set to null in your onStop to avoid leaks
   */
   fun getActivityContext() : Context{
       return mContext;
   }


   fun getApplicationContext() : Context{
       return ApplicationClass.getInstance()
   }
}


@Composable
fun SelectScreen() {
    Button(onClick = {
        val intent = Intent(Intent.ACTION_GET_CONTENT)
        getActivityContext().startActivity(intent)
    }
    ) {
        Text("BUTTON")
    }
}
Related