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.