Skip to content

Commit ce56682

Browse files
committed
feat: Support focus depth/distance on android
1 parent cd18368 commit ce56682

4 files changed

Lines changed: 67 additions & 0 deletions

File tree

package/android/src/main/java/com/mrousavy/camera/core/CameraSession.kt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,17 @@ import android.annotation.SuppressLint
55
import android.content.Context
66
import android.content.pm.PackageManager
77
import android.graphics.BitmapFactory
8+
import android.hardware.camera2.CameraMetadata
9+
import android.hardware.camera2.CaptureRequest
810
import android.media.AudioManager
911
import android.util.Log
1012
import android.util.Range
1113
import android.util.Size
1214
import androidx.annotation.MainThread
1315
import androidx.annotation.OptIn
16+
import androidx.camera.camera2.interop.Camera2CameraControl
17+
import androidx.camera.camera2.interop.CaptureRequestOptions
18+
import androidx.camera.camera2.interop.ExperimentalCamera2Interop
1419
import androidx.camera.core.Camera
1520
import androidx.camera.core.CameraControl
1621
import androidx.camera.core.CameraSelector
@@ -652,6 +657,26 @@ class CameraSession(private val context: Context, private val callback: Callback
652657
}
653658
}
654659

660+
@ExperimentalCamera2Interop
661+
@SuppressLint("RestrictedApi")
662+
fun focusDepth(depth: Double) {
663+
val camera = camera ?: throw CameraNotReadyError()
664+
665+
try {
666+
Camera2CameraControl.from(camera.cameraControl).let {
667+
CaptureRequestOptions.Builder().apply {
668+
val distance = depth.toFloat()
669+
setCaptureRequestOption(CaptureRequest.LENS_FOCUS_DISTANCE, distance)
670+
setCaptureRequestOption(CaptureRequest.CONTROL_AF_MODE, CameraMetadata.CONTROL_AF_MODE_OFF)
671+
}.let { builder ->
672+
it.addCaptureRequestOptions(builder.build())
673+
}
674+
}
675+
} catch (e: CameraControl.OperationCanceledException) {
676+
throw FocusCanceledError()
677+
}
678+
}
679+
655680
interface Callback {
656681
fun onError(error: Throwable)
657682
fun onFrame(frame: Frame)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.mrousavy.camera.react
2+
3+
import androidx.camera.camera2.interop.ExperimentalCamera2Interop
4+
5+
@ExperimentalCamera2Interop
6+
fun CameraView.focusDepth(distance: Double) {
7+
cameraSession.focusDepth(distance)
8+
}

package/android/src/main/java/com/mrousavy/camera/react/CameraViewModule.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package com.mrousavy.camera.react
33
import android.Manifest
44
import android.content.pm.PackageManager
55
import android.util.Log
6+
import androidx.camera.camera2.interop.ExperimentalCamera2Interop
67
import androidx.core.content.ContextCompat
78
import com.facebook.react.bridge.Callback
89
import com.facebook.react.bridge.Promise
@@ -188,6 +189,18 @@ class CameraViewModule(reactContext: ReactApplicationContext) : ReactContextBase
188189
}
189190
}
190191

192+
@ExperimentalCamera2Interop
193+
@ReactMethod
194+
fun focusDepth(viewTag: Int, distance: Double, promise: Promise) {
195+
backgroundCoroutineScope.launch {
196+
val view = findCameraView(viewTag)
197+
withPromise(promise) {
198+
view.focusDepth(distance)
199+
return@withPromise null
200+
}
201+
}
202+
}
203+
191204
private fun canRequestPermission(permission: String): Boolean {
192205
val activity = currentActivity as? PermissionAwareActivity
193206
return activity?.shouldShowRequestPermissionRationale(permission) ?: false

package/src/Camera.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,27 @@ export class Camera extends React.PureComponent<CameraProps, CameraState> {
372372
throw tryParseNativeCameraError(e)
373373
}
374374
}
375+
376+
/**
377+
* Focus the camera to a specific distance.
378+
* @param {number} distance The distance to focus to. It should be lower than the minFocusDistance. Lower the value (closer to 0.001f), further the distance, higher the value (closer to the minFocusDistance), more macro the focus will be.
379+
*
380+
* Make sure the value doesn't exceed the device.minFocusDistance.
381+
*
382+
* @throws {@linkcode CameraRuntimeError} When any kind of error occured while focussing.
383+
* Use the {@linkcode CameraRuntimeError.code | code} property to get the actual error
384+
* @example
385+
* ```ts
386+
* await camera.current.focusDepth(5)
387+
* ```
388+
*/
389+
public async focusDepth(distance: number): Promise<void> {
390+
try {
391+
return await CameraModule.focusDepth(this.handle, distance)
392+
} catch (e) {
393+
throw tryParseNativeCameraError(e)
394+
}
395+
}
375396
//#endregion
376397

377398
//#region Static Functions (NativeModule)

0 commit comments

Comments
 (0)