Android 二维码 生成和识别二维码 附源码下载
今天讲一下目前移动领域很常用的技术——二维码。现在大街小巷、各大网站都有二维码的踪迹,不管是ios、android、wp都有相关支持的软件。之前我就想了解二维码是如何工作,最近因为工作需要使用相关技术,所以做了初步了解。今天主要是讲解如何使用zxing库,生成和识别二维码。这篇文章实用性为主,理论性不会讲解太多,有兴趣可以自己查看源码。
1、zxing库介绍
这里简单介绍一下zxing库。zxing是一个开放源码的,用java实现的多种格式的1d/2d条码图像处理库,它包含了联系到其他语言的端口。zxing可以实现使用手机的内置的摄像头完成条形码的扫描及解码。该项目可实现的条形码编码和解码。目前支持以下格式:upc-a,upc-e、ean-8,ean-13、39码、93码。zxing是个很经典的条码/二维码识别的开源类库,以前在功能机上,就有开发者使用j2me运用zxing了,不过要支持jsr-234规范(自动对焦)的手机才能发挥其威力。
下面是zxing的demo运行,我这里创建了一个二维码,大伙可以用微信的扫一扫功能,试一下。就可以直接打开下面的网址。
2、zxing库主要类
下面给大家介绍一下,zxing库里面主要的类以及这些类的作用:
captureactivity。这个是启动activity 也就是扫描器。
captureactivityhandler 解码处理类,负责调用另外的线程进行解码。
decodethread 解码的线程。
com.google.zxing.client.android.camera 包,摄像头控制包。
viewfinderview 自定义的view,就是我们看见的拍摄时中间的框框了。
3、使用zxing生成二维码
下面针对二维码生成和解析做个简单介绍,至于详细的使用方法,建议大家还是自己看看源码,使用起来很简单,不过这个开源项目的代码,值得好好看看。首先给出二维码生成的方法:
//要转换的地址或字符串,可以是中文 public void createqrimage(string url) { try { //判断url合法性 if (url == null || "".equals(url) || url.length() < 1) { return; } hashtable<encodehinttype, string> hints = new hashtable<encodehinttype, string>(); hints.put(encodehinttype.character_set, "utf-8"); //图像数据转换,使用了矩阵转换 bitmatrix bitmatrix = new qrcodewriter().encode(url, barcodeformat.qr_code, qr_width, qr_height, hints); int[] pixels = new int[qr_width * qr_height]; //下面这里按照二维码的算法,逐个生成二维码的图片, //两个for循环是图片横列扫描的结果 for (int y = 0; y < qr_height; y++) { for (int x = 0; x < qr_width; x++) { if (bitmatrix.get(x, y)) { pixels[y * qr_width + x] = 0xff000000; } else { pixels[y * qr_width + x] = 0xffffffff; } } } //生成二维码图片的格式,使用argb_8888 bitmap bitmap = bitmap.createbitmap(qr_width, qr_height, bitmap.config.argb_8888); bitmap.setpixels(pixels, 0, qr_width, 0, 0, qr_width, qr_height); //显示到一个imageview上面 sweepiv.setimagebitmap(bitmap); } catch (writerexception e) { e.printstacktrace(); } }
上面就是二维码生成的方法接口,如果你只是使用者方法,很简单,只要传入一个url即可,就像我截图里面一样,传入一个合法的网址即可。或者像现在一些移动app的推广,把app下载地址转为二维码,只要扫一下就可以下载相应的app。这个也是目前比较流行的app的推广方式。
上面代码做的事情不多,主要是调用zxing库里面qrcodewriter().encode的方法对我们传进去的url进行编码,具体如何编码,这个我这里就不详细说,有兴趣可以看zxing的源码。文章最后会给出zxing的源码和例子代码。
4、扫描二维码获取信息
扫描获取二维码信息的工作稍微复杂一些,主要是需要编写camera的使用,这个跟我们一般使用camera一样,需要使用surfaceview作为预览,这一部我这里就不说了,这个应该不是太复杂。对于使用过camera做预览的朋友,应该是挺简单的事情。获取二维码数据的关键处理是在camera的自动对焦回调函数哪里,调用zxing的解码接口。
private void restartpreviewanddecode() { if (state == state.success) { state = state.preview; cameramanager.get().requestpreviewframe(decodethread.gethandler(), r.id.decode); cameramanager.get().requestautofocus(this, r.id.auto_focus); activity.drawviewfinder(); } }
这里稍微多说一句,由于解码需要一定时间,所以zxing的解码调用,都是使用了handler作为线程通信机制,解码的工作都是放在独立线程里面使用的,如果你直接在主线程解码,恐怕anr问题是避免不了。
public void handlemessage(message message) { switch (message.what) { case r.id.auto_focus: //log.d(tag, "got auto-focus message"); // when one auto focus pass finishes, start another. this is the closest thing to // continuous af. it does seem to hunt a bit, but i'm not sure what else to do. if (state == state.preview) { cameramanager.get().requestautofocus(this, r.id.auto_focus); } break; case r.id.restart_preview: log.d(tag, "got restart preview message"); restartpreviewanddecode(); break; case r.id.decode_succeeded: //解码成功,获取到界面的结果和原来的二维码数据 log.d(tag, "got decode succeeded message"); state = state.success; bundle bundle = message.getdata(); bitmap barcode = bundle == null ? null : (bitmap) bundle.getparcelable(decodethread.barcode_bitmap); activity.handledecode((result) message.obj, barcode); break; case r.id.decode_failed: // we're decoding as fast as possible, so when one decode fails, start another. state = state.preview; cameramanager.get().requestpreviewframe(decodethread.gethandler(), r.id.decode); break; case r.id.return_scan_result: log.d(tag, "got return scan result message"); activity.setresult(activity.result_ok, (intent) message.obj); activity.finish(); break; case r.id.launch_product_query: log.d(tag, "got product query message"); string url = (string) message.obj; intent intent = new intent(intent.action_view, uri.parse(url)); intent.addflags(intent.flag_activity_clear_when_task_reset); activity.startactivity(intent); break; } }
上面是解码的线程处理不同状态的时候需要注意的地方,我们这里只看获取图像成功的地方,成功获取图片解码的实在decodethread里面实现,decodethread里面解码成功后,会把数据序列化,然后保存到bundle里面,我们可以直接通过bundle的序列化,获取到图片数据。同时会把解码后的结果保存到msg里面,然后就可以根据实际情况进行处理,例如上面代码,解码成功后,会调用一个处理函数:
public void handledecode(final result obj, bitmap barcode) { inactivitytimer.onactivity(); playbeepsoundandvibrate(); alertdialog.builder dialog = new alertdialog.builder(this); if (barcode == null) { dialog.seticon(null); } else { drawable drawable = new bitmapdrawable(barcode); dialog.seticon(drawable); } dialog.settitle("扫描结果"); dialog.setmessage(obj.gettext()); dialog.setnegativebutton("确定", new dialoginterface.onclicklistener() { @override public void onclick(dialoginterface dialog, int which) { //用默认浏览器打开扫描得到的地址 intent intent = new intent(); intent.setaction("android.intent.action.view"); uri content_url = uri.parse(obj.gettext()); intent.setdata(content_url); startactivity(intent); finish(); } }); dialog.setpositivebutton("取消", new dialoginterface.onclicklistener() { @override public void onclick(dialoginterface dialog, int which) { finish(); } }); dialog.create().show(); }
上面就是整个二维码的解码流程,里面因为涉及很多camera的使用,所以你如果需要使用二维码识别,需要注意一下你的程序需要申请下面的权限,一般的camera使用以及camera的自动对焦等。
<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" />
5、结语
上面就是生成和识别二维码的关键流程和代码,有兴趣的朋友可以自己查看zxing的源码,里面有很多图像分析的知识可以学习。具体使用也可以参考我下面给出的demo。二维码对于现在移动开发来说很是很常用的技术,所以有空可以了解一下,说不定什么时候就用上了。另外,zxing库除了二维码外,其实对于条形码也是支持的,只是我这里没有介绍。有需要的自己去看看源码即可。
zxing开源项目google code地址:
zxingdemo下载:zxingdemo.rar
以上就是本文的全部内容,希望能给大家一个参考,也希望大家多多支持。
上一篇: indexof 和 indexofany的区别介绍
下一篇: vscode编辑器,自己喜欢的颜色