zoukankan      html  css  js  c++  java
  • Android ZXing 二维码、条形码扫描介绍

    最近公司的Android项目需要用到摄像头做条码或二维码的扫描,Google一下,发现一个开源的 ZXing项目。它提供二维码和条形码的扫描。扫描条形码就是直接读取条形码的内容,扫描二维码是按照自己指定的二维码格式进行编码和解码。

    1.什么是二维码和条形码?

                           

    二维条形码最早发明于日本,它是用某种特定的几何图形按一定规律在平面(二维方向上)分布的黑白相间的图形记录数据符号信息的,在代码编制上巧妙地利用构成计算机内部逻辑基础的“0”、“1”比特流的概念,使用若干个与二进制相对应的几何形体来表示文字数值信息,通过图象输入设备或光电扫描设备自动识读以实现信息自动处理。它具有条码技术的一些共性:每种码制有其特定的字符集;每个字符占有一定的宽度;具有一定的校验功能等。同时还具有对不同行的信息自动识别功能、及处理图形旋转变化等特点。

    条形码(barcode)是将宽度不等的多个黑条和空白,按照一定的编码规则排列,用以表达一组信息的图形标识符。常见的条形码是由反射率相差很大的黑条(简称条)和白条(简称空)排成的平行线图案。条形码可以标出物品的生产国、制造厂家、商品名称、生产日期、图书分类号、邮件起止地点、类别、日期等许多信息,因而在商品流通、图书管理、邮政管理、银行系统等许多领域都得到广泛的应用。

    2.ZXing基本介绍

    ZXing是一个开源Java类库用于解析多种格式的条形码和二维码.官网:http://code.google.com/p/zxing/

    截止目前为止最新版本提供以下编码格式的支持:

    • UPC-A and UPC-E
    • EAN-8 and EAN-13
    • Code 39
    • Code 93
    • Code 128
    • QR Code
    • ITF
    • Codabar
    • RSS-14 (all variants)
    • Data Matrix
    • PDF 417 ('alpha' quality)
    • Aztec ('alpha' quality)

    同时官网提供了 Android、cpp、C#、iPhone、j2me、j2se、jruby、objc、rim、symbian等多种应用的类库,具体详情可以参考下载的源码包中。

    3.Android端编码演示

    这里使用的ZXing是经过简化版的,去除了一些一般使用不必要的文件,项目工程和效果截图如下:

       

    其中encoding包是在原基础上加上去的,功能是根据传入的字符串来生成二维码图片,返回一个Bitmap,其余的包是ZXing项目自带的。另外对扫描界面的布局也进行了修改,官方的扫描界面是横向的,我改成了纵向的,并加入了顶部的Tab和取消按钮(camera.xml),另外还需要的一些文件是colors.xml、ids.xml,这些都是原本ZXing项目中自带的,最后就是libs下面的jar包。

    接下来看如何使用,首先是把ZXing项目中的一些文件拷贝到我们自己的项目中,然后在Mainifest文件中进行配置权限:

    1. <uses-permissionandroid:name="android.permission.VIBRATE"/> 
    2. <uses-permissionandroid:name="android.permission.CAMERA"/> 
    3. <uses-featureandroid:name="android.hardware.camera"/> 
    4. <uses-featureandroid:name="android.hardware.camera.autofocus"/> 

    还有就是扫描界面Activity的配置:

    1. <activity 
    2.          android:configChanges="orientation|keyboardHidden" 
    3.          android:name="com.zxing.activity.CaptureActivity" 
    4.          android:screenOrientation="portrait" 
    5.          android:theme="@android:style/Theme.NoTitleBar.Fullscreen" 
    6.          android:windowSoftInputMode="stateAlwaysHidden"> 
    7. </activity> 

    接下来是我自己项目的布局文件:

    1. <?xmlversion="1.0"encoding="utf-8"?> 
    2. <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" 
    3.     android:layout_width="fill_parent" 
    4.     android:layout_height="fill_parent" 
    5.     android:background="@android:color/white" 
    6.     android:orientation="vertical"> 
    7.  
    8.     <Button 
    9.         android:id="@+id/btn_scan_barcode" 
    10.         android:layout_width="fill_parent" 
    11.         android:layout_height="wrap_content" 
    12.         android:layout_marginTop="30dp" 
    13.         android:text="Open camera"/> 
    14.      
    15.     <LinearLayout  
    16.         android:orientation="horizontal" 
    17.         android:layout_marginTop="10dp" 
    18.         android:layout_width="fill_parent" 
    19.         android:layout_height="wrap_content"> 
    20.          
    21.         <TextView  
    22.         android:layout_width="wrap_content" 
    23.         android:layout_height="wrap_content" 
    24.         android:textColor="@android:color/black" 
    25.         android:textSize="18sp" 
    26.         android:text="Scan result:"/> 
    27.          
    28.         <TextView  
    29.         android:id="@+id/tv_scan_result" 
    30.         android:layout_width="fill_parent" 
    31.         android:textSize="18sp" 
    32.         android:textColor="@android:color/black" 
    33.         android:layout_height="wrap_content"/> 
    34.     </LinearLayout> 
    35.      
    36.     <EditText  
    37.         android:id="@+id/et_qr_string" 
    38.         android:layout_width="fill_parent" 
    39.         android:layout_height="wrap_content" 
    40.         android:layout_marginTop="30dp" 
    41.         android:hint="Input the text"/> 
    42.      
    43.     <Button 
    44.         android:id="@+id/btn_add_qrcode" 
    45.         android:layout_width="fill_parent" 
    46.         android:layout_height="wrap_content" 
    47.         android:text="Generate QRcode"/> 
    48.      
    49.     <ImageView  
    50.         android:id="@+id/iv_qr_image" 
    51.         android:layout_width="wrap_content" 
    52.         android:layout_height="wrap_content" 
    53.         android:layout_marginTop="10dp" 
    54.         android:layout_gravity="center"/> 
    55.  
    56. </LinearLayout> 

    下面是主Activity的代码,主要功能是打开扫描框、显示扫描结果、根据输入的字符串生成二维码图片:

    1. publicclass BarCodeTestActivity extends Activity { 
    2.     /** Called when the activity is first created. */ 
    3.     private TextView resultTextView; 
    4.     private EditText qrStrEditText; 
    5.     private ImageView qrImgImageView; 
    6.      
    7.     @Override 
    8.     publicvoid onCreate(Bundle savedInstanceState) { 
    9.         super.onCreate(savedInstanceState); 
    10.         setContentView(R.layout.main); 
    11.          
    12.         resultTextView = (TextView) this.findViewById(R.id.tv_scan_result); 
    13.         qrStrEditText = (EditText) this.findViewById(R.id.et_qr_string); 
    14.         qrImgImageView = (ImageView) this.findViewById(R.id.iv_qr_image); 
    15.          
    16.         Button scanBarCodeButton = (Button) this.findViewById(R.id.btn_scan_barcode); 
    17.         scanBarCodeButton.setOnClickListener(new OnClickListener() { 
    18.              
    19.             @Override 
    20.             publicvoid onClick(View v) { 
    21.                 //打开扫描界面扫描条形码或二维码  
    22.                 Intent openCameraIntent = new Intent(BarCodeTestActivity.this,CaptureActivity.class); 
    23.                 startActivityForResult(openCameraIntent, 0); 
    24.             } 
    25.         }); 
    26.          
    27.         Button generateQRCodeButton = (Button) this.findViewById(R.id.btn_add_qrcode); 
    28.         generateQRCodeButton.setOnClickListener(new OnClickListener() { 
    29.              
    30.             @Override 
    31.             publicvoid onClick(View v) { 
    32.                 try
    33.                     String contentString = qrStrEditText.getText().toString(); 
    34.                     if (!contentString.equals("")) { 
    35.                         //根据字符串生成二维码图片并显示在界面上,第二个参数为图片的大小(350*350)  
    36.                         Bitmap qrCodeBitmap = EncodingHandler.createQRCode(contentString, 350); 
    37.                         qrImgImageView.setImageBitmap(qrCodeBitmap); 
    38.                     }else
    39.                         Toast.makeText(BarCodeTestActivity.this, "Text can not be empty", Toast.LENGTH_SHORT).show(); 
    40.                     } 
    41.                      
    42.                 } catch (WriterException e) { 
    43.                     // TODO Auto-generated catch block  
    44.                     e.printStackTrace(); 
    45.                 } 
    46.             } 
    47.         }); 
    48.     } 
    49.  
    50.     @Override 
    51.     protectedvoid onActivityResult(int requestCode, int resultCode, Intent data) { 
    52.         super.onActivityResult(requestCode, resultCode, data); 
    53.         //处理扫描结果(在界面上显示)  
    54.         if (resultCode == RESULT_OK) { 
    55.             Bundle bundle = data.getExtras(); 
    56.             String scanResult = bundle.getString("result"); 
    57.             resultTextView.setText(scanResult); 
    58.         } 
    59.     } 

    其中生成二维码图片的代码在EncodingHandler.java中:

    1. publicfinalclass EncodingHandler { 
    2.     privatestaticfinalint BLACK = 0xff000000
    3.      
    4.     publicstatic Bitmap createQRCode(String str,int widthAndHeight) throws WriterException { 
    5.         Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>();   
    6.         hints.put(EncodeHintType.CHARACTER_SET, "utf-8");  
    7.         BitMatrix matrix = new MultiFormatWriter().encode(str, 
    8.                 BarcodeFormat.QR_CODE, widthAndHeight, widthAndHeight); 
    9.         int width = matrix.getWidth(); 
    10.         int height = matrix.getHeight(); 
    11.         int[] pixels = newint[width * height]; 
    12.          
    13.         for (int y = 0; y < height; y++) { 
    14.             for (int x = 0; x < width; x++) { 
    15.                 if (matrix.get(x, y)) { 
    16.                     pixels[y * width + x] = BLACK; 
    17.                 } 
    18.             } 
    19.         } 
    20.         Bitmap bitmap = Bitmap.createBitmap(width, height, 
    21.                 Bitmap.Config.ARGB_8888); 
    22.         bitmap.setPixels(pixels, 0, width, 0, 0, width, height); 
    23.         return bitmap; 
    24.     } 

    最后是在哪里对扫描结果进行解码,进入CaptureActivity.java找到下面这个方法便可以对自己对结果进行操作:

    1. /**
    2. * Handler scan result
    3. * @param result
    4. * @param barcode
    5. */ 
    6. ublic void handleDecode(Result result, Bitmap barcode) { 
    7. inactivityTimer.onActivity(); 
    8. playBeepSoundAndVibrate(); 
    9. String resultString = result.getText(); 
    10. //FIXME  
    11. if (resultString.equals("")) { 
    12.     Toast.makeText(CaptureActivity.this, "Scan failed!", Toast.LENGTH_SHORT).show(); 
    13. }else
    14.             System.out.println("Result:"+resultString); 
    15.     Intent resultIntent = new Intent(); 
    16.     Bundle bundle = new Bundle(); 
    17.     bundle.putString("result", resultString); 
    18.     resultIntent.putExtras(bundle); 
    19.     this.setResult(RESULT_OK, resultIntent); 
    20. CaptureActivity.this.finish(); 

    4.Java端编码演示

    在Java端上实现条形码(EAN-13)和二维码(QRCode) 的编码和解码的示例,以供大家参考,用到了源码中core和javase下面的相关源代码,附件提供自己编译之后的lib包:

    • zxing.jar
    • zxing-j2se.jar

      有关各种手机系统的应用,有兴趣的朋友可以下载官方源码包,包下有具体详细的应用介绍。

      1)二维码(QRCode)的编码和解码演示:

      编码示例:

      1. package michael.zxing; 
      2.  
      3. import java.io.File; 
      4. import java.util.Hashtable; 
      5.  
      6. import com.google.zxing.BarcodeFormat; 
      7. import com.google.zxing.EncodeHintType; 
      8. import com.google.zxing.MultiFormatWriter; 
      9. import com.google.zxing.client.j2se.MatrixToImageWriter; 
      10. import com.google.zxing.common.BitMatrix; 
      11. import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; 
      12.  
      13. /**
      14. * @blog http://sjsky.iteye.com
      15. * @author Michael
      16. */ 
      17. publicclass ZxingEncoderHandler { 
      18.  
      19.     /**
      20.      * 编码
      21.      * @param contents
      22.      * @param width
      23.      * @param height
      24.      * @param imgPath
      25.      */ 
      26.     publicvoid encode(String contents, int width, int height, String imgPath) { 
      27.         Hashtable<Object, Object> hints = new Hashtable<Object, Object>(); 
      28.         // 指定纠错等级  
      29.         hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L); 
      30.         // 指定编码格式  
      31.         hints.put(EncodeHintType.CHARACTER_SET, "GBK"); 
      32.         try
      33.             BitMatrix bitMatrix = new MultiFormatWriter().encode(contents, 
      34.                     BarcodeFormat.QR_CODE, width, height, hints); 
      35.  
      36.             MatrixToImageWriter 
      37.                     .writeToFile(bitMatrix, "png", new File(imgPath)); 
      38.  
      39.         } catch (Exception e) { 
      40.             e.printStackTrace(); 
      41.         } 
      42.     } 
      43.  
      44.     /**
      45.      * @param args
      46.      */ 
      47.     publicstaticvoid main(String[] args) { 
      48.         String imgPath = "d:/1.png"
      49.         String contents = "Hello Word!"
      50.         int width = 300, height = 300
      51.         ZxingEncoderHandler handler = new ZxingEncoderHandler(); 
      52.         handler.encode(contents, width, height, imgPath); 
      53.     } 

      运行后生成的二维码图片如下:

      用手机的二维码扫描软件(本人用的:android 快拍二维码 )来测试下,识别成功的截图如下:

       

           解码示例:

      1. package michael.zxing; 
      2.  
      3. import java.awt.image.BufferedImage; 
      4. import java.io.File; 
      5. import java.util.Hashtable; 
      6.  
      7. import javax.imageio.ImageIO; 
      8.  
      9. import com.google.zxing.BinaryBitmap; 
      10. import com.google.zxing.DecodeHintType; 
      11. import com.google.zxing.LuminanceSource; 
      12. import com.google.zxing.MultiFormatReader; 
      13. import com.google.zxing.Result; 
      14. import com.google.zxing.client.j2se.BufferedImageLuminanceSource; 
      15. import com.google.zxing.common.HybridBinarizer; 
      16.  
      17. /**
      18. * @blog http://sjsky.iteye.com
      19. * @author Michael
      20. */ 
      21. publicclass ZxingDecoderHandler { 
      22.  
      23.     /**
      24.      * @param imgPath
      25.      * @return String
      26.      */ 
      27.     public String decode(String imgPath) { 
      28.         BufferedImage image = null
      29.         Result result = null
      30.         try
      31.             image = ImageIO.read(new File(imgPath)); 
      32.             if (image == null) { 
      33.                 System.out.println("the decode image may be not exit."); 
      34.             } 
      35.             LuminanceSource source = new BufferedImageLuminanceSource(image); 
      36.             BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); 
      37.  
      38.             Hashtable<Object, Object> hints = new Hashtable<Object, Object>(); 
      39.             hints.put(DecodeHintType.CHARACTER_SET, "utf-8"); 
      40.  
      41.             result = new MultiFormatReader().decode(bitmap, hints); 
      42.             return result.getText(); 
      43.         } catch (Exception e) { 
      44.             e.printStackTrace(); 
      45.         } 
      46.         returnnull
      47.     } 
      48.  
      49.     /**
      50.      * @param args
      51.      */ 
      52.     publicstaticvoid main(String[] args) { 
      53.         String imgPath = "d:/1.png"
      54.         ZxingDecoderHandler handler = new ZxingDecoderHandler(); 
      55.         String decodeContent = handler.decode(imgPath); 
      56.         System.out.println("解码内容如下:"); 
      57.         System.out.println(decodeContent); 
      58.     } 

      解码内容如下: Hello Word!

      2)条形码(EAN-13)的编码和解码演示:

      编码示例:

      1. package michael.zxing; 
      2.  
      3. import java.io.File; 
      4.  
      5. import com.google.zxing.BarcodeFormat; 
      6. import com.google.zxing.MultiFormatWriter; 
      7. import com.google.zxing.client.j2se.MatrixToImageWriter; 
      8. import com.google.zxing.common.BitMatrix; 
      9.  
      10. /**
      11. * @blog http://sjsky.iteye.com
      12. * @author Michael
      13. */ 
      14. publicclass ZxingEAN13EncoderHandler { 
      15.  
      16.     /**
      17.      * 编码
      18.      * @param contents
      19.      * @param width
      20.      * @param height
      21.      * @param imgPath
      22.      */ 
      23.     publicvoid encode(String contents, int width, int height, String imgPath) { 
      24.         int codeWidth = 3 + // start guard  
      25.                 (7 * 6) + // left bars  
      26.                 5 + // middle guard  
      27.                 (7 * 6) + // right bars  
      28.                 3; // end guard  
      29.         codeWidth = Math.max(codeWidth, width); 
      30.         try
      31.             BitMatrix bitMatrix = new MultiFormatWriter().encode(contents, 
      32.                     BarcodeFormat.EAN_13, codeWidth, height, null); 
      33.  
      34.             MatrixToImageWriter 
      35.                     .writeToFile(bitMatrix, "png", new File(imgPath)); 
      36.  
      37.         } catch (Exception e) { 
      38.             e.printStackTrace(); 
      39.         } 
      40.     } 
      41.  
      42.     /**
      43.      * @param args
      44.      */ 
      45.     publicstaticvoid main(String[] args) { 
      46.         String imgPath = "d:/2.png"
      47.         // 益达无糖口香糖的条形码  
      48.         String contents = "6923450657713"
      49.  
      50.         int width = 105, height = 50
      51.         ZxingEAN13EncoderHandler handler = new ZxingEAN13EncoderHandler(); 
      52.         handler.encode(contents, width, height, imgPath); 
      53.     } 

      运行后生成条形码图片如下:

    • 用手机的条形码扫描软件(本人用的:android 快拍二维码 )来测试下,识别成功的截图如下:

      解码示例:

      1. package michael.zxing; 
      2.  
      3. import java.awt.image.BufferedImage; 
      4. import java.io.File; 
      5.  
      6. import javax.imageio.ImageIO; 
      7.  
      8. import com.google.zxing.BinaryBitmap; 
      9. import com.google.zxing.LuminanceSource; 
      10. import com.google.zxing.MultiFormatReader; 
      11. import com.google.zxing.Result; 
      12. import com.google.zxing.client.j2se.BufferedImageLuminanceSource; 
      13. import com.google.zxing.common.HybridBinarizer; 
      14.  
      15. /**
      16. * @blog http://sjsky.iteye.com
      17. * @author Michael
      18. */ 
      19. publicclass ZxingEAN13DecoderHandler { 
      20.  
      21.     /**
      22.      * @param imgPath
      23.      * @return String
      24.      */ 
      25.     public String decode(String imgPath) { 
      26.         BufferedImage image = null
      27.         Result result = null
      28.         try
      29.             image = ImageIO.read(new File(imgPath)); 
      30.             if (image == null) { 
      31.                 System.out.println("the decode image may be not exit."); 
      32.             } 
      33.             LuminanceSource source = new BufferedImageLuminanceSource(image); 
      34.             BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); 
      35.  
      36.             result = new MultiFormatReader().decode(bitmap, null); 
      37.             return result.getText(); 
      38.         } catch (Exception e) { 
      39.             e.printStackTrace(); 
      40.         } 
      41.         returnnull
      42.     } 
      43.  
      44.     /**
      45.      * @param args
      46.      */ 
      47.     publicstaticvoid main(String[] args) { 
      48.         String imgPath = "d:/2.png"
      49.         ZxingEAN13DecoderHandler handler = new ZxingEAN13DecoderHandler(); 
      50.         String decodeContent = handler.decode(imgPath); 
      51.         System.out.println("解码内容如下:"); 
      52.         System.out.println(decodeContent); 
      53.     } 

      解码内容如下: 6923450657713

      5.源码说明和下载

      官方例子:

      BarcodeScanner (Barcode Scanner 4.31 for Android Featured 必须先将此apk安装才可以运行ZXingTest项目)

      ZXingTest (android端调用BarcodeScanner测试例子)

      简化例子:

      BarCodeTest (android端扫描和解码精简例子)

      QRcode (java端扫描和解码例子)

      源码下载

    转载请标明出处http://blog.csdn.net/shimiso 欢迎有识之士加入我们的技术交流群:173711587

  • 相关阅读:
    Codewars Solution:Two to One
    Codewars Solution:Get the Middle Character
    golang jwt+token验证
    C#基础知识点梳理二
    C#基础知识点梳理一
    逻辑值
    step-1
    视频第5讲-ID转换
    通过向量访问矩阵
    跟着jmzeng学习GEO数据分析-GEO42872_1--题外
  • 原文地址:https://www.cnblogs.com/LiaoHao/p/3301028.html
Copyright © 2011-2022 走看看