Android ZXing 二维码、条形码扫描介绍



   

二维码

目录(?)[+]

  1. 什么是二维码和条形码
  2. ZXing基本介绍
  3. Android端编码演示
  4. Java端编码演示
    1. 二维码QRCode的编码和解码演示
    2. 条形码EAN-13的编码和解码演示
  5. 源码说明和下载

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

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

Android ZXing 二维码、条形码扫描介绍_第1张图片                        Android ZXing 二维码、条形码扫描介绍_第2张图片

二维条形码最早发明于日本,它是用某种特定的几何图形按一定规律在平面(二维方向上)分布的黑白相间的图形记录数据符号信息的,在代码编制上巧妙地利用构成计算机内部逻辑基础的“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是经过简化版的,去除了一些一般使用不必要的文件,项目工程和效果截图如下:

Android ZXing 二维码、条形码扫描介绍_第3张图片Android ZXing 二维码、条形码扫描介绍_第4张图片    Android ZXing 二维码、条形码扫描介绍_第5张图片

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

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

[html] view plain copy
  1. <uses-permission android:name="android.permission.VIBRATE" />  
  2. <uses-permission android:name="android.permission.CAMERA" />  
  3. <uses-feature android:name="android.hardware.camera" />  
  4. <uses-feature android:name="android.hardware.camera.autofocus" />  

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

[html] view plain copy
  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>  

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

[html] view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns: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的代码,主要功能是打开扫描框、显示扫描结果、根据输入的字符串生成二维码图片:

[java] view plain copy
  1. public class 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.     public void 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.             public void 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.             public void 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.     protected void 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.     }  
  60. }  

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

[java] view plain copy
  1. public final class EncodingHandler {  
  2.     private static final int BLACK = 0xff000000;  
  3.       
  4.     public static 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 = new int[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, 00, width, height);  
  23.         return bitmap;  
  24.     }  
  25. }  

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

[java] view plain copy
  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. }  
  21. CaptureActivity.this.finish();  

4.Java端编码演示

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

  • zxing.jar
  • zxing-j2se.jar

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

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

    编码示例:

    [java] view plain copy
    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. public class ZxingEncoderHandler {  
    18.   
    19.     /** 
    20.      * 编码 
    21.      * @param contents 
    22.      * @param width 
    23.      * @param height 
    24.      * @param imgPath 
    25.      */  
    26.     public void 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.     public static void 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.     }  
    54. }  

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

    Android ZXing 二维码、条形码扫描介绍_第6张图片

    用手机的二维码扫描软件(本人用的:android 快拍二维码 )来测试下,识别成功的截图如下:
    Android ZXing 二维码、条形码扫描介绍_第7张图片

    解码示例:

    [java] view plain copy
    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. public class 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.         return null;  
    47.     }  
    48.   
    49.     /** 
    50.      * @param args 
    51.      */  
    52.     public static void 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.     }  
    59. }  

    解码内容如下:
    Hello Word!

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

    编码示例:

    [java] view plain copy
    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. public class ZxingEAN13EncoderHandler {  
    15.   
    16.     /** 
    17.      * 编码 
    18.      * @param contents 
    19.      * @param width 
    20.      * @param height 
    21.      * @param imgPath 
    22.      */  
    23.     public void 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.     public static void 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.     }  
    54. }  

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

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

    Android ZXing 二维码、条形码扫描介绍_第8张图片

    解码示例:

    [java] view plain copy
    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. public class 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.         return null;  
    42.     }  
    43.   
    44.     /** 
    45.      * @param args 
    46.      */  
    47.     public static void 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.     }  
    54. }  

    解码内容如下:
    6923450657713

    5.源码说明和下载

    官方例子:

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

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

    简化例子:

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

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

  • 你可能感兴趣的:(Android ZXing 二维码、条形码扫描介绍)