【问题标题】:How to read barcodes with the camera on Android?如何在 Android 上使用相机读取条形码?
【发布时间】:2011-05-25 12:57:32
【问题描述】:

我希望我的应用程序能够识别相机拍摄的条形码。是否可以使用 Android SDK?

类似这样的: Barcode Scanner

【问题讨论】:

标签: android barcode barcode-scanner


【解决方案1】:

它没有内置在 SDK 中,但您可以使用 Zxing library。它是免费的、开源的,并获得 Apache 许可。

2016 年的建议是使用Barcode API,它也可以离线使用。

【讨论】:

  • 现在,它已内置在 SDK 中:developers.google.com/vision/barcodes-overview
  • 我对这个事实感到兴奋,直到我注意到它使用谷歌播放服务,对我们的仓库没有用处,没有谷歌服务,也没有外部互联网作为安全网络。
  • @dave - 问题是它需要互联网才能工作吗?谢谢。
  • @nsandersen 问题可能是播放服务要求。仓库中使用的许多设备没有消费软件,而且通常没有可用的 Play 服务。
  • 但是 google vision 提供的 BarCode Api 只检测到一些支持的特定格式,我想要一个案例,它可以从我自己的应用程序中扫描的条形码中检测到任何东西,有什么办法可以实现这个?
【解决方案2】:

2016 年更新

使用 Google Play 服务 v7.8 的 latest release,您可以访问新的 Mobile Vision API。这可能是现在实现条码扫描最方便的方式了,也是works offline

来自Android Barcode API

条形码 API 在设备上以任何方向实时检测条形码。它还可以一次检测多个条码。

它读取以下条码格式:

  • 一维条码:EAN-13、EAN-8、UPC-A、UPC-E、Code-39、Code-93、Code-128、ITF、Codabar
  • 二维条码:二维码、数据矩阵、PDF-417、AZTEC

它会自动解析二维码、数据矩阵、PDF-417 和 Aztec 值,支持以下格式:

  • 网址
  • 联系信息(VCARD 等)
  • 日历活动
  • 电子邮件
  • 电话
  • 短信
  • 国际标准书号
  • 无线网络
  • 地理位置(经纬度)
  • AAMVA 驾驶执照/身份证

【讨论】:

    【解决方案3】:

    这里是使用相机 api 的示例代码

    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    import android.util.SparseArray;
    import android.view.SurfaceHolder;
    import android.view.SurfaceView;
    import android.view.View;
    import android.widget.Button;
    import android.widget.TextView;
    import java.io.IOException;
    import com.google.android.gms.vision.CameraSource;
    import com.google.android.gms.vision.Detector;
    import com.google.android.gms.vision.Frame;
    import com.google.android.gms.vision.barcode.Barcode;
    import com.google.android.gms.vision.barcode.BarcodeDetector;
    
    public class MainActivity extends AppCompatActivity {
    
    TextView barcodeInfo;
    SurfaceView cameraView;
    CameraSource cameraSource;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        cameraView = (SurfaceView) findViewById(R.id.camera_view);
          barcodeInfo = (TextView) findViewById(R.id.txtContent);
    
    
        BarcodeDetector barcodeDetector =
                new BarcodeDetector.Builder(this)
                        .setBarcodeFormats(Barcode.CODE_128)//QR_CODE)
                        .build();
    
        cameraSource = new CameraSource
                .Builder(this, barcodeDetector)
                .setRequestedPreviewSize(640, 480)
                .build();
    
        cameraView.getHolder().addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {
    
                try {
                    cameraSource.start(cameraView.getHolder());
                } catch (IOException ie) {
                    Log.e("CAMERA SOURCE", ie.getMessage());
                }
            }
    
            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            }
    
            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                cameraSource.stop();
            }
        });
    
    
        barcodeDetector.setProcessor(new Detector.Processor<Barcode>() {
            @Override
            public void release() {
            }
    
            @Override
            public void receiveDetections(Detector.Detections<Barcode> detections) {
    
                final SparseArray<Barcode> barcodes = detections.getDetectedItems();
    
                if (barcodes.size() != 0) {
                    barcodeInfo.post(new Runnable() {    // Use the post method of the TextView
                        public void run() {
                            barcodeInfo.setText(    // Update the TextView
                                    barcodes.valueAt(0).displayValue
                            );
                        }
                    });
                }
            }
        });
    }
    }
    

    activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.gateway.cameraapibarcode.MainActivity">
    
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical">
    
        <SurfaceView
            android:layout_width="640px"
            android:layout_height="480px"
            android:layout_centerVertical="true"
            android:layout_alignParentLeft="true"
            android:id="@+id/camera_view"/>
    
        <TextView
            android:text=" code reader"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/txtContent"/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Process"
            android:id="@+id/button"
            android:layout_alignParentTop="true"
            android:layout_alignParentStart="true" />
        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/imgview"/>
    </LinearLayout>
    </RelativeLayout>
    

    build.gradle(模块:app)

    在依赖项中添加compile 'com.google.android.gms:play-services:7.8.+'

    【讨论】:

    • 可以,但是如果要扫描二维码,请使用 Barcode.QR_CODE 而不是 Barcode.CODE_128
    • 也适合在不影响性能的情况下使用所有格式。
    • 在新的 gradle (3+) 中只添加“vision”,implementation 'com.google.android.gms:play-services-vision:16.2.0'编译'com.google.android.gms:play-services:7.8.+'
    【解决方案4】:

    这是一个示例代码: 我的应用使用 ZXing Barcode Scanner。

    1. 您需要以下 2 个类: IntentIntegratorIntentResult

    2. 调用扫描仪(例如 OnClickListener、OnMenuItemSelected...)、“PRODUCT_MODE” - 它扫描标准一维条码(您可以添加更多)。:

      IntentIntegrator.initiateScan(this, 
                 "Warning", 
                 "ZXing Barcode Scanner is not installed, download?",
                 "Yes", "No",
                 "PRODUCT_MODE");
      
    3. 得到条码结果:

      public void onActivityResult(int requestCode, int resultCode, Intent intent) {  
        switch (requestCode) {
        case IntentIntegrator.REQUEST_CODE:
           if (resultCode == Activity.RESULT_OK) {
      
              IntentResult intentResult = 
                 IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
      
              if (intentResult != null) {
      
                 String contents = intentResult.getContents();
                 String format = intentResult.getFormatName();
      
                 this.elemQuery.setText(contents);
                 this.resume = false;
                 Log.d("SEARCH_EAN", "OK, EAN: " + contents + ", FORMAT: " + format);
              } else {
                 Log.e("SEARCH_EAN", "IntentResult je NULL!");
              }
           } else if (resultCode == Activity.RESULT_CANCELED) {
              Log.e("SEARCH_EAN", "CANCEL");
           }
        }
      }
      

    内容保存条形码编号

    【讨论】:

      【解决方案5】:

      模块应用:

      implementation 'com.google.zxing:core:3.2.1'
      
      implementation 'com.journeyapps:zxing-android-embedded:3.2.0@aar'
      

      AndroidManifest.xml

      <uses-permission android:name="android.permission.CAMERA" />
      <uses-feature android:name="android.hardware.camera" />
      <uses-feature android:name="android.hardware.camera.autofocus"/>
      

      MainActivity.java

      public class MainActivity extends AppCompatActivity {
      
          Button BarCode;
      
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
      
              BarCode = findViewById(R.id.button_barcode);
              final Activity activity = this;
      
              BarCode.setOnClickListener(new View.OnClickListener() {
                  @Override
                  public void onClick(View v) {
      
                      IntentIntegrator intentIntegrator = new IntentIntegrator(activity);
                      intentIntegrator.setDesiredBarcodeFormats(intentIntegrator.ALL_CODE_TYPES);
                      intentIntegrator.setBeepEnabled(false);
                      intentIntegrator.setCameraId(0);
                      intentIntegrator.setPrompt("SCAN");
                      intentIntegrator.setBarcodeImageEnabled(false);
                      intentIntegrator.initiateScan();
                  }
              });
          }
      
          @Override
          protected void onActivityResult(int requestCode, int resultCode, Intent data) {
      
              IntentResult Result = IntentIntegrator.parseActivityResult(requestCode , resultCode ,data);
              if(Result != null){
                  if(Result.getContents() == null){
                      Log.d("MainActivity" , "cancelled scan");
                      Toast.makeText(this, "cancelled", Toast.LENGTH_SHORT).show();
                  }
                  else {
                      Log.d("MainActivity" , "Scanned");
                      Toast.makeText(this,"Scanned -> " + Result.getContents(), Toast.LENGTH_SHORT).show();
                  }
              }
              else {
                  super.onActivityResult(requestCode , resultCode , data);
              }
          }
      }
      

      【讨论】:

      • 这是一个被严重低估的答案。非常感谢!
      【解决方案6】:

      你也可以使用barcodefragmentlibbarcodefragmentlib,它是zxing的一个扩展,但是提供了条码扫描作为片段库,所以可以很容易地集成。

      这里是使用库的支持documentation

      【讨论】:

      【解决方案7】:

      借助 Google Firebase ML Kit 的条形码扫描 API,您可以读取使用大多数标准条形码格式编码的数据。

      https://firebase.google.com/docs/ml-kit/read-barcodes?authuser=0

      您可以点击此链接高效读取条形码。

      【讨论】:

        【解决方案8】:

        构建条码扫描功能分为两部分,一是使用相机捕获条码图像,二是从图像中提取条码值。

        可以使用相机应用从您的应用中捕获条形码图像,并且可以使用 Firebase 机器学习套件条形码扫描 API 提取条形码值。

        这是一个示例应用 https://www.zoftino.com/android-barcode-scanning-example

        【讨论】:

          【解决方案9】:

          Firebase 条码扫描 API 已弃用。

          您可以使用 Googles ML Kit 来识别和解码条形码 没有火力基地的帮助。

          在你的 gradle(app) 中添加

          implementation 'com.google.mlkit:barcode-scanning:17.1.1'
          

          更多详情请查看official guideline

          【讨论】:

            【解决方案10】:

            我对 parseActivityForResult 参数有疑问。我得到了这个工作:

            package JMA.BarCodeScanner;
            
            import android.app.Activity;
            import android.content.Intent;
            import android.os.Bundle;
            import android.util.Log;
            import android.view.View;
            import android.widget.Button;
            import android.widget.TextView;
            
            public class JMABarcodeScannerActivity extends Activity {
            
                Button captureButton;
                TextView tvContents;
                TextView tvFormat;
                Activity activity;
            
                @Override
                public void onCreate(Bundle savedInstanceState) {
                    super.onCreate(savedInstanceState);
                    setContentView(R.layout.main);
            
                    activity = this;
                    captureButton = (Button)findViewById(R.id.capture);
                    captureButton.setOnClickListener(listener);
                    tvContents = (TextView)findViewById(R.id.tvContents);
                    tvFormat = (TextView)findViewById(R.id.tvFormat);
                }
            
                public void onActivityResult(int requestCode, int resultCode, Intent intent) 
                {  
                    switch (requestCode) 
                    {
                        case IntentIntegrator.REQUEST_CODE:
                        if (resultCode == Activity.RESULT_OK) 
                        {
                            IntentResult intentResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
            
                            if (intentResult != null) 
                            {
                               String contents = intentResult.getContents();
                               String format = intentResult.getFormatName();
                               tvContents.setText(contents.toString());
                               tvFormat.setText(format.toString());
            
                               //this.elemQuery.setText(contents);
                               //this.resume = false;
                               Log.d("SEARCH_EAN", "OK, EAN: " + contents + ", FORMAT: " + format);
                            } else {
                                Log.e("SEARCH_EAN", "IntentResult je NULL!");
                            }
                        } 
                        else if (resultCode == Activity.RESULT_CANCELED) {
                            Log.e("SEARCH_EAN", "CANCEL");
                        }
                    }
                }
            
                private View.OnClickListener listener = new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                         IntentIntegrator integrator = new IntentIntegrator(activity);
                         integrator.initiateScan();
                    }
                };
            }
            

            活动布局:

            <?xml version="1.0" encoding="utf-8"?>
            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:orientation="vertical"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent">
                <Button
                    android:id="@+id/capture"
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:text="Take a Picture"/>
            
                <TextView xmlns:android="http://schemas.android.com/apk/res/android"
                    android:id="@+id/tvContents"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"/>
            
                <TextView xmlns:android="http://schemas.android.com/apk/res/android"
                    android:id="@+id/tvFormat"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"/>
            </LinearLayout>
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2017-11-09
              • 2012-01-27
              • 1970-01-01
              • 1970-01-01
              • 2011-06-16
              • 1970-01-01
              相关资源
              最近更新 更多