Android ZXing 二維碼、條形碼掃描介紹

最近公司的Android項目須要用到攝像頭作條碼或二維碼的掃描,Google一下,發現一個開源的 ZXing項目。它提供二維碼和條形碼的掃描。掃描條形碼就是直接讀取條形碼的內容,掃描二維碼是按照本身指定的二維碼格式進行編碼和解碼。 php

1.什麼是二維碼和條形碼?

                        

二維條形碼最先發明於日本,它是用某種特定的幾何圖形按必定規律在平面(二維方向上)分佈的黑白相間的圖形記錄數據符號信息的,在代碼編制上巧妙地利用構成計算機內部邏輯基礎的「0」、「1」比特流的概念,使用若干個與二進制相對應的幾何形體來表示文字數值信息,經過圖象輸入設備或光電掃描設備自動識讀以實現信息自動處理。它具備條碼技術的一些共性:每種碼制有其特定的字符集;每一個字符佔有必定的寬度;具備必定的校驗功能等。同時還具備對不一樣行的信息自動識別功能、及處理圖形旋轉變化等特色。 java

條形碼(barcode)是將寬度不等的多個黑條和空白,按照必定的編碼規則排列,用以表達一組信息的圖形標識符。常見的條形碼是由反射率相差很大的黑條(簡稱條)和白條(簡稱空)排成的平行線圖案。條形碼能夠標出物品的生產國、製造廠家、商品名稱、生產日期、圖書分類號、郵件起止地點、類別、日期等許多信息,於是在商品流通、圖書管理、郵政管理、銀行系統等許多領域都獲得普遍的應用。 android

2.ZXing基本介紹

ZXing是一個開源Java類庫用於解析多種格式的條形碼和二維碼.官網:http://code.google.com/p/zxing/ ruby

截止目前爲止最新版本提供如下編碼格式的支持: ide

  • 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包。 ui

接下來看如何使用,首先是把ZXing項目中的一些文件拷貝到咱們本身的項目中,而後在Mainifest文件中進行配置權限: this


  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的配置: google


  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
相關文章
相關標籤/搜索