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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM