Android 二维码 生成和识别

<p>今天讲一下目前移动领域很常用的技术——二维码。现在大街小巷、各大网站都有二维码的踪迹,不管是IOS、Android、WP都有相关支持的软件。之前我就想了解二维码是如何工作,最近因为工作需要使用相关技术,所以做了初步了解。今天主要是讲解如何使用ZXing库,生成和识别二维码。这篇文章实用性为主,理论性不会讲解太多,有兴趣可以自己查看源码。</p><p></p><p>1、ZXing库介绍</p><p>  这里简单介绍一下ZXing库。ZXing是一个开放源码的,用Java实现的多种格式的1D/2D条码图像处理库,它包含了联系到其他语言的端口。Zxing可以实现使用手机的内置的摄像头完成条形码的扫描及解码。该项目可实现的条形码编码和解码。目前支持以下格式:UPC-A,UPC-E、EAN-8,EAN-13、39码、93码。ZXing是个很经典的条码/二维码识别的开源类库,以前在功能机上,就有开发者使用J2ME运用ZXing了,不过要支持JSR-234规范(自动对焦)的手机才能发挥其威力。</p><p>  下面是ZXing的demo运行,我这里创建了一个二维码,内容是我博客的网址,大伙可以用微信的扫一扫功能,试一下。就可以直接打开我博客。</p><p><img src="/up_pic/201810/301107106839.jpg" title="301107106839.jpg" alt="1.jpg"/></p><p>2、ZXing库主要类</p><p>  下面给大家介绍一下,ZXing库里面主要的类以及这些类的作用:</p><p>CaptureActivity。这个是启动Activity 也就是扫描器。</p><p>CaptureActivityHandler 解码处理类,负责调用另外的线程进行解码。</p><p>DecodeThread 解码的线程。</p><p>com.google.zxing.client.android.camera 包,摄像头控制包。</p><p>ViewfinderView 自定义的View,就是我们看见的拍摄时中间的框框了。</p><p></p><p>3、使用ZXing生成二维码</p><p>  下面针对二维码生成和解析做个简单介绍,至于详细的使用方法,建议大家还是自己看看源码,使用起来很简单,不过这个开源项目的代码,值得好好看看。首先给出二维码生成的方法:</p><pre class="brush:java;toolbar:false">  //要转换的地址或字符串,可以是中文 publicvoidcreateQRImage(Stringurl) { try { //判断URL合法性 if(url==null||&quot;&quot;.equals(url)||url.length()&lt;1) { return; } Hashtable&lt;EncodeHintType,String&gt;hints=newHashtable&lt;EncodeHintType,String&gt;(); hints.put(EncodeHintType.CHARACTER_SET,&quot;utf-8&quot;); //图像数据转换,使用了矩阵转换 BitMatrixbitMatrix=newQRCodeWriter().encode(url,BarcodeFormat.QR_CODE,QR_WIDTH,QR_HEIGHT,hints); int[]pixels=newint[QR_WIDTH*QR_HEIGHT]; //下面这里按照二维码的算法,逐个生成二维码的图片, //两个for循环是图片横列扫描的结果 for(inty=0;y&lt;QR_HEIGHT;y++) { for(intx=0;x&lt;QR_WIDTH;x++) { if(bitMatrix.get(x,y)) { pixels[y*QR_WIDTH+x]=0xff000000; } else { pixels[y*QR_WIDTH+x]=0xffffffff; } } } //生成二维码图片的格式,使用ARGB_8888 Bitmapbitmap=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(WriterExceptione) { e.printStackTrace(); } }</pre><p>上面就是二维码生成的方法接口,如果你只是使用者方法,很简单,只要传入一个URL即可,就像我截图里面一样,传入一个合法的网址即可。或者像现在一些移动APP的推广,把APP下载地址转为二维码,只要扫一下就可以下载相应的APP。这个也是目前比较流行的APP的推广方式。</p><p>  上面代码做的事情不多,主要是调用ZXing库里面QRCodeWriter().encode的方法对我们传进去的URL进行编码,具体如何编码,这个我这里就不详细说,有兴趣可以看ZXing的源码。文章最后会给出ZXing的源码和例子代码。</p><p></p><p>4、扫描二维码获取信息</p><p>  扫描获取二维码信息的工作稍微复杂一些,主要是需要编写Camera的使用,这个跟我们一般使用Camera一样,需要使用Surfaceview作为预览,这一部我这里就不说了,这个应该不是太复杂。对于使用过Camera做预览的朋友,应该是挺简单的事情。获取二维码数据的关键处理是在Camera的自动对焦回调函数哪里,调用ZXing的解码接口。</p><pre class="brush:java;toolbar:false">  privatevoidrestartPreviewAndDecode(){ 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(); } }</pre><p>这里稍微多说一句,由于解码需要一定时间,所以ZXing的解码调用,都是使用了Handler作为线程通信机制,解码的工作都是放在独立线程里面使用的,如果你直接在主线程解码,恐怕ANR问题是避免不了。</p><pre class="brush:java;toolbar:false">publicvoidhandleMessage(Messagemessage){ switch(message.what){ caseR.id.auto_focus: //Log.d(TAG,&quot;Gotauto-focusmessage&quot;); //Whenoneautofocuspassfinishes,startanother.Thisistheclosestthingto //continuousAF.Itdoesseemtohuntabit,butI&#39;mnotsurewhatelsetodo. if(state==State.PREVIEW){ CameraManager.get().requestAutoFocus(this,R.id.auto_focus); } break; caseR.id.restart_preview: Log.d(TAG,&quot;Gotrestartpreviewmessage&quot;); restartPreviewAndDecode(); break; caseR.id.decode_succeeded:     //解码成功,获取到界面的结果和原来的二维码数据 Log.d(TAG,&quot;Gotdecodesucceededmessage&quot;); state=State.SUCCESS; Bundlebundle=message.getData(); Bitmapbarcode=bundle==null?null: (Bitmap)bundle.getParcelable(DecodeThread.BARCODE_BITMAP); activity.handleDecode((Result)message.obj,barcode); break; caseR.id.decode_failed: //We&#39;redecodingasfastaspossible,sowhenonedecodefails,startanother. state=State.PREVIEW; CameraManager.get().requestPreviewFrame(decodeThread.getHandler(),R.id.decode); break; caseR.id.return_scan_result: Log.d(TAG,&quot;Gotreturnscanresultmessage&quot;); activity.setResult(Activity.RESULT_OK,(Intent)message.obj); activity.finish(); break; caseR.id.launch_product_query: Log.d(TAG,&quot;Gotproductquerymessage&quot;); Stringurl=(String)message.obj; Intentintent=newIntent(Intent.ACTION_VIEW,Uri.parse(url)); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); activity.startActivity(intent); break; } }</pre><p>  上面是解码的线程处理不同状态的时候需要注意的地方,我们这里只看获取图像成功的地方,成功获取图片解码的实在DecodeThread里面实现,DecodeThread里面解码成功后,会把数据序列化,然后保存到Bundle里面,我们可以直接通过Bundle的序列化,获取到图片数据。同时会把解码后的结果保存到MSG里面,然后就可以根据实际情况进行处理,例如上面代码,解码成功后,会调用一个处理函数:</p><pre class="brush:java;toolbar:false">  publicvoidhandleDecode(finalResultobj,Bitmapbarcode) { inactivityTimer.onActivity(); playBeepSoundAndVibrate(); AlertDialog.Builderdialog=newAlertDialog.Builder(this); if(barcode==null) { dialog.setIcon(null); } else { Drawabledrawable=newBitmapDrawable(barcode); dialog.setIcon(drawable); } dialog.setTitle(&quot;扫描结果&quot;); dialog.setMessage(obj.getText()); dialog.setNegativeButton(&quot;确定&quot;,newDialogInterface.OnClickListener() { @Override publicvoidonClick(DialogInterfacedialog,intwhich) { //用默认浏览器打开扫描得到的地址 Intentintent=newIntent(); intent.setAction(&quot;android.intent.action.VIEW&quot;); Uricontent_url=Uri.parse(obj.getText()); intent.setData(content_url); startActivity(intent); finish(); } }); dialog.setPositiveButton(&quot;取消&quot;,newDialogInterface.OnClickListener() { @Override publicvoidonClick(DialogInterfacedialog,intwhich) { finish(); } }); dialog.create().show(); }</pre><p>上面就是整个二维码的解码流程,里面因为涉及很多Camera的使用,所以你如果需要使用二维码识别,需要注意一下你的程序需要申请下面的权限,一般的Camera使用以及Camera的自动对焦等。</p><pre class="brush:xml;toolbar:false">&lt;uses-permissionandroid:name=&quot;android.permission.CAMERA&quot;&gt;&lt;/uses-permission&gt; &lt;uses-permissionandroid:name=&quot;android.permission.WRITE_EXTERNAL_STORAGE&quot;&gt;&lt;/uses-permission&gt; &lt;uses-featureandroid:name=&quot;android.hardware.camera&quot;/&gt; &lt;uses-featureandroid:name=&quot;android.hardware.camera.autofocus&quot;/&gt;</pre><p>5、结语</p><p>  上面就是生成和识别二维码的关键流程和代码,有兴趣的朋友可以自己查看ZXing的源码,里面有很多图像分析的知识可以学习。具体使用也可以参考我下面给出的Demo。二维码对于现在移动开发来说很是很常用的技术,所以有空可以了解一下,说不定什么时候就用上了。另外,ZXing库除了二维码外,其实对于条形码也是支持的,只是我这里没有介绍。有需要的自己去看看源码即可。</p><p></p><p>2013-8-16</p><p>Edited by 泡泡糖</p><p>ZXing开源项目Google Code地址:https://code.google.com/p/zxing/</p>
RangeTime:0.008036s
RangeMem:215.6 KB
返回顶部 留言