From 09e46f321e32331be7f5389d1af15a3027cec1d7 Mon Sep 17 00:00:00 2001 From: Andrea Brighi Date: Sun, 14 May 2023 17:15:54 +0200 Subject: [PATCH] feat(app): add PreviewViewComposable to show the camera preview stream --- .../app/ui/common/PreviewViewComposable.kt | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 app/src/main/kotlin/com/intelligentbackpack/app/ui/common/PreviewViewComposable.kt diff --git a/app/src/main/kotlin/com/intelligentbackpack/app/ui/common/PreviewViewComposable.kt b/app/src/main/kotlin/com/intelligentbackpack/app/ui/common/PreviewViewComposable.kt new file mode 100644 index 00000000..18e5466c --- /dev/null +++ b/app/src/main/kotlin/com/intelligentbackpack/app/ui/common/PreviewViewComposable.kt @@ -0,0 +1,75 @@ +package com.intelligentbackpack.app.ui.common + +import android.util.Log +import androidx.camera.core.CameraSelector +import androidx.camera.core.ImageAnalysis +import androidx.camera.core.ImageCapture +import androidx.camera.core.Preview +import androidx.camera.lifecycle.ProcessCameraProvider +import androidx.camera.view.PreviewView +import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalLifecycleOwner +import androidx.compose.ui.viewinterop.AndroidView +import androidx.core.content.ContextCompat +import com.intelligentbackpack.app.sensor.BarcodeAnalyser +import java.util.concurrent.Executors + +@androidx.camera.core.ExperimentalGetImage +@Composable +fun PreviewViewComposable(modifier: Modifier, barcodeAnalyser: BarcodeAnalyser) { + val lifecycleOwner = LocalLifecycleOwner.current + var cameraProvider: ProcessCameraProvider? = null + DisposableEffect(key1 = cameraProvider) { + onDispose { + cameraProvider?.unbindAll() // closes the camera + } + } + AndroidView( + { context -> + val cameraExecutor = Executors.newSingleThreadExecutor() + val previewView = PreviewView(context).also { + it.scaleType = PreviewView.ScaleType.FILL_CENTER + } + val cameraProviderFuture = ProcessCameraProvider.getInstance(context) + cameraProviderFuture.addListener({ + cameraProvider = cameraProviderFuture.get() + + val preview = Preview.Builder() + .build() + .also { + it.setSurfaceProvider(previewView.surfaceProvider) + } + + val imageCapture = ImageCapture.Builder().build() + + val imageAnalyzer = ImageAnalysis.Builder() + .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) + .build() + .apply { + setAnalyzer(cameraExecutor, barcodeAnalyser) + } + + val cameraSelector = CameraSelector.Builder() + .requireLensFacing(CameraSelector.LENS_FACING_BACK) + .build() + + try { + // Unbind use cases before rebinding + cameraProvider?.unbindAll() + + // Bind use cases to camera + cameraProvider?.bindToLifecycle( + lifecycleOwner, cameraSelector, preview, imageCapture, imageAnalyzer + ) + + } catch (exc: Exception) { + Log.e("DEBUG", "Use case binding failed", exc) + } + }, ContextCompat.getMainExecutor(context)) + previewView + }, + modifier = modifier + ) +} \ No newline at end of file