Mastering Camera2 API in Kotlin: A Comprehensive Guide with Examples

Reza Ramesh
Towards Dev
Published in
3 min readNov 22, 2023

--

The Camera2 API in Android is a powerful framework that allows developers to access advanced camera features on Android devices. It provides fine-grained control over camera settings, exposure, focus, and more. In this article, we will explore how to use the Camera2 API in Kotlin with practical examples.

Setting Up Your Project

Before diving into Camera2, ensure that you have the necessary permissions in your AndroidManifest.xml file:

<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-feature android:name="android.hardware.camera.flash" />

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Additionally, make sure your app’s target SDK is at least 21 (Android 5.0, Lollipop), as Camera2 API is not available in earlier versions.

Managing Camera Permissions

Handle camera permissions in your activity or fragment. You can use the following code to check and request camera permissions:

private val cameraPermissionCode = 101

private fun checkCameraPermission() {
if (ContextCompat.checkSelfPermission(
this,
Manifest.permission.CAMERA
) != PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.CAMERA),
cameraPermissionCode
)
} else {
// Permission already granted
// Initialize and open the camera
initializeCamera()
}
}

override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
if (requestCode == cameraPermissionCode) {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission granted
// Initialize and open the camera
initializeCamera()
} else {
// Permission denied
Toast.makeText(this, "Camera permission denied", Toast.LENGTH_SHORT).show()
}
}
}

Initializing the Camera

Once you have obtained the necessary permissions, it’s time to initialize the camera. You can use the following code to get a reference to the camera and open it:

private lateinit var cameraDevice: CameraDevice

private val cameraStateCallback = object : CameraDevice.StateCallback() {
override fun onOpened(camera: CameraDevice) {
cameraDevice = camera
// Start camera preview here
startCameraPreview()
}

override fun onDisconnected(camera: CameraDevice) {
// Handle camera disconnection
camera.close()
}

override fun onError(camera: CameraDevice, error: Int) {
// Handle camera errors
camera.close()
}
}

private fun initializeCamera() {
val cameraManager = getSystemService(Context.CAMERA_SERVICE) as CameraManager
val cameraId = cameraManager.cameraIdList[0] // Use the first camera

// Open the camera
cameraManager.openCamera(cameraId, cameraStateCallback, null)
}

Starting Camera Preview

To display the camera preview, create a CameraCaptureSession and set up a Surface to receive the preview frames. Here's an example:

private lateinit var cameraCaptureSession: CameraCaptureSession
private lateinit var previewRequestBuilder: CaptureRequest.Builder

private fun startCameraPreview() {
val surfaceTexture = textureView.surfaceTexture
surfaceTexture.setDefaultBufferSize(previewSize.width, previewSize.height)

val surface = Surface(surfaceTexture)
previewRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)
previewRequestBuilder.addTarget(surface)

cameraDevice.createCaptureSession(
listOf(surface),
object : CameraCaptureSession.StateCallback() {
override fun onConfigured(session: CameraCaptureSession) {
cameraCaptureSession = session
updatePreview()
}

override fun onConfigureFailed(session: CameraCaptureSession) {
// Handle configuration failures
}
},
null
)
}

Capturing Still Images

To capture still images, create a new CaptureRequest and configure it for image capture. Here's a simplified example:

private fun takePicture() {
val imageReader = ImageReader.newInstance(
imageWidth, imageHeight,
ImageFormat.JPEG, 1
)

val surfaces = mutableListOf<Surface>()
surfaces.add(imageReader.surface)
surfaces.add(Surface(textureView.surfaceTexture))

val captureRequestBuilder =
cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE)
captureRequestBuilder.addTarget(imageReader.surface)

cameraDevice.createCaptureSession(
surfaces,
object : CameraCaptureSession.StateCallback() {
override fun onConfigured(session: CameraCaptureSession) {
session.capture(captureRequestBuilder.build(), null, null)
}

override fun onConfigureFailed(session: CameraCaptureSession) {
// Handle configuration failures
}
},null
)
}

Conclusion

The Camera2 API in Kotlin offers powerful features for developing camera applications on Android. This article provided a basic overview and practical examples for initializing the camera, starting the preview, and capturing still images. Explore the official Android documentation for more advanced features and customization options. Happy coding!

LinkedInGithub

Learn More:

1.Understanding the Differences Between Activities and Fragments

2. Exploring Hilt Integration in Jetpack Compose: A Comprehensive Guide

3.Exploring the World with Google Maps in Jetpack Compose

--

--

I am an Android developer and UI/UX designer with 4 years of experience in creating engaging and user-friendly mobile applications