I'm trying to create a QR code scanner for my company to scan QR codes on used parts during manufacturing. I currently have it where it will scan the code and update text views on the main activity, but after scanning, I have to manually hit the back button to get back to the main activity. also, the final version needs to add the scan results to a list, instead of a text view, so I need it to scan only one time. I'm trying to get the scanner to end the activity once it processes the code, but the finish() function isn't working for some reason.
class ScanActivity : AppCompatActivity() {
lateinit var scanView: TextureView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_scan)
scanView = findViewById(R.id.scanView)
scanView.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
updateTransform()
}
if (allPermissionsGranted()) {
scanView.post { startCamera() }
} else {
ActivityCompat.requestPermissions(
this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS)
}
}
private fun startCamera() {
val previewConfig = PreviewConfig.Builder().apply {
setTargetResolution(Size(800, 640))
}.build()
val preview = Preview(previewConfig)
preview.setOnPreviewOutputUpdateListener {
val parent = scanView.parent as ViewGroup
parent.removeView(scanView)
parent.addView(scanView, 0)
scanView.surfaceTexture = it.surfaceTexture
updateTransform()
}
val analyzerConfig = ImageAnalysisConfig.Builder().apply {
setImageReaderMode(
ImageAnalysis.ImageReaderMode.ACQUIRE_LATEST_IMAGE)
}.build()
val analyzerUseCase = ImageAnalysis(analyzerConfig).apply {
setAnalyzer(executor,QRCodeAnalyzer())
}
CameraX.bindToLifecycle(this, preview,analyzerUseCase)
}
private fun updateTransform() {
val matrix = Matrix()
val centerX = scanView.width / 2f
val centerY = scanView.height / 2f
val rotationDegrees = when (scanView.display.rotation) {
Surface.ROTATION_0 -> 0
Surface.ROTATION_90 -> 90
Surface.ROTATION_180 -> 180
Surface.ROTATION_270 -> 270
else -> return
}
matrix.postRotate(-rotationDegrees.toFloat(), centerX, centerY)
scanView.setTransform(matrix)
}
private val executor = Executors.newSingleThreadExecutor()
private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all {
ContextCompat.checkSelfPermission(
baseContext, it) == PackageManager.PERMISSION_GRANTED
}
override fun onRequestPermissionsResult(
requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
if (requestCode == REQUEST_CODE_PERMISSIONS) {
if (allPermissionsGranted()) {
scanView.post { startCamera() }
} else {
Toast.makeText(this,
"Permissions not granted by the user.",
Toast.LENGTH_SHORT).show()
finish()
}
}
}
private class QRCodeAnalyzer : ImageAnalysis.Analyzer {
private fun degreesToFirebaseRotation(degrees: Int): Int = when (degrees) {
0 -> FirebaseVisionImageMetadata.ROTATION_0
90 -> FirebaseVisionImageMetadata.ROTATION_90
180 -> FirebaseVisionImageMetadata.ROTATION_180
270 -> FirebaseVisionImageMetadata.ROTATION_270
else -> throw Exception("Rotation must be 0, 90, 180, or 270.")
}
@SuppressLint("SetTextI18n")
override fun analyze(imageProxy: ImageProxy?, degrees: Int) {
val mediaImage = imageProxy?.image
val imageRotation = degreesToFirebaseRotation(degrees)
if (mediaImage!=null) {
val image = FirebaseVisionImage.fromMediaImage(mediaImage, imageRotation)
val options = FirebaseVisionBarcodeDetectorOptions.Builder()
.setBarcodeFormats(FirebaseVisionBarcode.FORMAT_QR_CODE).build()
val detector = FirebaseVision.getInstance().getVisionBarcodeDetector(options)
val result = detector.detectInImage(image)
.addOnSuccessListener { barcodes ->
var code = ""
for (barcode in barcodes) {
code = barcode.rawValue.toString()
}
Log.i("STAGE ONE COMPLETE!!!", code)
//Start breaking down QR scan into Part Number and Lot Number
var partNumberText = ""
var partNumber: Pattern = Pattern.compile("MCU-(.*?) ")
var mPN: Matcher = partNumber.matcher(code)
while (mPN.find()) {
partNumberText = mPN.group(1)
MainActivity.partNumberTextView.text = "Part Number: $partNumberText"
}
if (code.length > 47) {
var lotNumberSubText = code.substring(0, 47)
var lotNumberText = ""
var lotNumber: Pattern = Pattern.compile("$lotNumberSubText(.*?) ")
var mLN: Matcher = lotNumber.matcher(code)
while (mLN.find()) {
lotNumberText = mLN.group(1)
MainActivity.lotNumberTextView.text = "Lot Number: $lotNumberText"
}
}
finish()
}
.addOnFailureListener {
Log.i("FAILURE", "Scan Failed")
}
}
}
}
}
You can try this. Add constructor to QRCodeAnalyzer class:
private class QRCodeAnalyzer constructor(val activity: Activity) : ImageAnalysis.Analyzer
You can call:
activity.finish()
and setAnalyzer:
setAnalyzer(executor,QRCodeAnalyzer(this))