Mastering Camera2 API in Kotlin: A Comprehensive Guide with Examples

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!
Learn More:
1.Understanding the Differences Between Activities and Fragments
2. Exploring Hilt Integration in Jetpack Compose: A Comprehensive Guide