Android中的二维码生成与扫描功能
0. 前言
今天这篇文章主要描述二维码的生成与扫描,使用目前流行的zxing,为什么要讲二维码,因为二维码太普遍了,随便一个android app都会有二维码扫描。本篇旨在帮助有需求的同学快速完成二维码生成和扫描的功能。
1. zxing的使用
从github上下载项目后,可以看到整体代码结构如下:
我们只需将zxing包下的所有代码copy一份到我们的项目中去,除了这些还需要zxing的jar包,最后相应的资源文件,包括values文件下的ids文件、raw文件中的资源文件(可以替换)、layout文件下的activity_capture.xml(可以进行相应的订制) 和图片资源。
2. 生成二维码的实现
等上面工作全部准备完毕后,就可以创建我们的二维码了。如何生成二维码?
需要encodingutils这个二维码生成工具类。通过调用工具类中的createqrcode()方法来生成二维码。该方法参数介绍如下:
/* * content:二维码内容 * widthpix:二维码宽度 * heightpix:二维码高度 * logobm:二维码中间的logo对应的bitmap */ public static bitmap createqrcode(string content, int widthpix, int heightpix, bitmap logobm)
下面完成的是生成的一个百度地址的二维码,中间logo是android小机器人。并保存图片到本地,方便后续测试二维码的本地读取功能。
/** * 创建、展示二维码并将bitmap保存在本地 */ private void create() { int width = densityutil.dip2px(this, 200); bitmap bitmap = encodingutils.createqrcode("http://www.baidu.com", width, width, bitmapfactory.decoderesource(getresources(),r.drawable.ic_launcher)); iv_zxing.setimagebitmap(bitmap); savebitmap(bitmap); } /** * 将bitmap保存在本地 * * @param bitmap */ public void savebitmap(bitmap bitmap) { // 首先保存图片 file appdir = new file(environment.getexternalstoragedirectory(),"zxing_image"); if (!appdir.exists()) { appdir.mkdir(); } string filename = "zxing_image" + ".jpg"; file file = new file(appdir, filename); try { fileoutputstream fos = new fileoutputstream(file); bitmap.compress(compressformat.jpeg, 100, fos); fos.flush(); fos.close(); } catch (exception e) { e.printstacktrace(); } // 把文件插入到系统图库 try { mediastore.images.media.insertimage(this.getcontentresolver(),file.getabsolutepath(), filename, null); } catch (filenotfoundexception e) { e.printstacktrace(); } // 通知图库更新 sendbroadcast(new intent(intent.action_media_scanner_scan_file, uri.parse("file://" + "/sdcard/namecard/"))); }
看到如下效果:
3. 读取二维码的实现
3.1 摄像头扫描的方式
二维码扫描需要借助于captureactivity这个类,打开captureactivity界面并进行扫描,扫描完毕后回调onactivityresult()方法,从onactivityresult()中得到扫描后的结果。效果就不演示的,因为使用的是模拟器。详细代码如下:
/** * 打开二维码扫描 */ private void open() { config(); startactivityforresult(new intent(mainactivity.this,captureactivity.class), 0); } /** * 提高屏幕亮度 */ private void config() { windowmanager.layoutparams lp = getwindow().getattributes(); lp.screenbrightness = 1.0f; getwindow().setattributes(lp); } @override protected void onactivityresult(int requestcode, int resultcode, intent data) { super.onactivityresult(requestcode, resultcode, data); if (resultcode == result_ok) { bundle bundle = data.getextras(); string result = bundle.getstring("result"); tv_result.settext(result); }
3.2 本地图片扫描的方式
扫描本地图片需要我们在captureactivity中进行相应的修改,为此我在扫描界面底部增加了一个按钮,用来选择本地图片。layout代码这里就不展示,我们直接看点击后的事件处理。
/** * 打开本地图片 */ private void openlocalimage() { // 打开手机中的相册 intent innerintent = new intent(intent.action_get_content); innerintent.settype("image/*"); intent wrapperintent = intent.createchooser(innerintent, "选择二维码图片"); this.startactivityforresult(wrapperintent, 0x01); }
打开系统图片库后选择图片,这时需要重写onactivityresult()方法用于返回图片信息。
@override protected void onactivityresult(int requestcode, int resultcode, intent data) { super.onactivityresult(requestcode, resultcode, data); if (resultcode == result_ok) { switch (requestcode) { case 0x01: // 获取选中图片的路径 cursor cursor = getcontentresolver().query(data.getdata(),null, null, null, null); if (cursor.movetofirst()) { photo_path = cursor.getstring(cursor.getcolumnindex(mediastore.images.media.data)); } cursor.close(); new thread(new runnable() { @override public void run() { result result = scanningimage(photo_path); if (result != null) { handledecode(result, new bundle()); } } }).start(); break; } } }
获取图片路径photo_path后,调用scanningimage()方法进行扫描,zxing源码中,扫描到的结果都是存放在result结果集中。获取到result后,就进行结果的回传,阅读captureactivity源码可以得知最后result结果集会传递给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 bundle * the extras */ public void handledecode(result rawresult, bundle bundle) { inactivitytimer.onactivity(); beepmanager.playbeepsoundandvibrate(); intent resultintent = new intent(); bundle.putint("width", mcroprect.width()); bundle.putint("height", mcroprect.height()); bundle.putstring("result", rawresult.gettext()); resultintent.putextras(bundle); this.setresult(result_ok, resultintent); captureactivity.this.finish(); }
获取到图片路径后需要将其二维码信息包装成result对象,因此需要解析图片:
/** * 扫描二维码图片的方法 * * @param path * @return */ public result scanningimage(string path) { if (textutils.isempty(path)) { return null; } hashtable<decodehinttype, string> hints = new hashtable<decodehinttype, string>(); hints.put(decodehinttype.character_set, "utf8"); // 设置二维码内容的编码 bitmapfactory.options options = new bitmapfactory.options(); options.injustdecodebounds = true; // 先获取原大小 scanbitmap = bitmapfactory.decodefile(path, options); options.injustdecodebounds = false; // 获取新的大小 int samplesize = (int) (options.outheight / (float) 200); if (samplesize <= 0) samplesize = 1; options.insamplesize = samplesize; scanbitmap = bitmapfactory.decodefile(path, options); int width = scanbitmap.getwidth(); int height = scanbitmap.getheight(); int[] pixels = new int[width * height]; scanbitmap.getpixels(pixels, 0, width, 0, 0, width, height); /** * 第三个参数是图片的像素 */ rgbluminancesource source = new rgbluminancesource(width, height, pixels); binarybitmap bitmap1 = new binarybitmap(new hybridbinarizer(source)); qrcodereader reader = new qrcodereader(); try { return reader.decode(bitmap1, hints); } catch (notfoundexception e) { e.printstacktrace(); } catch (checksumexception e) { e.printstacktrace(); } catch (formatexception e) { e.printstacktrace(); } return null; }
根据路径获取bitmap,最后通过qrcodereader 中的decode方法解析成result对象并返回,最终传递给handledecode方法。运行程序效果如下,扫描出来的是之前定义的百度地址。
最后不要忘了申明权限和captureactivity。
<uses-permission android:name="android.permission.write_external_storage"/> <uses-permission android:name="android.permission.mount_unmount_filesystems"/> <uses-permission android:name="android.permission.camera"/> <uses-permission android:name="android.permission.vibrate"/> <activity android:name="com.example.zxingtest.zxing.activity.captureactivity"/>
大家可以参考下这篇文章:android实现二维码扫描和生成的简单方法
以上所述是小编给大家介绍的android中的二维码生成与扫描功能,希望对大家有所帮助