Sreeramktm 27
07/28/2023, 7:32 AM@Composable
private fun RealDeviceCamera(
camera: AVCaptureDevice,
onQrCodeScanned: (String) -> Boolean
) {
val capturePhotoOutput = remember { AVCapturePhotoOutput() }
var actualOrientation by remember {
mutableStateOf(
AVCaptureVideoOrientationPortrait
)
}
val captureSession: AVCaptureSession = remember {
AVCaptureSession().also { captureSession ->
captureSession.sessionPreset = AVCaptureSessionPresetPhoto
val captureDeviceInput: AVCaptureDeviceInput =
deviceInputWithDevice(device = camera, error = null)!!
captureSession.addInput(captureDeviceInput)
captureSession.addOutput(capturePhotoOutput)
//Initialize an AVCaptureMetadataOutput object and set it as the output device to the capture session.
val metadataOutput = AVCaptureMetadataOutput()
if (captureSession.canAddOutput(metadataOutput)) {
captureSession.addOutput(metadataOutput)
metadataOutput.setMetadataObjectsDelegate(objectsDelegate = object : NSObject(),
AVCaptureMetadataOutputObjectsDelegateProtocol {
override fun captureOutput(
output: AVCaptureOutput,
didOutputMetadataObjects: List<*>,
fromConnection: AVCaptureConnection
) {
didOutputMetadataObjects.firstOrNull()?.let { metadataObject ->
val readableObject =
metadataObject as? AVMetadataMachineReadableCodeObject
if (readableObject?.type == AVMetadataObjectTypeQRCode) {
val code = readableObject?.stringValue ?: ""
if (onQrCodeScanned.invoke(code)) {
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
captureSession.stopRunning()
}
}
}
}
}, queue = dispatch_get_main_queue())
metadataOutput.metadataObjectTypes = listOf(AVMetadataObjectTypeQRCode)
/*
Commenting this line as this provides support for many ISO Image formats.
Later if needed to extend QR scanner to support other formats comment this line and uncomment the above line.
*/
// metadataOutput.metadataObjectTypes = metadataOutput.availableMetadataObjectTypes()
}
}
}
val cameraPreviewLayer = remember {
AVCaptureVideoPreviewLayer(session = captureSession)
}
DisposableEffect(Unit) {
class OrientationListener : NSObject() {
@Suppress("UNUSED_PARAMETER")
@ObjCAction
fun orientationDidChange(arg: NSNotification) {
val cameraConnection = cameraPreviewLayer.connection
if (cameraConnection != null) {
actualOrientation = when (UIDevice.currentDevice.orientation) {
UIDeviceOrientation.UIDeviceOrientationPortrait ->
AVCaptureVideoOrientationPortrait
UIDeviceOrientation.UIDeviceOrientationLandscapeLeft ->
AVCaptureVideoOrientationLandscapeRight
UIDeviceOrientation.UIDeviceOrientationLandscapeRight ->
AVCaptureVideoOrientationLandscapeLeft
UIDeviceOrientation.UIDeviceOrientationPortraitUpsideDown ->
AVCaptureVideoOrientationPortrait
else -> cameraConnection.videoOrientation
}
cameraConnection.videoOrientation = actualOrientation
}
capturePhotoOutput.connectionWithMediaType(AVMediaTypeVideo)
?.videoOrientation = actualOrientation
}
}
val listener = OrientationListener()
val notificationName = UIDeviceOrientationDidChangeNotification
NSNotificationCenter.defaultCenter.addObserver(
observer = listener,
selector = NSSelectorFromString(
OrientationListener::orientationDidChange.name + ":"
),
name = notificationName,
`object` = null
)
onDispose {
NSNotificationCenter.defaultCenter.removeObserver(
observer = listener,
name = notificationName,
`object` = null
)
}
}
Box(modifier = Modifier.fillMaxSize()) {
UIKitView(
modifier = Modifier.fillMaxSize(),
factory = {
val cameraContainer = UIView()
cameraContainer.layer.addSublayer(cameraPreviewLayer)
cameraPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
captureSession.startRunning()
cameraContainer
},
onResize = { view: UIView, rect: CValue<CGRect> ->
CATransaction.begin()
CATransaction.setValue(true, kCATransactionDisableActions)
view.layer.setFrame(rect)
cameraPreviewLayer.setFrame(rect)
CATransaction.commit()
},
)
}
}
Dima Avdeev
07/31/2023, 10:49 AM