Cyril Kym
08/01/2022, 1:51 PM@OptIn(ExperimentalPermissionsApi::class)
@Composable
fun QrCodeScanner(model: Model){
var code by remember { mutableStateOf("") }
val context = LocalContext.current
val lifecycleOwner = LocalLifecycleOwner.current
val cameraProviderFuture = remember {
ProcessCameraProvider.getInstance(context)
}
val cameraPermissionState = rememberPermissionState(Manifest.permission.CAMERA)
Column(
modifier = Modifier.fillMaxSize()
) {
if(cameraPermissionState.hasPermission){
AndroidView(factory = {context ->
val previewView = PreviewView(context)
val preview = Preview.Builder().build()
val selector = CameraSelector.Builder()
.requireLensFacing(CameraSelector.LENS_FACING_BACK)
.build()
preview.setSurfaceProvider(previewView.surfaceProvider)
val imageAnalysis = ImageAnalysis.Builder()
.setTargetResolution(
Size(
previewView.width,
previewView.height
)
)
.setBackpressureStrategy(
ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.build()
imageAnalysis.setAnalyzer(
ContextCompat.getMainExecutor(context),
QrCodeAnalyzer { result->
code = result
}
)
try {
cameraProviderFuture.get().unbindAll()
cameraProviderFuture.get().bindToLifecycle(
lifecycleOwner,
selector,
preview,
imageAnalysis
)
} catch (e: Exception){
e.printStackTrace()
}
//previewView.addView(View())
previewView
},
modifier = Modifier.fillMaxSize().weight(1f))
Column(Modifier.height(112.dp).padding(bottom = 56.dp)) {
Row(verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.height(56.dp).padding(horizontal = 12.dp)){
ConstraintLayout(Modifier
.fillMaxSize()
.background(ColorsUtil.get(FormColors.BACKGROUND_COLOR_LIGHT))
) {
val (codeText, button) = createRefs()
Text(
text = code,
textAlign = TextAlign.Center,
modifier = Modifier.constrainAs(codeText){
top.linkTo(<http://parent.top|parent.top>)
start.linkTo(parent.start)
bottom.linkTo(parent.bottom)
}
.fillMaxWidth())
Button(onClick = {
model.setValueAsText(code)
model.publishText()
}, content = {
Text("Send")
},
modifier = Modifier.constrainAs(button){
top.linkTo(<http://parent.top|parent.top>)
end.linkTo(parent.end)
bottom.linkTo(parent.bottom)
})
}
}
}
}else if(cameraPermissionState.shouldShowRationale){
Text("permission is required to access the camera")
}
else if(!cameraPermissionState.shouldShowRationale && !cameraPermissionState.hasPermission){
Text("camera permission was permanently denied, you can enable it in the app settings")
}
}
class QrCodeAnalyzer(
private val onQrCodeScanned: (String) -> Unit
): ImageAnalysis.Analyzer {
override fun analyze(imageProxy: ImageProxy) {
val mediaImage = imageProxy.image
if (mediaImage != null) {
val image = InputImage.fromMediaImage(mediaImage, imageProxy.imageInfo.rotationDegrees)
val scanner = BarcodeScanning.getClient()
scanner.process(image)
.addOnSuccessListener { barcodes ->
if(barcodes.size > 0) {
when(barcodes[0].valueType){
Barcode.TYPE_URL -> barcodes[0].rawValue?.let { onQrCodeScanned(it) }
Barcode.TYPE_ISBN -> barcodes[0].rawValue?.let { onQrCodeScanned(it) }
Barcode.TYPE_TEXT -> barcodes[0].rawValue?.let { onQrCodeScanned(it) }
Barcode.TYPE_URL -> barcodes[0].rawValue?.let { onQrCodeScanned(it) }
else -> barcodes[0].rawValue?.let { onQrCodeScanned("Type not supported") }
}
Log.d("position", barcodes[0].boundingBox.toString())
}
imageProxy.close()
scanner.close()
}
.addOnFailureListener {
it.printStackTrace()
imageProxy.close()
scanner.close()
}
}
}
}