Android上使用ZXing识别条形码与二维码的方法
目前有越来越多的手机具备自动对焦的拍摄功能,这也意味着这些手机可以具备条码扫描的功能。手机具备条码扫描的功能,可以优化购物流程,快速存储电子名片(二维码)等。
本文所述实例就使用了zxing 1.6实现条码/二维码识别。zxing是个很经典的条码/二维码识别的开源类库,早在很久以前,就有开发者在j2me上使用zxing了,只不过需要支持jsr-234规范(自动对焦)的手机才能发挥其威力,而目前已经有不少android手机具备自动对焦的功能。
本文代码运行的结果如下,使用91手机助手截图时,无法截取surfaceview的实时图像:
本文使用了zxing1.6的core,即把/zxing-1.6/core/下的src复制覆盖工程的src;另外还要使用到/zxing-1.6/android/下的planaryuvluminancesource.java。
此处需要注意:/zxing-1.6/android/ 是barcodescanner的源码,本文程序相当于barcodescanner的精简版,只保留最基本的识别功能。
本文完整源码点击此处本地下载。
源码目录结果如下图,checksumexception.java下面还有很多源文件,截图尚未列出:
本文例子必须要开摄像头和自动对焦的权限,不然启动时会报异常,所用的权限如下:
<uses-permission android:name="android.permission.camera"></uses-permission> <uses-permission android:name="android.permission.write_external_storage"></uses-permission> <uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.camera.autofocus" />
main.xml源码如下,main.xml必须要用到framelayout才能重叠控件实现“范围框”的效果:
<?xml version="1.0" encoding="utf-8"?> <framelayout android:id="@+id/framelayout01" android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android"> <surfaceview android:layout_height="fill_parent" android:id="@+id/sfvcamera" android:layout_width="fill_parent"></surfaceview> <relativelayout android:id="@+id/relativelayout01" android:layout_height="fill_parent" android:layout_width="fill_parent"> <imageview android:id="@+id/imageview01" android:layout_height="100dip" android:layout_width="160dip"></imageview> <view android:layout_centervertical="true" android:layout_centerhorizontal="true" android:layout_width="300dip" android:background="#55ff6666" android:id="@+id/centerview" android:layout_height="180dip"></view> <textview android:layout_centerhorizontal="true" android:layout_width="wrap_content" android:layout_below="@+id/centerview" android:layout_height="wrap_content" android:text="scanning..." android:id="@+id/txtscanresult" android:textcolor="#ff000000"></textview> </relativelayout> </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类调用。
ps:本站还提供了一个功能非常强大的二维码生成工具,感兴趣的朋友可以参考一下:
希望本文实例对大家学习android程序设计能有所帮助。