Existing 3-function callback to Kotlin Coroutines
In this particular case you can use a general approach to convert a callback-based API to a suspending function via suspendCoroutine
function:
suspend fun CameraManager.openCamera(cameraId: String): CameraDevice? = suspendCoroutine { cont -> val callback = object : CameraDevice.StateCallback() { override fun onOpened(camera: CameraDevice) { cont.resume(camera) } override fun onDisconnected(camera: CameraDevice) { cont.resume(null) } override fun onError(camera: CameraDevice, error: Int) { // assuming that we don't care about the error in this example cont.resume(null) } } openCamera(cameraId, callback, null) }
Now, in your application code you can just do manager.openCamera(cameraId)
and get a reference to CameraDevice
if it was opened successfully or null
if it was not.
I've used 2 solutions for this type of thing.
1: wrap the interface in an extension
CameraDevice.openCamera(cameraId: Integer, onOpenedCallback: (CameraDevice) -> (), onDisconnectedCallback: (CameraDevice) ->()) { manager.openCamera(cameraId, object : CameraDevice.StateCallback() { override fun onOpened(openedCameraDevice: CameraDevice) { onOpenedCallback(openedCameraDevice) } override fun onDisconnected(cameraDevice: CameraDevice) { onDisconnectedCallback(cameraDevice) } })}
2: Make a simple container class with a more functional interface:
class StateCallbackWrapper(val onOpened: (CameraDevice) -> (), val onClosed: (CameraDevice) ->()): CameraDevice.StateCallback() { override fun onOpened(openedCameraDevice: CameraDevice) { onOpened(openedCameraDevice) } override fun onDisconnected(cameraDevice: CameraDevice) { onClosed(cameraDevice) }}
Personally I would start with something like these, and then build whatever threading differences on top of that.