Search code examples
androidkotlinhandlerandroid-camera2executor

Clarification on Handlers, Threads and Executors when using a camera in Android Development


I'm trying to implement the Camera2 API in my application. Having never done this before, I'm starting with the Camera2Basic example code provided by android.

However, within the createCaptureSession() method there is a deprecated initialization method CameraDevice.createCaptureSession(), so I changed it to the following:

private suspend fun createCaptureSession(
    device: CameraDevice,
    targets: List<Surface>
): CameraCaptureSession = suspendCoroutine { cont ->

    // Create a capture session using the predefined targets; this also involves defining the
    // session state callback to be notified of when the session is ready
    var outConfig = mutableListOf<OutputConfiguration>()
    for (target in targets) {
        outConfig.add(OutputConfiguration(target))
    }
    var sessionConfig = SessionConfiguration(SessionConfiguration.SESSION_REGULAR, outConfig, cameraExecutor, object: CameraCaptureSession.StateCallback() {

        override fun onConfigured(session: CameraCaptureSession) = cont.resume(session)

        override fun onConfigureFailed(session: CameraCaptureSession) {
            val exc = RuntimeException("Camera ${device.id} session configuration failed")
            cont.resumeWithException(exc)
        }
    })

    device.createCaptureSession(sessionConfig)
}

However, in addition to the created Thread for the camera, now I also need an Executor, so now I have

/** cameraExecutor */
private val cameraExecutor = Executors.newSingleThreadExecutor()

/** [HandlerThread] where all camera operations run */
private val cameraThread = HandlerThread("CameraThread").apply { start() }

/** [Handler] corresponding to [cameraThread] */
private val cameraHandler = Handler(cameraThread.looper)

Having a CameraThread as well as an cameraExecutor is most likely wrong (I guess??). But how can I get a Handler from the Executor? Is this even the correct approach?


Solution

  • The documentation might resolve your problem:

    As per this link:

    To dispatch events through the main thread of your application, you can use Context.getMainExecutor(). To dispatch events through a shared thread pool, you can use AsyncTask#THREAD_POOL_EXECUTOR.

    You might get rid of the variable cameraHandler by using equivalent methods: CameraCaptureSession#capture -> CameraCaptureSession#captureSingleRequest CameraCaptureSession#setRepeatingRequest -> CameraCaptureSession#setSingleRepeatingRequest

    and so on. But be aware, that the method you mentioned (CameraDevice#createCaptureSession(java.util.List<android.view.Surface>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler)) was introduced in API 24 and deprecated in API 30, but the CameraDevice#createCaptureSession(SessionConfiguration) was introduced only in API 28. So very probably You would need to handle API differences.