Site icon Howtodoandroid

How to capture images using the camera in jetpack compose

Take photos using the camera in jetpack compose poster

In this tutorial, I am going to explain how to capture images in a jetpack compose using a device camera. Also, I have added code to asking runtime permissions for the camera.

To get started with taking photos using the camera, First need to add camera permission on the manifest.xml file.

<uses-permission android:name="android.permission.CAMERA"/> <uses-feature android:name="android.hardware.camera.any"/>
Code language: HTML, XML (xml)

Get File URI From Pathprovider

In the next step, need to get the file URI to store the captured image. So, we need to use the file Provider to get the file URI.

need to create a path_provider.xml file and define the cache directory.

<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-cache-path name="my_images" path="/"/> </paths>
Code language: HTML, XML (xml)

After creating the path provider XML file need to declare that in the manifest.xml file.

<provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.provider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/path_provider" /> </provider>
Code language: HTML, XML (xml)

Now, we have access to the external cache directory. Then create the file and get the URL from the file provider.

val context = LocalContext.current val file = context.createImageFile() val uri = FileProvider.getUriForFile( Objects.requireNonNull(context), BuildConfig.APPLICATION_ID + ".provider", file ) fun Context.createImageFile(): File { // Create an image file name val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date()) val imageFileName = "JPEG_" + timeStamp + "_" val image = File.createTempFile( imageFileName, /* prefix */ ".jpg", /* suffix */ externalCacheDir /* directory */ ) return image }
Code language: JavaScript (javascript)

Now the file is ready to store the captured image. But to launch the camera we need camera permission for the application. let’s create the permission launcher to get the camera permission.

check my another tutorial to learn runtime permissions on jetpack compose.

https://www.howtodoandroid.com/runtime-permission-on-jetpack-compose/

val permissionLauncher = rememberLauncherForActivityResult( ActivityResultContracts.RequestPermission() ) { if (it) { Toast.makeText(context, "Permission Granted", Toast.LENGTH_SHORT).show() cameraLauncher.launch(uri) } else { Toast.makeText(context, "Permission Denied", Toast.LENGTH_SHORT).show() } }
Code language: JavaScript (javascript)

Also, create the camera launcher to capture the image. Also, create mutableStateOf() a variable to store the captured image URL. by default it will be empty. After capture, the image updates the captured image URI.

var capturedImageUri by remember { mutableStateOf<Uri>(Uri.EMPTY) } val cameraLauncher = rememberLauncherForActivityResult(ActivityResultContracts.TakePicture()) { capturedImageUri = uri }
Code language: PHP (php)

Check the camera permission, if permission is granted call the camera launcher or launch the camera launcher.

val permissionCheckResult = ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) if (permissionCheckResult == PackageManager.PERMISSION_GRANTED) { cameraLauncher.launch(uri) } else { // Request a permission permissionLauncher.launch(Manifest.permission.CAMERA) }
Code language: JavaScript (javascript)

In the above code in the camera launcher, we are updating the captured image URI, So that the image will be displayed using the URL.

if (capturedImageUri.path?.isNotEmpty() == true) { Image( modifier = Modifier .padding(16.dp, 8.dp), painter = rememberImagePainter(capturedImageUri), contentDescription = null ) }
Code language: JavaScript (javascript)

final code for this example,

class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { CaptureImageFromCameraJetpackComposeTheme { // A surface container using the 'background' color from the theme Surface( modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background ) { AppContent() //check permission } } } } } @OptIn(ExperimentalCoilApi::class) @Composable fun AppContent() { val context = LocalContext.current val file = context.createImageFile() val uri = FileProvider.getUriForFile( Objects.requireNonNull(context), BuildConfig.APPLICATION_ID + ".provider", file ) var capturedImageUri by remember { mutableStateOf<Uri>(Uri.EMPTY) } val cameraLauncher = rememberLauncherForActivityResult(ActivityResultContracts.TakePicture()) { capturedImageUri = uri } val permissionLauncher = rememberLauncherForActivityResult( ActivityResultContracts.RequestPermission() ) { if (it) { Toast.makeText(context, "Permission Granted", Toast.LENGTH_SHORT).show() cameraLauncher.launch(uri) } else { Toast.makeText(context, "Permission Denied", Toast.LENGTH_SHORT).show() } } Column( Modifier .fillMaxSize() .padding(10.dp), horizontalAlignment = Alignment.CenterHorizontally ) { Button(onClick = { val permissionCheckResult = ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) if (permissionCheckResult == PackageManager.PERMISSION_GRANTED) { cameraLauncher.launch(uri) } else { // Request a permission permissionLauncher.launch(Manifest.permission.CAMERA) } }) { Text(text = "Capture Image From Camera") } } if (capturedImageUri.path?.isNotEmpty() == true) { Image( modifier = Modifier .padding(16.dp, 8.dp), painter = rememberImagePainter(capturedImageUri), contentDescription = null ) } }
Code language: HTML, XML (xml)

output

Thanks for reading. let me know your feedback in the comments. Also, you can download is sample source code on Github.

Exit mobile version