Home > Back-end >  How to use stock camera app to take photo with Jetpack Compose?
How to use stock camera app to take photo with Jetpack Compose?

Time:06-06

In my app using Jetpack Compose, how can I use the existing stock photo app to take a picture and store it? Google's documentation mentions the depreciated Camera API by using an Intent, but they're using the old view system. And it seems like the newer Camera2 and CameraX APIs both are intended for creating custom camera interfaces directly in the app.

CodePudding user response:

You have to use the activity contracts, see this article for details

class ComposeFileProvider : FileProvider(
    R.xml.filepaths
) {
    companion object {
        fun getImageUri(context: Context): Uri {
            val directory = File(context.cacheDir, "images")
            directory.mkdirs()
            val file = File.createTempFile(
                "selected_image_",
                ".jpg",
                directory,
            )
            val authority = context.packageName   ".fileprovider"
            return getUriForFile(
                context,
                authority,
                file,
            )
        }
    }
}

@Composable
fun ImagePicker(
    modifier: Modifier = Modifier,
) {
    var hasImage by remember {
        mutableStateOf(false)
    }
    var imageUri by remember {
        mutableStateOf<Uri?>(null)
    }

    val imagePicker = rememberLauncherForActivityResult(
        contract = ActivityResultContracts.GetContent(),
        onResult = { uri ->
            hasImage = uri != null
            imageUri = uri
        }
    )

    val cameraLauncher = rememberLauncherForActivityResult(
        contract = ActivityResultContracts.TakePicture(),
        onResult = { success ->
            hasImage = success
        }
    )

    val context = LocalContext.current
    Box(
        modifier = modifier,
    ) {
        if (hasImage && imageUri != null) {
            AsyncImage(
                model = imageUri,
                modifier = Modifier.fillMaxWidth(),
                contentDescription = "Selected image",
            )
        }
        Column(
            modifier = Modifier
                .align(Alignment.BottomCenter)
                .padding(bottom = 32.dp),
            horizontalAlignment = Alignment.CenterHorizontally,
        ) {
            Button(
                onClick = {
                    imagePicker.launch("image/*")
                },
            ) {
                Text(
                    text = "Select Image"
                )
            }
            Button(
                modifier = Modifier.padding(top = 16.dp),
                onClick = {
                    val uri = ComposeFileProvider.getImageUri(context)
                    imageUri = uri
                    cameraLauncher.launch(uri)
                },
            ) {
                Text(
                    text = "Take photo"
                )
            }
        }
    }
}

CodePudding user response:

You're a bit confused. There's 3 ways to take a picture.

1)Intent. This does not use views- it launches the camera app to take the picture. If you don't need tighter control, use this, it's the easiest way.

2)Camera 1 API. This is deprecated. This does not use views, because it doesn't require you to display anything. Displaying something is your option.

3)Camera 2 API. This is the current API way to do it. Once again, it doesn't require views, because it doesn't require you to display anything.

Also, you did know that you can wrap and view into Jetpack using AndroidView, right? So even if you did want to use a camera built in display view, you can use that. Get used to doing things like that if you go down the compose route, very few libraries use compose.

  • Related