This commit is contained in:
Benoit Marty 2025-12-11 17:23:34 +01:00
parent efa5c7794d
commit 6100d4944f
2 changed files with 16 additions and 12 deletions

View file

@ -106,7 +106,7 @@ private fun Content(
QrCodeCameraView( QrCodeCameraView(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
onScanQrCode = { state.eventSink.invoke(QrCodeScanEvents.QrCodeScanned(it)) }, onScanQrCode = { state.eventSink.invoke(QrCodeScanEvents.QrCodeScanned(it)) },
renderPreview = state.isScanning, isScanning = state.isScanning,
) )
} }
} }

View file

@ -45,7 +45,7 @@ import kotlin.coroutines.suspendCoroutine
@Composable @Composable
fun QrCodeCameraView( fun QrCodeCameraView(
onScanQrCode: (ByteArray) -> Unit, onScanQrCode: (ByteArray) -> Unit,
renderPreview: Boolean, isScanning: Boolean,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
if (LocalInspectionMode.current) { if (LocalInspectionMode.current) {
@ -73,13 +73,13 @@ fun QrCodeCameraView(
cameraProvider = localContext.getCameraProvider() cameraProvider = localContext.getCameraProvider()
} }
suspend fun startQRCodeAnalysis(cameraProvider: ProcessCameraProvider, previewView: PreviewView, attempt: Int = 1) { suspend fun startQRCodeAnalysis(cameraProvider: ProcessCameraProvider, attempt: Int = 1) {
lastFrame = null lastFrame = null
val cameraSelector = CameraSelector.Builder() val cameraSelector = CameraSelector.Builder()
.requireLensFacing(CameraSelector.LENS_FACING_BACK) .requireLensFacing(CameraSelector.LENS_FACING_BACK)
.build() .build()
imageAnalysis.setAnalyzer( imageAnalysis.setAnalyzer(
ContextCompat.getMainExecutor(previewView.context), ContextCompat.getMainExecutor(localContext),
QRCodeAnalyzer(onScanQrCode) QRCodeAnalyzer(onScanQrCode)
) )
try { try {
@ -100,7 +100,7 @@ fun QrCodeCameraView(
} else { } else {
Timber.e(e, "Use case binding failed (attempt #$attempt). Retrying after a delay...") Timber.e(e, "Use case binding failed (attempt #$attempt). Retrying after a delay...")
delay(100) delay(100)
startQRCodeAnalysis(cameraProvider, previewView, attempt + 1) startQRCodeAnalysis(cameraProvider, attempt + 1)
} }
} }
} }
@ -123,16 +123,18 @@ fun QrCodeCameraView(
AndroidView( AndroidView(
factory = { context -> factory = { context ->
val previewView = PreviewView(context) val previewView = PreviewView(context)
previewUseCase.setSurfaceProvider(previewView.surfaceProvider) previewUseCase.surfaceProvider = previewView.surfaceProvider
previewView.previewStreamState.observe(lifecycleOwner) { state -> previewView.previewStreamState.observe(lifecycleOwner) { state ->
previewView.alpha = if (state == PreviewView.StreamState.STREAMING) 1f else 0f previewView.alpha = if (state == PreviewView.StreamState.STREAMING) 1f else 0f
} }
previewView previewView
}, },
update = { previewView -> update = { previewView ->
if (renderPreview) { if (isScanning) {
cameraProvider?.let { provider -> cameraProvider?.let { provider ->
coroutineScope.launch { startQRCodeAnalysis(provider, previewView) } coroutineScope.launch {
startQRCodeAnalysis(provider)
}
} }
} else { } else {
stopQRCodeAnalysis(previewView) stopQRCodeAnalysis(previewView)
@ -150,12 +152,14 @@ fun QrCodeCameraView(
} }
} }
@Suppress("BlockingMethodInNonBlockingContext")
private suspend fun Context.getCameraProvider(): ProcessCameraProvider = private suspend fun Context.getCameraProvider(): ProcessCameraProvider =
suspendCoroutine { continuation -> suspendCoroutine { continuation ->
ProcessCameraProvider.getInstance(this).also { cameraProvider -> ProcessCameraProvider.getInstance(this).also { cameraProvider ->
cameraProvider.addListener({ cameraProvider.addListener(
continuation.resume(cameraProvider.get()) {
}, ContextCompat.getMainExecutor(this)) continuation.resume(cameraProvider.get())
},
ContextCompat.getMainExecutor(this)
)
} }
} }