Skip to content

Commit

Permalink
fix: Fix Android focus not using correct focus point (#958)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Menardi authored Mar 31, 2022
1 parent a7e66ed commit fe01295
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 4 deletions.
9 changes: 6 additions & 3 deletions android/src/main/java/com/mrousavy/camera/CameraView+Focus.kt
Original file line number Diff line number Diff line change
@@ -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) {
Expand All @@ -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()
Expand Down
2 changes: 1 addition & 1 deletion android/src/main/java/com/mrousavy/camera/CameraView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit fe01295

Please sign in to comment.