我正在尝试为我的公司创建一个 QR 码扫描仪,以便在制造过程中扫描使用过的零件上的 QR 码。我目前有它,它将扫描代码并更新主要活动的文本视图,但扫描后,我必须手动点击后退按钮才能返回主要活动。另外,最终版本需要将扫描结果添加到列表中,而不是文本视图,所以我只需要它扫描一次。我试图让扫描仪在处理代码后结束活动,但由于某种原因,finish() 函数无法正常工作。
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")
}
}
}
}
}