Android二维码的创建、解析及NotFoundException
来源:互联网 发布:主动刹车 知乎 编辑:程序博客网 时间:2024/06/16 10:28
本篇博客主要记录一下Android生成及解析二维码的基本方法,
同时记录一下遇到的NotFoundException及对应解决方法。
如今很多APK都集成了二维码,其本质不过是将信息按照0、1的方式写入到图片中,
0、1分别对应了不同的颜色。
从APK调用api的角度来看,生成和解析二维码是非常容易的,
真正的难度其实还是在信息的编码及图像的识别上,而这就比较依赖于专业知识了。
对于普通开发者而言,在项目中引用google的支持库后,就能够开发基本的功能了。
我自己写demo时,在Android Studio中引用的支持库为com.google.zxing:core:3.3.0。
整个demo的界面非常简单,如下图所示:
基本功能就是点击GENERATE按键后,在界面下方生成二维码;
点击SCAN按键后,从二维码图片中得到对应的信息。
其中,生成二维码的核心代码如下:
private void generateQRCode() { //得到信息对应的像素数组 int[] pixels = generatePixels(); if (pixels != null) { Bitmap bitmap = Bitmap.createBitmap( QR_WIDTH, QR_HEIGHT, Bitmap.Config.ARGB_8888); //根据像素数组生成bitmap //这部分参数含义查看一下API描述,比较容易弄懂 bitmap.setPixels(pixels, 0, QR_WIDTH, 0, 0, QR_WIDTH, QR_HEIGHT); //将bitmap显示到界面上 mImageView.setImageBitmap(bitmap); mScanButton.setEnabled(true); } }
容易看出,上面代码的重点部分在于生成像素数组。
这部分内容如下所示:
private int[] generatePixels() { //得到需要写入的信息 String data = createData(); int[] pixels = null; //定义编码的附加信息,这里指定以utf-8编码 Hashtable<EncodeHintType, Object> hints = new Hashtable<>(); hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); try { //这里以QRcodeWriter,将信息编码成矩阵 //参数分别为信息、编码格式、矩阵宽、矩阵高及附加信息 BitMatrix bitMatrix = new QRCodeWriter() .encode(data, BarcodeFormat.QR_CODE, QR_WIDTH, QR_HEIGHT, hints); //得到矩阵后,就可以根据矩阵得到像素数组 pixels = new int[QR_WIDTH * QR_HEIGHT]; for (int y = 0; y < QR_HEIGHT; ++y) { for (int x = 0; x < QR_WIDTH; ++x) { //轮寻矩阵的每一个元素 //我在这里比较传统的,用黑白来形成像素数组 //按需可进行调整 pixels[y * QR_WIDTH + x] = bitMatrix.get(x, y) ? Color.BLACK : Color.WHITE; } } } catch (WriterException e) { Log.d("ZJTest", e.toString()); } return pixels; }
最后这一部分是用于生成信息的:
private String createData() { String data = null; try { JSONObject jsonObject = new JSONObject(); jsonObject.put("author", "ZhangJianIsAStark"); jsonObject.put("url", "http://blog.csdn.net/gaugamela"); data = jsonObject.toString(); } catch (JSONException e) { Log.d("ZJTest", e.toString()); } return data; }
可以按照需要写入任何信息,只要最后以String表示即可。
我在这里是以JSONObject的信息,生成String。
按照上述代码,点击GENERATE按键后,就可以得到二维码了,如下图所示:
图中,我的长宽的数值均为1000。
根据上面的代码,我们知道形成二维码的逻辑是:
1、得到String字符;
2、将String字符编码为像素数组;
3、根据像素数组,得到Bitmap。
接下来,我们看看解析二维码的基本方法。
一般像微信扫一扫这样的功能,都依赖于对Camera的操作。
自己对这一块不是很熟,因此是照着其他人的demo学习的,链接如下。
http://www.cnblogs.com/weixing/archive/2013/08/28/3287120.html
这个demo的主体应该是Zxing的示例代码,其中在Android 5.1之后的版本上使用时,
需要修改代码获取Camera的运行时权限。
此外,该demo中Camera的用法太老了,现在都应该使用Camera2的接口,简单看看就好。
在这里我仅记录一下,直接从图像中解析信息的步骤,略去Camera获取图片等操作。
private void scanQRCode() { //将ImageView的drawable转化为BitmapDrawable //然后获取Bitmap Bitmap bitmap = ((BitmapDrawable)mImageView.getDrawable()).getBitmap(); //按比例缩小Bitmap Matrix matrix = new Matrix(); matrix.postScale(0.1f, 0.1f); Bitmap resizeBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); int width = resizeBitmap.getWidth(); int height = resizeBitmap.getHeight(); //从Bitmap中获取像素矩阵 int[] pixels = new int[width * height]; resizeBitmap.getPixels(pixels, 0, width, 0, 0, width, height); //利用像素矩阵得到RGBLuminanceSource //ZXing库中定义了LuminanceSource及其子类 RGBLuminanceSource rgbLuminanceSource = new RGBLuminanceSource(width, height, pixels); //利用LuminanceSource、HybridBinarizer得到BinaryBitmap BinaryBitmap binaryBitmap = new BinaryBitmap( new HybridBinarizer(rgbLuminanceSource)); //定义解码附加信息 Hashtable<DecodeHintType, Object> hints = new Hashtable<>(); hints.put(DecodeHintType.CHARACTER_SET, "utf-8"); try { //利用MultiFormatReader得到解码结果 //本例也可以使用QRCodeReader Result result = new MultiFormatReader().decode(binaryBitmap, hints); try { //利用Result的getText方法获取String对象 //以下是JSONObject的基本解析 JSONObject jsonObject = new JSONObject(result.getText()); String name = jsonObject.getString("author"); String url = jsonObject.getString("url"); Log.d("ZJTest", "name: " + name + ", url: " + url); } catch (JSONException e) { Log.d("ZJTest", e.toString()); } } catch (NotFoundException e) { Log.d("ZJTest", e.toString()); e.printStackTrace(); } }
解析图像后的log信息如下:
03-20 21:41:42.675 5781-5781/stark.a.is.zhang.zxingtest D/ZJTest: name: ZhangJianIsAStark, url: http://blog.csdn.net/gaugamela
与之前写入的一致。
从上面的代码可以看出,二维码的解析,基本上是生成的逆过程:
1、根据Bitmap,得到像素数组;
2、根据像素数组解码出字符;
3、从字符中得到之前写入的信息。
其中解码的过程比较复杂,使用了大量Zxing库中的类。
最后记录一下,写代码遇到的问题。
最初写demo时,自己在解析二维码时,
从ImageView中获取Bitmap后,并没有对Bitmap进行缩小的操作。
于是,遇到了Zxing库抛出的NotFoundException。
自己仔细看了代码,没觉得有什么问题。
结果修改ImageView的宽、高为200以下时,就能正确解析出结果。
根据这个现象,首先推测是否从bitmap获取像素数组时,丢失了部分信息。
于是进行测试,发现在宽、高为1000时,比较生成和解析的像素数组,发现完全一致。
因此,图片与像素数组之间的转换没有问题,应该是Zxing库的原因。
目前的根本原因没有找到,个人推测是否Zxing库限制了像素数组大小的上限,
当像素信息超过上限后,会丢失掉部分信息?
在主动缩小Bitmap后,问题就解决了。
- Android二维码的创建、解析及NotFoundException
- zxing解析二维码--NotFoundException
- android 二维码生成及解析
- 使用zxing解析二维码抛出com.google.zxing.NotFoundException 解决方案
- 二维码及带logo二维码的生成和解析-Zxing
- [Android]Resources NotFoundException的解决
- Android的解析二维码图片实例
- Android之二维码的生成与解析
- Android之二维码的生成与解析
- Android之二维码的生成与解析
- Android之二维码的生成与解析
- Android之二维码的生成与解析
- android二维码的生成与解析
- 使用ZXing创建二维码和解析二维码
- java 创建二维码和解析二维码
- Android二维码登录原理及生成与解析
- android 解析、生成二维码
- Android 解析二维码图片
- Java模式(适配器模式)
- RxJava RxAndroid 入门使用用法 参照博文自己领悟使用解析
- 欢迎使用CSDN-markdown编辑器
- 解决前后台共同写一个页面问题:
- Oracle 自增长主键的处理
- Android二维码的创建、解析及NotFoundException
- FPGA 关于错误(10200)
- mysql设置指定ip访问,用户权限相关操作
- sklearn.svm.SVC 参数说明
- Variant 与 内存泄露
- 关于变量定义时初始化的必要性
- Android渐变色画笔 自定义View渐变色
- win7 下 vs2013 + Qt5.7 程序打包
- java 中静态代码和非静态代码块的区别!