xsheru
xsheru

Reputation: 497

QR Scanner Camera Preview stops and starts again and then shuts down when reads qr code

I have implemented QR Scanner inside my app. I used Firebase MLKit as well as tried Zxing Scanner.

I start new activity where qr scanner runs. Once it detects valid qr code it finishes the scanner activity and send the result back to previous activity.

Everything works without any errors.

But there is small bug probably with Camera in android.

After getting valid qr code camera shuts off for a second then starts again and after a second or two shuts down and then activity gets finishes and return result to previous activity.

I have tried Camera, Camera2, Zxing Core, MLKit with all possible combinations. Everytime same thing occurs.

I also tried couple of Github Repos MLKitQRScanner, KotlinFirebaseMLKitQRRealtimeDemo, QRCodeCameraX, QRScannerCameraX

This is using CameraX but I also tried the older camera apis in android with same result

I think the problem is with camera preview but I tried camera2 and cameraX api. both gives same output. So it is probably something in code.

ACTIVITY

var analyzerHandler: Handler? = null
var analysis: ImageAnalysis? = null

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_scanner_x)

    context = this

    Dexter.withActivity(this)
        .withPermissions(Manifest.permission.CAMERA)
        .withListener(object : MultiplePermissionsListener {
            override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
                textureView.post {
                    val metrics = DisplayMetrics().also { textureView.display.getRealMetrics(it) }
                    val screenAspectRatio = Rational(metrics.widthPixels, metrics.heightPixels)

                    val previewConfig = PreviewConfig.Builder().apply {
                        setTargetAspectRatio(screenAspectRatio)
                        setTargetRotation(textureView.display.rotation)
                        setLensFacing(CameraX.LensFacing.BACK)
                    }.build()

                    val analysisConfig = ImageAnalysisConfig.Builder().apply {
                        setImageReaderMode(ImageAnalysis.ImageReaderMode.ACQUIRE_LATEST_IMAGE)
                        val analyzerThread = HandlerThread("BarcodeFirebaseAnalyzer").apply { start() }
                        analyzerHandler = Handler(analyzerThread.looper)
                        setCallbackHandler(analyzerHandler!!)
                        setTargetAspectRatio(screenAspectRatio)
                        setTargetRotation(textureView.display.rotation)
                        setLensFacing(CameraX.LensFacing.BACK)
                    }.build()

                    val preview = AutoFitPreviewBuilder.build(previewConfig, textureView)
                    analysis = ImageAnalysis(analysisConfig)

                    val googlePlayServicesAvailable = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context)
                    if (googlePlayServicesAvailable == ConnectionResult.SUCCESS) {
                        analysis!!.analyzer = BarcodeFirebaseAnalyzer { barcode ->
                            toAddAuth(barcode) //THIS RUNS ONCE VALID QR CODE IS THERE. ITS JUST INTENT TO SEND BACK THE RESULT FOR startActivityForResult
                        }
                    } else {
                        analysis!!.analyzer = BarcodeZxingAnalyzer { barcode ->
                            toAddAuth(barcode)
                        }
                    }

                    CameraX.bindToLifecycle(this@ScannerX, preview, analysis)
                }
            }

            override fun onPermissionRationaleShouldBeShown(permissions: MutableList<PermissionRequest>?, token: PermissionToken?) {
                //
            }
        }).check()
}


override fun onResume() {
    super.onResume()
    textureView.postDelayed({
        textureView.systemUiVisibility = flagsFullscreen
    }, immersiveFlagTimeout)
}

override fun onDestroy() {
    analyzerHandler?.removeCallbacksAndMessages(null)
    analyzerHandler?.looper?.quitSafely()
    analysis?.analyzer = null
    super.onDestroy()
}

I just need to close camera and activity once analyzer gets valid code

ALSO IF I PRESS BACK BUTTON ON SCANNER ACTIVITY CAMERA PREVIEW GOES OFF AND THEN TURN BACK ON AND HAVE TO PRESS THAT BACK BUTTON AGAIN TO FINISH THIS SCANNER ACTIVITY.

SO ITS NOT JUST BARCODE LISTENER. IT HAPPENS WITH BACK BUTTON AS WELL.

Upvotes: 1

Views: 1604

Answers (2)

xsheru
xsheru

Reputation: 497

[SOLVED]

I dont know exactly what causing this issue but somehow this whole thing doesn't work inside an Activity .

CameraX.bindToLifecycle have some strange bug which messing up with Activity LifeCycle.

Implementing everything inside Fragment does solve the issue. Only thing is have to keep all Camera related stuff inside fragment. When its time to finish the activity and return scan results to previous activity better do it in Activity hosting the fragment.

Upvotes: 0

ralphgabb
ralphgabb

Reputation: 10528

Here's a gist of QR Code, let me know if this helps you

// QR Code - XZing
implementation 'com.dlazaro66.qrcodereaderview:qrcodereaderview:2.0.3'

QR Code Gist File

Don't forget to add the permission

   <uses-permission android:name="android.permission.CAMERA"/>

Cheers

Upvotes: 2

Related Questions