Android has released a new API camerax in recent months. I'm trying to understand how to get auto-focusing for the camera to work.
https://groups.google.com/a/android.com/forum/#!searchin/camerax-developers/auto$20focus|sort:date/camerax-developers/IQ3KZd8iOIY/LIbrRIqEBgAJ
Here is a discussion on the topic but there is almost no specific documentation on it.
Here is also the basic camerax app but I couldn't find any file dealing with the auto focusing.
Any tips or points to documentation is helpful. Also I'm fairly new to android so its very possible I'm missing something that makes the above links more useful.
With the current CameraX 1.0.0
, you can proceed in this 2 ways:
Auto-focus every X seconds:
previewView.afterMeasured {
val autoFocusPoint = SurfaceOrientedMeteringPointFactory(1f, 1f)
.createPoint(.5f, .5f)
try {
val autoFocusAction = FocusMeteringAction.Builder(
autoFocusPoint,
FocusMeteringAction.FLAG_AF
).apply {
//start auto-focusing after 2 seconds
setAutoCancelDuration(2, TimeUnit.SECONDS)
}.build()
camera.cameraControl.startFocusAndMetering(autoFocusAction)
} catch (e: CameraInfoUnavailableException) {
Log.d("ERROR", "cannot access camera", e)
}
}
Focus on-tap:
previewView.afterMeasured {
previewView.setOnTouchListener { _, event ->
return@setOnTouchListener when (event.action) {
MotionEvent.ACTION_DOWN -> {
true
}
MotionEvent.ACTION_UP -> {
val factory: MeteringPointFactory = SurfaceOrientedMeteringPointFactory(
previewView.width.toFloat(), previewView.height.toFloat()
)
val autoFocusPoint = factory.createPoint(event.x, event.y)
try {
camera.cameraControl.startFocusAndMetering(
FocusMeteringAction.Builder(
autoFocusPoint,
FocusMeteringAction.FLAG_AF
).apply {
//focus only when the user tap the preview
disableAutoCancel()
}.build()
)
} catch (e: CameraInfoUnavailableException) {
Log.d("ERROR", "cannot access camera", e)
}
true
}
else -> false // Unhandled event.
}
}
}
afterMeasured extension function is a simple utility:
inline fun View.afterMeasured(crossinline block: () -> Unit) {
viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
if (measuredWidth > 0 && measuredHeight > 0) {
viewTreeObserver.removeOnGlobalLayoutListener(this)
block()
}
}
})
}
A Camera
object can be obtained with
val camera = cameraProvider.bindToLifecycle(
this@Activity, cameraSelector, previewView //this is a PreviewView
)