From fe0129522634441733bfab624cbac4ebace8c326 Mon Sep 17 00:00:00 2001 From: Menardi Date: Thu, 31 Mar 2022 17:01:21 +0100 Subject: [PATCH] fix: Fix Android focus not using correct focus point (#958) This commit fixes #758. I was having the same issue and looked into it a bit. I found [this StackOverflow answer](https://stackoverflow.com/a/60585382) which described a solution to the same problem. Rather than manually calculate the focus point, we can get the PreviewView to do it for us. This fixes the issue because the PreviewView factors in any scaling or resizing of the view on the screen, which we weren't doing before. The only potential issue is that this needs to run on the UI thread (which is what the `withContext` is doing), but I've tested it with frame processors enabled and disabled, and have found no issues in either case. --- .../main/java/com/mrousavy/camera/CameraView+Focus.kt | 9 ++++++--- android/src/main/java/com/mrousavy/camera/CameraView.kt | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/android/src/main/java/com/mrousavy/camera/CameraView+Focus.kt b/android/src/main/java/com/mrousavy/camera/CameraView+Focus.kt index da68003..c945c0b 100644 --- a/android/src/main/java/com/mrousavy/camera/CameraView+Focus.kt +++ b/android/src/main/java/com/mrousavy/camera/CameraView+Focus.kt @@ -1,9 +1,9 @@ package com.mrousavy.camera import androidx.camera.core.FocusMeteringAction -import androidx.camera.core.SurfaceOrientedMeteringPointFactory import com.facebook.react.bridge.ReadableMap import kotlinx.coroutines.guava.await +import kotlinx.coroutines.withContext import java.util.concurrent.TimeUnit suspend fun CameraView.focus(pointMap: ReadableMap) { @@ -16,8 +16,11 @@ suspend fun CameraView.focus(pointMap: ReadableMap) { val x = pointMap.getDouble("x") * dpi val y = pointMap.getDouble("y") * dpi - val factory = SurfaceOrientedMeteringPointFactory(this.width.toFloat(), this.height.toFloat()) - val point = factory.createPoint(x.toFloat(), y.toFloat()) + // Getting the point from the previewView needs to be run on the UI thread + val point = withContext(coroutineScope.coroutineContext) { + previewView.meteringPointFactory.createPoint(x.toFloat(), y.toFloat()); + } + val action = FocusMeteringAction.Builder(point, FocusMeteringAction.FLAG_AF or FocusMeteringAction.FLAG_AE) .setAutoCancelDuration(5, TimeUnit.SECONDS) // auto-reset after 5 seconds .build() diff --git a/android/src/main/java/com/mrousavy/camera/CameraView.kt b/android/src/main/java/com/mrousavy/camera/CameraView.kt index 16eb4dc..507e9fd 100644 --- a/android/src/main/java/com/mrousavy/camera/CameraView.kt +++ b/android/src/main/java/com/mrousavy/camera/CameraView.kt @@ -121,7 +121,7 @@ class CameraView(context: Context, private val frameProcessorThread: ExecutorSer private val cameraExecutor = Executors.newSingleThreadExecutor() internal val takePhotoExecutor = Executors.newSingleThreadExecutor() internal val recordVideoExecutor = Executors.newSingleThreadExecutor() - private var coroutineScope = CoroutineScope(Dispatchers.Main) + internal var coroutineScope = CoroutineScope(Dispatchers.Main) internal var camera: Camera? = null internal var imageCapture: ImageCapture? = null