本文介绍了使用Android/Kotlin QR扫描仪应用程序和最新版本的Google ML Kit扫描条形码崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试制作一个读取QR图像并从图像中获取数据的应用程序.我正在使用最新版的Google机器学习套件来扫描条形码,并遵循有关此 https://developers.google.com/ml-kit/vision/barcode-scanning/android .

I am trying to make an app which reads QR images and get the data from the image. I am using the latest version of the google machine learning kit for scan barcodes and following the documentation about this https://developers.google.com/ml-kit/vision/barcode-scanning/android.

但是,在我运行该应用程序的那一刻,我遇到了以下崩溃:

However, at the moment that I run the app, I am getting the following crash:

QR扫描仪应用出现图像错误

我不知道这是怎么回事,因为我有这种功能的新功能.这是我现在正在使用的代码:

I have no idea what's going on with this due I a new with this kind of functionality. This is the code that I am using right now:

package com.google.firebase.codelab.barcode_scanning

import android.os.Bundle
import android.util.Log
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.camera.core.*
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.mlkit.vision.barcode.Barcode
import com.google.mlkit.vision.barcode.BarcodeScannerOptions
import com.google.mlkit.vision.barcode.BarcodeScanning
import com.google.mlkit.vision.common.InputImage
import kotlinx.android.synthetic.main.activity_main.*
import java.util.concurrent.Executors

class BarcodeScannerActivity : AppCompatActivity() {

    private val qrList = arrayListOf<QrCode>()
    val adapter = QrCodeAdapter(qrList)
    private val executor = Executors.newSingleThreadExecutor()
    private val options = BarcodeScannerOptions.Builder()
            .setBarcodeFormats(
                    Barcode.FORMAT_QR_CODE)
            .build()
    private val scanner = BarcodeScanning.getClient(options)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        rvQrCode.layoutManager = LinearLayoutManager(this)
        rvQrCode.adapter = adapter


        val imageAnalysisConfig = ImageAnalysisConfig.Builder()
                .setImageReaderMode(ImageAnalysis.ImageReaderMode.ACQUIRE_LATEST_IMAGE)
                .build()

        val imageAnalysis = ImageAnalysis(imageAnalysisConfig)

        val previewConfig = PreviewConfig.Builder().apply {
            setLensFacing(CameraX.LensFacing.BACK)
        }.build()

        val preview = Preview(previewConfig)

        preview.setOnPreviewOutputUpdateListener {
            val parent = cameraView.parent as ViewGroup
            parent.removeView(cameraView)
            cameraView.surfaceTexture = it.surfaceTexture
            parent.addView(cameraView, 0)
        }

        val analyzer = ImageAnalysis.Analyzer{ imageProxy: ImageProxy?, rotationDegrees: Int ->
            imageProxy?.let {
                it.image?.let { image ->
                    val inputImage = InputImage.fromMediaImage(image, rotationDegrees)
                    runBarcodeScanner(inputImage)
                    //image.close()
                }
            }
            imageProxy?.close()
        }

        imageAnalysis.setAnalyzer(executor, analyzer)
        CameraX.bindToLifecycle(this, preview, imageAnalysis)
    }


    private fun runBarcodeScanner(image: InputImage) {
        // [START run_detector]
        scanner.process(image)
                .addOnSuccessListener { barcodes ->
                    // Task completed successfully
                    // [START_EXCLUDE]
                    // [START get_barcodes]
                    Log.e("SUCCESS..","OK")
                    for (barcode in barcodes) {
                        val bounds = barcode.boundingBox
                        val corners = barcode.cornerPoints

                        val rawValue = barcode.rawValue

                        val valueType = barcode.valueType
                        // See API reference for complete list of supported types
                        when (valueType) {
                            Barcode.TYPE_WIFI -> {
                                val ssid = barcode.wifi!!.ssid
                                val password = barcode.wifi!!.password
                                val type = barcode.wifi!!.encryptionType
                            }
                            Barcode.TYPE_URL -> {
                                val title = barcode.url!!.title
                                val url = barcode.url!!.url
                            }
                        }
                    }
                    // [END get_barcodes]
                    // [END_EXCLUDE]
                }
                .addOnFailureListener {
                    // Task failed with an exception
                    // ...
                    Log.e("ERROR..","ERROR")
                }
        // [END run_detector]
    }
}

布局xml文件如下:

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextureView
        android:id="@+id/cameraView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:adjustViewBounds="true" />

    <FrameLayout
        android:id="@+id/framePreview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone">

        <ImageView
            android:id="@+id/imagePreview"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="centerCrop" />

        <ImageButton
            android:id="@+id/btnRetry"
            android:layout_width="120dp"
            android:layout_height="120dp"
            android:layout_gravity="center"
            android:background="@null"
            android:scaleType="centerCrop"
            android:src="@drawable/ic_refresh" />

    </FrameLayout>

    <LinearLayout
        android:id="@+id/layout_bottom_sheet"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#FAFAFA"
        android:orientation="vertical"
        app:layout_behavior="@string/bottom_sheet_behavior">

        <ProgressBar
            android:id="@+id/progressBar"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:indeterminate="true"
            android:visibility="gone" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="16dp"
            android:text="Detected Barcodes"
            android:textSize="24sp" />

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/rvQrCode"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:paddingLeft="8dp"
            android:paddingRight="8dp" />

    </LinearLayout>

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab_take_photo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        android:src="@drawable/ic_camera"
        app:backgroundTint="@color/colorPrimary"
        app:fabSize="normal"
        app:layout_anchor="@id/layout_bottom_sheet"
        app:layout_anchorGravity="end"
        app:rippleColor="@color/colorAccent" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

我的应用评分文件是这样的:

And my app grade file is like this:

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.google.firebase.codelab.barcode_scanning"
        minSdkVersion 21
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

androidExtensions {
    experimental = true
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'androidx.appcompat:appcompat:1.0.0-rc02'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.13'
    androidTestImplementation 'androidx.test:runner:1.3.0-rc01'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0-rc01'
    implementation 'com.otaliastudios:cameraview:1.6.0'
    implementation "com.google.android.material:material:1.3.0-alpha01"
    implementation "androidx.cardview:cardview:1.0.0"
    // Barcode model
    implementation 'com.google.mlkit:barcode-scanning:16.0.1'
    implementation 'androidx.camera:camera-core:1.0.0-alpha06'
    implementation 'androidx.camera:camera-camera2:1.0.0-alpha06'
}

预先感谢任何人都可以给我的帮助.

Thanks in advance for any help that anyone can give me.

推荐答案

因此,如果我们看一下代码:

So if we look at the code:

  1. 从ImageProxy创建InputImage
  2. scanner.process(image).addWhateverListener(etc etc)但不是onComplete
  3. imageProxy.close

为什么这不起作用?步骤2是异步的,因此执行之前需要花费一小部分时间,但与此同时,步骤3会启动并清除图像-没有要检测的图像.解决方案是使用 addOnCompleteListener 关闭图像:

Why would this not work? Step 2 is async so it takes say a fraction of time before it is executed but in the meantime, step 3 kicks in and clear the image - no image to detect. The solution is to use addOnCompleteListener to close the image:

    scanner.process(image)
        .addOnFailureListener { // Some code}
        .addOnSuccessListener { // Some more code}
        .addOnCompleteListener {
            // Close the image
            imageProxy.close()}

顺便说一句,这也是我第一次来,我们正在考虑添加比图像已经关闭"更好的调试消息.

BTW this got me the first time too and we are thinking about adding better debug message than "Image is already close".

这篇关于使用Android/Kotlin QR扫描仪应用程序和最新版本的Google ML Kit扫描条形码崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-28 22:58