如何使条码扫描仪只扫描一次(谷歌移动视觉 API)?

Posted

技术标签:

【中文标题】如何使条码扫描仪只扫描一次(谷歌移动视觉 API)?【英文标题】:How to make Barcode Scanner only scan once (Google Mobile Vision API)? 【发布时间】:2018-07-05 07:43:51 【问题描述】:

我正在使用谷歌移动视觉 api 开发一个具有条形码扫描仪的应用程序。我应该只能在 ScannerClassy.java 中扫描一次并将结果保存在 MainActivity 中。问题是当我扫描条形码时,它打开 MainActivity.java 5-7 次。我尝试使用 camerasource.release() 但它不起作用。

ScannerClass.java

    import com.example.MashapeHello.R;
    import com.google.android.gms.vision.Detector;
    import android.Manifest;
    import android.app.Activity;
    import android.content.Intent;
    import android.content.pm.PackageManager;
    import android.os.Looper;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.support.v4.app.ActivityCompat;
    import android.util.Log;
    import android.util.SparseArray;
    import android.view.SurfaceHolder;
    import android.view.SurfaceView;
    import android.widget.TextView;

    import com.google.android.gms.vision.CameraSource;
    import com.google.android.gms.vision.barcode.Barcode;
    import com.google.android.gms.vision.barcode.BarcodeDetector;
    import java.io.IOException;


    public class ScannerClass extends AppCompatActivity implements Detector.Processor 
        private TextView textView;
        private SurfaceView surfaceView;
        private BarcodeDetector barcodeDetector;
        private CameraSource cameraSource;
        @Override
        protected void onCreate(Bundle savedInstanceState) 
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            surfaceView = (SurfaceView) this.findViewById(R.id.surfaceView);

        barcodeDetector = new BarcodeDetector.Builder(this).setBarcodeFormats(Barcode.ALL_FORMATS).build();
        barcodeDetector.setProcessor(this);

        cameraSource = new CameraSource.Builder(getApplicationContext(), barcodeDetector).
                setRequestedPreviewSize(1024,1024).setAutoFocusEnabled(true)
                .build();

        final Activity activity = this;

        surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() 
            @Override
            public void surfaceCreated(SurfaceHolder holder) 
                try
                    if(ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)
                        ActivityCompat.requestPermissions(activity, new String[]Manifest.permission.CAMERA,1024);
                        return;
                    
                    cameraSource.start(surfaceView.getHolder());
                 catch (IOException ie)
                    Log.e("Camera start problem", ie.getMessage());
                
            

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) 

            

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) 
                cameraSource.stop();
            
        );
        


        @Override
        public void release()

        


        @Override
        public void receiveDetections(Detector.Detections detections) 
        final SparseArray<Barcode> barcodes = detections.getDetectedItems();
        if (barcodes.size() != 0) 
            final StringBuilder sb = new StringBuilder();
            for (int i = 0; i < barcodes.size(); ++i) 
                sb.append(barcodes.valueAt(i).rawValue).append("\n");
            
            Intent intent = new Intent(this, MainActivity.class);
            intent.putExtra("barcodevalue", sb.toString());
            startActivity(intent);
            cameraSource.release();


        
    

【问题讨论】:

【参考方案1】:

您可以通过创建自己的条形码检测器类来解决此问题,该类在内部使用 BarcodeDetector 类。这是一个简单的例子:

public class LimitToOneBarcodeDetector extends Detector<Barcode> 

     private BarcodeDetector internalDetector;

     public LimitToOneBarcodeDetector(Context context) 
         this.internalDetector = new BarcodeDetector.Builder(App.getContext())
            .setBarcodeFormats(Barcode.ALL_FORMATS)
            .build();
    

    @Override
    public SparseArray<Barcode> detect(Frame frame) 

        SparseArray<Barcode> detected = this.internalDetector.detect(frame);

        if (detected == null) 
            // Nothing detected, kick out an empty array 
            return new SparseArray<>();
        

        if (detected.size() == 0) 
            // Detected size = 0 , kick out an empty array
            return new SparseArray<>();
        

        if (detected.size() > 1) 
            // Detected more than one barcode, kick out an empty array
            return new SparseArray<>();
        

        // If we're here, there is only one barcode, return the array
        return detected;

然后您只需在 Activity 中替换此行:

barcodeDetector = new BarcodeDetector.Builder(this).setBarcodeFormats(Barcode.ALL_FORMATS).build();

有了这个或类似的东西:

barcodeDetector = new LimitToOneBarcodeDetector(this);

【讨论】:

【参考方案2】:

这个问题是,你不断用startActivity(intent);开始新的活动

而不是用检测结果结束当前活动...

最好以startActivityForResult() 开头ScannerClass 并传回所有条形码:

if (barcodes.size() > 0) 
    cameraSource.release();
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < barcodes.size(); ++i) 
        sb.append(barcodes.valueAt(i).rawValue).append("\n");
    
    Intent data = new Intent();
    data.putExtra("barcodes", sb.toString());
    this.setResult(AppCompatActivity.RESULT_OK, data);
    this.finish();

然后可以在方法MainActivity.onActivityResult() 中处理这些。

【讨论】:

以上是关于如何使条码扫描仪只扫描一次(谷歌移动视觉 API)?的主要内容,如果未能解决你的问题,请参考以下文章

条码扫描不适用于视觉 API

是否可以使用 google vision api 一次扫描 10 张图像 ocr?到目前为止只做了1

phonegap 条码扫描仪:如何一次进行多次扫描

如何在条码扫描仪的移动 web 应用程序中集成 Phonegap 插件?

odoo移动端使用条码扫描打不开相机

谷歌身份验证器扫描时条码无效