1. 程式人生 > >Android ZXing二維碼、條形碼的生成和解析

Android ZXing二維碼、條形碼的生成和解析

ZXing(Zebra Crossing)是Google開發的一個二維碼解析和生成的開源庫。

近期的一個手錶專案需要用到二維碼生成,於是就研究了一下。實現起來很簡便,將jar包放入工程,就可以直接使用API了。

裝置將位置資訊更新給伺服器,在瀏覽器輸入URL訪問指定ID裝置的位置資訊。這個URL可以用二維碼的形式展示出來。

1.生成二維碼:

	private void initialLayout() {
		ImageView imageQRCode = (ImageView) findViewById(R.id.imageQRCode);
		String contentQRCode = Constant.Server.URL_MAP_INDEX + MyApp.deviceId;
		try {
			// 根據字串生成二維碼圖片並顯示在介面上,第二個引數為圖片的大小(310*310)
			Bitmap bitmapQRCode = QRCodeUtil.createQRCode(contentQRCode,
					310);
			imageQRCode.setImageBitmap(bitmapQRCode);
		} catch (WriterException e) {
			e.printStackTrace();
		}
	}

QRCodeUtil:

import java.util.Hashtable;

import android.graphics.Bitmap;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;

public final class QRCodeUtil {
	private static final int BLACK = 0xff000000;

	public static Bitmap createQRCode(String str, int widthAndHeight)
			throws WriterException {
		Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>();
		hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
		BitMatrix matrix = new MultiFormatWriter().encode(str,
				BarcodeFormat.QR_CODE, widthAndHeight, widthAndHeight);
		int width = matrix.getWidth();
		int height = matrix.getHeight();
		int[] pixels = new int[width * height];

		for (int y = 0; y < height; y++) {
			for (int x = 0; x < width; x++) {
				if (matrix.get(x, y)) {
					pixels[y * width + x] = BLACK;
				}
			}
		}
		Bitmap bitmap = Bitmap.createBitmap(width, height,
				Bitmap.Config.ARGB_8888);
		bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
		return bitmap;
	}
}


效果圖:

可以用微信掃一掃,也可以用自己寫的解析程式掃描,進入指定的URL。

2.生成條形碼

條形碼有很多種類,二維(條形)碼就是其中一種。表示內容也有不同,有的只能表示純數字,不能表示字母。

BarcodeFormat.CODE_128; // 表示高密度資料, 字串可變長,符號內含校驗碼
BarcodeFormat.CODE_39;
BarcodeFormat.CODE_93;
BarcodeFormat.CODABAR; // 可表示數字0 - 9,字元$、+、 -、還有隻能用作起始/終止符的a,b,c d四個字元,可變長度,沒有校驗位
BarcodeFormat.DATA_MATRIX;
BarcodeFormat.EAN_8;
BarcodeFormat.EAN_13;
BarcodeFormat.ITF;
BarcodeFormat.PDF417; // 二維碼
BarcodeFormat.QR_CODE; // 二維碼
BarcodeFormat.RSS_EXPANDED;
BarcodeFormat.RSS14;
BarcodeFormat.UPC_E; // 統一產品程式碼E:7位數字,最後一位為校驗位
BarcodeFormat.UPC_A; // 統一產品程式碼A:12位數字,最後一位為校驗位
BarcodeFormat.UPC_EAN_EXTENSION;

ublic static Bitmap creatBarcode(Context context, String contents,
			int desiredWidth, int desiredHeight, boolean displayCode) {
		Bitmap ruseltBitmap = null;
		int marginW = 20;
		BarcodeFormat barcodeFormat = BarcodeFormat.CODE_128;

		if (displayCode) {
			Bitmap barcodeBitmap = encodeAsBitmap(contents, barcodeFormat,
					desiredWidth, desiredHeight);
			Bitmap codeBitmap = creatCodeBitmap(contents, desiredWidth + 2
					* marginW, desiredHeight, context);
			ruseltBitmap = mixtureBitmap(barcodeBitmap, codeBitmap, new PointF(
					0, desiredHeight));
		} else {
			ruseltBitmap = encodeAsBitmap(contents, barcodeFormat,
					desiredWidth, desiredHeight);
		}

		return ruseltBitmap;
	}
	
	
	protected static Bitmap encodeAsBitmap(String contents,
			BarcodeFormat format, int desiredWidth, int desiredHeight) {
		final int WHITE = 0xFFFFFFFF;
		final int BLACK = 0xFF000000;

		MultiFormatWriter writer = new MultiFormatWriter();
		BitMatrix result = null;
		try {
			result = writer.encode(contents, format, desiredWidth,
					desiredHeight, null);
		} catch (WriterException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		int width = result.getWidth();
		int height = result.getHeight();
		int[] pixels = new int[width * height];
		// All are 0, or black, by default
		for (int y = 0; y < height; y++) {
			int offset = y * width;
			for (int x = 0; x < width; x++) {
				pixels[offset + x] = result.get(x, y) ? BLACK : WHITE;
			}
		}

		Bitmap bitmap = Bitmap.createBitmap(width, height,
				Bitmap.Config.ARGB_8888);
		bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
		return bitmap;
	}
	
	
	protected static Bitmap creatCodeBitmap(String contents, int width,
			int height, Context context) {
		TextView tv = new TextView(context);
		LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
				LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
		tv.setLayoutParams(layoutParams);
		tv.setText(contents);
		tv.setHeight(height);
		tv.setGravity(Gravity.CENTER_HORIZONTAL);
		tv.setWidth(width);
		tv.setDrawingCacheEnabled(true);
		tv.setTextColor(Color.BLACK);
		tv.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
				MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
		tv.layout(0, 0, tv.getMeasuredWidth(), tv.getMeasuredHeight());

		tv.buildDrawingCache();
		Bitmap bitmapCode = tv.getDrawingCache();
		return bitmapCode;
	}
	
	
	protected static Bitmap mixtureBitmap(Bitmap first, Bitmap second,
			PointF fromPoint) {
		if (first == null || second == null || fromPoint == null) {
			return null;
		}
		int marginW = 20;
		Bitmap newBitmap = Bitmap.createBitmap(
				first.getWidth() + second.getWidth() + marginW,
				first.getHeight() + second.getHeight(), Config.ARGB_4444);
		Canvas cv = new Canvas(newBitmap);
		cv.drawBitmap(first, marginW, 0, null);
		cv.drawBitmap(second, fromPoint.x, fromPoint.y, null);
		cv.save(Canvas.ALL_SAVE_FLAG);
		cv.restore();

		return newBitmap;
	}

creatBarcode的最後一個引數:是否要在條形碼下方顯示生成的內容。

		ImageView imageBarCode = (ImageView) findViewById(R.id.imageBarCode);
		imageBarCode.setImageBitmap(QRCodeUtil.creatBarcode(
				getApplicationContext(), "78480000b4a5", 600, 400, true));

生成結果:


3.解析-zxing.CaptureActivity中handleDecode處理解析好的資料即可:

    /**
     * A valid barcode has been found, so give an indication of success and show
     * the results.
     *
     * @param rawResult   The contents of the barcode.
     * @param scaleFactor amount by which thumbnail was scaled
     * @param barcode     A greyscale bitmap of the camera data which was decoded.
     */
    public void handleDecode(final Result rawResult, Bitmap barcode,
                             float scaleFactor) {
        inactivityTimer.onActivity();
        boolean fromLiveScan = barcode != null;

        if (fromLiveScan) {
            beepManager.playBeepSoundAndVibrate();
        }

        finish();
        String scanResult = rawResult.getText();
        if (null != scanResult && scanResult.trim().length() > 0) {
            Intent intentBind = new Intent(CaptureActivity.this,
                    BindActivity.class);
            intentBind.putExtra("physicalId", scanResult);
            startActivity(intentBind);
        }

        switch (source) {
            case NATIVE_APP_INTENT:
            case PRODUCT_SEARCH_LINK:
                break;
				
            case ZXING_LINK:
                break;
				
            case NONE:
                break;
        }
    }