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

    本帖最后由 Shims 于 2013-11-9 12:39 编辑

    最近公司的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. <font color="#000"><font face="Arial">    <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" /></font></font>
    复制代码

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


    1. <font color="#000">   <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></font>
    复制代码

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


    1. <font color="#000"><font face="Arial"><?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.     <Button
    8.         android:id="@+id/btn_scan_barcode"
    9.         android:layout_width="fill_parent"
    10.         android:layout_height="wrap_content"
    11.         android:layout_marginTop="30dp"
    12.         android:text="Open camera" />
    13.     
    14.     <LinearLayout 
    15.         android:orientation="horizontal"
    16.         android:layout_marginTop="10dp"
    17.         android:layout_width="fill_parent"
    18.         android:layout_height="wrap_content">
    19.         
    20.         <TextView 
    21.                android:layout_width="wrap_content"
    22.         android:layout_height="wrap_content"
    23.         android:textColor="@android:color/black"
    24.         android:textSize="18sp"
    25.         android:text="Scan result:" />
    26.         
    27.         <TextView 
    28.         android:id="@+id/tv_scan_result"
    29.                android:layout_width="fill_parent"
    30.                android:textSize="18sp"
    31.                android:textColor="@android:color/black"
    32.         android:layout_height="wrap_content" />
    33.     </LinearLayout>
    34.     
    35.     <EditText 
    36.         android:id="@+id/et_qr_string"
    37.         android:layout_width="fill_parent"
    38.         android:layout_height="wrap_content"
    39.         android:layout_marginTop="30dp"
    40.         android:hint="Input the text"/>
    41.     
    42.     <Button
    43.         android:id="@+id/btn_add_qrcode"
    44.         android:layout_width="fill_parent"
    45.         android:layout_height="wrap_content"
    46.         android:text="Generate QRcode" />
    47.     
    48.     <ImageView 
    49.         android:id="@+id/iv_qr_image"
    50.         android:layout_width="wrap_content"
    51.         android:layout_height="wrap_content"
    52.         android:layout_marginTop="10dp"
    53.         android:layout_gravity="center"/>
    54. </LinearLayout></font></font>
    复制代码

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


    1. <font color="#000"><font face="Arial">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.         @Override
    50.         protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    51.                 super.onActivityResult(requestCode, resultCode, data);
    52.                 //处理扫描结果(在界面上显示)
    53.                 if (resultCode == RESULT_OK) {
    54.                         Bundle bundle = data.getExtras();
    55.                         String scanResult = bundle.getString("result");
    56.                         resultTextView.setText(scanResult);
    57.                 }
    58.         }
    59. }</font></font>
    复制代码

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


    1. <font color="#000"><font face="Arial">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, 0, 0, width, height);
    23.                 return bitmap;
    24.         }
    25. }</font></font>
    复制代码

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


    1. <font color="#000"><font face="Arial">  /**
    2.          * Handler scan result
    3.          * @param result
    4.          * @param barcode
    5.          */
    6.         public 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();
    22.         }</font></font>
    复制代码



    4.Java端编码演示

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

    zxing.jar
    zxing-j2se.jar
    有关各种手机系统的应用,有兴趣的朋友可以下载官方源码包,包下有具体详细的应用介绍。
    1)二维码(QRCode)的编码和解码演示:
    编码示例:
    1. package michael.zxing;
    2. import java.io.File;
    3. import java.util.Hashtable;
    4. import com.google.zxing.BarcodeFormat;
    5. import com.google.zxing.EncodeHintType;
    6. import com.google.zxing.MultiFormatWriter;
    7. import com.google.zxing.client.j2se.MatrixToImageWriter;
    8. import com.google.zxing.common.BitMatrix;
    9. import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
    10. /**
    11. * [url=home.php?mod=space&uid=618199]@blog[/url] http://sjsky.iteye.com
    12. * @author Michael
    13. */
    14. public class ZxingEncoderHandler {
    15.     /**
    16.      * 编码
    17.      * @param contents
    18.      * @param width
    19.      * @param height
    20.      * @param imgPath
    21.      */
    22.     public void encode(String contents, int width, int height, String imgPath) {
    23.         Hashtable<Object, Object> hints = new Hashtable<Object, Object>();
    24.         // 指定纠错等级
    25.         hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
    26.         // 指定编码格式
    27.         hints.put(EncodeHintType.CHARACTER_SET, "GBK");
    28.         try {
    29.             BitMatrix bitMatrix = new MultiFormatWriter().encode(contents,
    30.                     BarcodeFormat.QR_CODE, width, height, hints);
    31.             MatrixToImageWriter
    32.                     .writeToFile(bitMatrix, "png", new File(imgPath));
    33.         } catch (Exception e) {
    34.             e.printStackTrace();
    35.         }
    36.     }
    37.     /**
    38.      * @param args
    39.      */
    40.     public static void main(String[] args) {
    41.         String imgPath = "d:/1.png";
    42.         String contents = "Hello Word!";
    43.         int width = 300, height = 300;
    44.         ZxingEncoderHandler handler = new ZxingEncoderHandler();
    45.         handler.encode(contents, width, height, imgPath);
    46.     }
    47. }
    复制代码
    运行后生成的二维码图片如下:
    用手机的二维码扫描软件(本人用的:android 快拍二维码 )来测试下,识别成功的截图如下:


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

    Hello Word!
    2)条形码(EAN-13)的编码和解码演示:
    编码示例:
    1. package michael.zxing;
    2. import java.io.File;
    3. import com.google.zxing.BarcodeFormat;
    4. import com.google.zxing.MultiFormatWriter;
    5. import com.google.zxing.client.j2se.MatrixToImageWriter;
    6. import com.google.zxing.common.BitMatrix;
    7. /**
    8. * @blog http://sjsky.iteye.com
    9. * @author Michael
    10. */
    11. public class ZxingEAN13EncoderHandler {
    12.     /**
    13.      * 编码
    14.      * @param contents
    15.      * @param width
    16.      * @param height
    17.      * @param imgPath
    18.      */
    19.     public void encode(String contents, int width, int height, String imgPath) {
    20.         int codeWidth = 3 + // start guard
    21.                 (7 * 6) + // left bars
    22.                 5 + // middle guard
    23.                 (7 * 6) + // right bars
    24.                 3; // end guard
    25.         codeWidth = Math.max(codeWidth, width);
    26.         try {
    27.             BitMatrix bitMatrix = new MultiFormatWriter().encode(contents,
    28.                     BarcodeFormat.EAN_13, codeWidth, height, null);
    29.             MatrixToImageWriter
    30.                     .writeToFile(bitMatrix, "png", new File(imgPath));
    31.         } catch (Exception e) {
    32.             e.printStackTrace();
    33.         }
    34.     }
    35.     /**
    36.      * @param args
    37.      */
    38.     public static void main(String[] args) {
    39.         String imgPath = "d:/2.png";
    40.         // 益达无糖口香糖的条形码
    41.         String contents = "6923450657713";
    42.         int width = 105, height = 50;
    43.         ZxingEAN13EncoderHandler handler = new ZxingEAN13EncoderHandler();
    44.         handler.encode(contents, width, height, imgPath);
    45.     }
    46. }
    复制代码
    运行后生成条形码图片如下:

    用手机的条形码扫描软件(本人用的:android 快拍二维码 )来测试下,识别成功的截图如下:
    解码示例:
    1. package michael.zxing;
    2. import java.awt.image.BufferedImage;
    3. import java.io.File;
    4. import javax.imageio.ImageIO;
    5. import com.google.zxing.BinaryBitmap;
    6. import com.google.zxing.LuminanceSource;
    7. import com.google.zxing.MultiFormatReader;
    8. import com.google.zxing.Result;
    9. import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
    10. import com.google.zxing.common.HybridBinarizer;
    11. /**
    12. * @blog http://sjsky.iteye.com
    13. * @author Michael
    14. */
    15. public class ZxingEAN13DecoderHandler {
    16.     /**
    17.      * @param imgPath
    18.      * @return String
    19.      */
    20.     public String decode(String imgPath) {
    21.         BufferedImage image = null;
    22.         Result result = null;
    23.         try {
    24.             image = ImageIO.read(new File(imgPath));
    25.             if (image == null) {
    26.                 System.out.println("the decode image may be not exit.");
    27.             }
    28.             LuminanceSource source = new BufferedImageLuminanceSource(image);
    29.             BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
    30.             result = new MultiFormatReader().decode(bitmap, null);
    31.             return result.getText();
    32.         } catch (Exception e) {
    33.             e.printStackTrace();
    34.         }
    35.         return null;
    36.     }
    37.     /**
    38.      * @param args
    39.      */
    40.     public static void main(String[] args) {
    41.         String imgPath = "d:/2.png";
    42.         ZxingEAN13DecoderHandler handler = new ZxingEAN13DecoderHandler();
    43.         String decodeContent = handler.decode(imgPath);
    44.         System.out.println("解码内容如下:");
    45.         System.out.println(decodeContent);
    46.     }
    47. }
    复制代码
    解码内容如下:
    6923450657713

     

  • 相关阅读:
    Linux文档中翻页和搜索关键字
    windows安装mysql
    生成二维码和解析二维码
    powerdesigner通过er图生成mysql执行文件
    powerdesigner使用遇到的一些问题
    UnsupportedOperationException异常
    String[]和List的区别及相互转换
    @PostConstruct注解原理解析
    git强制更新并覆盖本地修改
    Dubbo架构与底层实现
  • 原文地址:https://www.cnblogs.com/sage-blog/p/4169528.html
Copyright © 2011-2022 走看看