Android中使用ZXing识别条形码/二维码

现在大部分的手机都具备自动对焦的拍摄功能,这意味着这些手机可以具备条码扫描的功能,手机具备条码扫描的功能,可以优化购物流程,快速存储电子名片(Android二维码)等。

本文使用ZXing 1.6实现条码/二维码识别。ZXing是个很经典的条码/二维码识别的开源类库,很早就有开发者在J2ME上使用ZXing了,不过要支持JSR-234规范(自动对焦)的手机才能发挥其威力,而目前已经有不少Android手机具备自动对焦的功能。

本文代码运行的结果如下,使用91手机助手截图时,无法截取SurfaceView的实时图像:

Android条码

android二维码

Android识别码

本文使用了ZXing1.6的core,即把/zxing-1.6/core/下的src复制覆盖工程的src;另外还要使用到/zxing-1.6/android/下的PlanarYUVLuminanceSource.java。

PS:/zxing-1.6/android/ 是BarcodeScanner的源码,本文程序相当于BarcodeScanner的精简版,只保留最基本的识别功能。

本文源码工程下载地址二维码Demo.rar

源码目录结果如下图,ChecksumException.java下面还有很多源文件,截图尚未列出:

工程目录

本文例子必须要开摄像头和自动对焦的权限,不然启动时会报异常,所需权限如下

main.xml源码如下,main.xml必须要用到FrameLayout才能重叠控件实现“范围框”的效果:

testCamera.java是主类,负责控制Camera和对图像做解码,源码如下:

package com.testCamera;

import java.util.Timer;
import java.util.TimerTask;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.Result;
import com.google.zxing.Android.PlanarYUVLuminanceSource;
import com.google.zxing.common.HybridBinarizer;
import android.app.Activity;
import android.graphics.Bitmap;
import android.hardware.Camera;
import android.os.Bundle;
import android.view.SurfaceView;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

public class testCamera extends Activity {
	/** Called when the activity is first created. */
	private SurfaceView sfvCamera;
	private SFHCamera sfhCamera;
	private ImageView imgView;
	private View centerView;
	private TextView txtScanResult;
	private Timer mTimer;
	private MyTimerTask mTimerTask;
	// 按照标准HVGA
	final static int width = 480;
	final static int height = 320;
	int dstLeft, dstTop, dstWidth, dstHeight;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		this.setTitle("Android条码/二维码识别Demo-----hellogv");
		imgView = (ImageView) this.findViewById(R.id.ImageView01);
		centerView = (View) this.findViewById(R.id.centerView);
		sfvCamera = (SurfaceView) this.findViewById(R.id.sfvCamera);
		sfhCamera = new SFHCamera(sfvCamera.getHolder(), width, height,
				previewCallback);
		txtScanResult = (TextView) this.findViewById(R.id.txtScanResult);
		// 初始化定时器
		mTimer = new Timer();
		mTimerTask = new MyTimerTask();
		mTimer.schedule(mTimerTask, 0, 80);
	}

	class MyTimerTask extends TimerTask {
		@Override
		public void run() {
			if (dstLeft == 0) {// 只赋值一次
				dstLeft = centerView.getLeft() * width
						/ getWindowManager().getDefaultDisplay().getWidth();
				dstTop = centerView.getTop() * height
						/ getWindowManager().getDefaultDisplay().getHeight();
				dstWidth = (centerView.getRight() - centerView.getLeft())
						* width
						/ getWindowManager().getDefaultDisplay().getWidth();
				dstHeight = (centerView.getBottom() - centerView.getTop())
						* height
						/ getWindowManager().getDefaultDisplay().getHeight();
			}
			sfhCamera.AutoFocusAndPreviewCallback();
		}
	}

	/**
	 * 自动对焦后输出图片
	 */
	private Camera.PreviewCallback previewCallback = new Camera.PreviewCallback() {
		@Override
		public void onPreviewFrame(byte[] data, Camera arg1) {
			// 取得指定范围的帧的数据
			PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource(
					data, width, height, dstLeft, dstTop, dstWidth, dstHeight);
			// 取得灰度图
			Bitmap mBitmap = source.renderCroppedGreyscaleBitmap();
			// 显示灰度图
			imgView.setImageBitmap(mBitmap);
			BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
			MultiFormatReader reader = new MultiFormatReader();
			try {
				Result result = reader.decode(bitmap);
				String strResult = "BarcodeFormat:"
						+ result.getBarcodeFormat().toString() + "  text:"
						+ result.getText();
				txtScanResult.setText(strResult);
			} catch (Exception e) {
				txtScanResult.setText("Scanning");
			}
		}
	};
}

SFHCamera.java是Camera控制类,源码如下:

package com.testCamera;

import java.io.IOException;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.util.Log;
import android.view.SurfaceHolder;

public class SFHCamera implements SurfaceHolder.Callback {

	private SurfaceHolder holder = null;
	private Camera mCamera;
	private int width, height;
	private Camera.PreviewCallback previewCallback;

	public SFHCamera(SurfaceHolder holder, int w, int h,
			Camera.PreviewCallback previewCallback) {
		this.holder = holder;
		this.holder.addCallback(this);
		this.holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
		width = w;
		height = h;
		this.previewCallback = previewCallback;
	}

	@Override
	public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
		Camera.Parameters parameters = mCamera.getParameters();
		parameters.setPreviewSize(width, height);// 设置尺寸
		parameters.setPictureFormat(PixelFormat.JPEG);
		mCamera.setParameters(parameters);
		mCamera.startPreview();// 开始预览
		Log.e("Camera", "surfaceChanged");
	}

	@Override
	public void surfaceCreated(SurfaceHolder arg0) {
		mCamera = Camera.open();// 启动服务
		try {
			mCamera.setPreviewDisplay(holder);// 设置预览
			Log.e("Camera", "surfaceCreated");
		} catch (IOException e) {
			mCamera.release();// 释放
			mCamera = null;
		}

	}

	@Override
	public void surfaceDestroyed(SurfaceHolder arg0) {
		mCamera.setPreviewCallback(null);
		mCamera.stopPreview();// 停止预览
		mCamera = null;
		Log.e("Camera", "surfaceDestroyed");
	}

	/**
	 * 自动对焦并回调Camera.PreviewCallback
	 */
	public void AutoFocusAndPreviewCallback() {
		if (mCamera != null)
			mCamera.autoFocus(mAutoFocusCallBack);
	}

	/**
	 * 自动对焦
	 */
	private Camera.AutoFocusCallback mAutoFocusCallBack = new Camera.AutoFocusCallback() {

		@Override
		public void onAutoFocus(boolean success, Camera camera) {
			if (success) { // 对焦成功,回调Camera.PreviewCallback
				mCamera.setOneShotPreviewCallback(previewCallback);
			}
		}
	};

}

其中testCamera.java的Camera.PreviewCallback previewCallback 是整个程序的逻辑核心,作为回调函数给SFHCamera.java的内部Camera类调用。

本文摘自:http://blog.csdn.net/hellogv/article/details/6101663

暂无评论
  • 1:请一针见血的评论。
  • 2:评论需要审核通过后才能显示。
  • 3:评论字数限制在1000字以内。
  • 当前字数:0
热门文章
推荐文章
随机文章
关于本站 - 广告服务 - 版权声明 - 联系我们 - 友情链接 - 网站地图 - 帮助中心