ZXing扫码的module化
前言
最近因为因为项目需要,要实现一个二维码扫码功能,作为一个Android开发,首先想到的当然是ZXing,从官网上下载了3.3.3版本,然后本地一编译一运行,可谓是一顿操作猛如虎啊,可惜结果是水土不服,横屏,页面效果,功能过多等等不符合项目需求,于是就走上了项目调整与精简的道路,又考虑到希望后期集成可以更方便的进行,就尝试进行模块化的调整。
一言不合上GIT:ZxingLib
过程
一 移花接木
创建一个项目ZXingLib,然后创建一个Module(ZXingScan),然后把ZXing->android下assets,res,src的内容复制到Module对应目录下。
然后在bulid.gradle下添加如下两个依赖引用
compile 'com.google.zxing:core:3.3.3'
compile 'com.google.zxing:android-core:3.3.0'
并在中配置相关权限申请
在主项目的MainActivity继承CaptureActivity,运行,修改一些报错,直至可以顺利安装。
至此,我们长征的第一步算是顺利达成了。
PS:这边要注意的是因为没有做动态权限认证,相机相关权限可以到设置中手动开启。
二 修剪枝叶
第一步
对上面的一些功能模块整个文件夹,asset文件夹及res下的国际化values都删除。
然后编译并修复一些因为文件删除带来的的报错。主要指CaptureActivity中的一些错误。
handleDecode()方法修改如下
public void handleDecode(Result rawResult, Bitmap barcode, float scaleFactor) {
inactivityTimer.onActivity();
lastResult = rawResult;
}
然后在其中调用的drawResultPoints(),handleDecodeInternally(),handleDecodeExternally()相关方法也进行删除。
第二步
删除余下的不必要的类并进行调整。其中Capture和Decode相关类为核心,需要保留。
另外ViewfinderView主要负责负责扫码界面扫码框及动画处理,接下来打算直接使用xml布局,就把ViewfinderView也删除。移除Preferences相关,设置均设置成默认设置。
精简后的目录结构大概如下
三 精心培育
大枝大叶修改完毕,接下来就是对页面的调整了。
第一步
CaptureActivity中去除除SurfaceView之外所有控件的处理。并添加
protected abstract int getLayoutViewId();
方法,修改onCreate()
setContentView(getLayoutViewId());
同时由主题app提供layout,要注意的是主题app界面中必须要有SurfaceView并且id必须为preview_view
然后在CaptureActivity中设置
public void handleDecode(Result rawResult, Bitmap barcode, float scaleFactor) {
inactivityTimer.onActivity();
onDecodeResult(rawResult, barcode, scaleFactor);
}
protected abstract void onDecodeResult(Result rawResult, Bitmap barcode, float scaleFactor);
这样就可以实现在主题activity中接收结果并处理了。
到现在为止,我们已经可以进行扫码操作了,可还有一个问题就是,现在条码扫描依然是横屏,这里我们就需要进行转换。
我们找到CameraManager类下的buildLuminanceSource()方法,修改如下
return new PlanarYUVLuminanceSource(data, width, height, rect.left, rect.top,
rect.width(), rect.height(), false);
修改为
return new PlanarYUVLuminanceSource(rotateYUVDegree90(data, width, height), height, width, 0, 0,
height, width, false);
其中4、5、6、7参数为解码的范围,我们改成0, 0,height, width,表示全范围扫描,不只限于扫码框范围。
然后height, width表示宽高互换。
并在最后添加
private byte[] rotateYUVDegree90(byte[] data, int imageWidth, int imageHeight) {
byte[] yuv = new byte[imageWidth * imageHeight * 3 / 2];
// Rotate the Y luma
int i = 0;
for (int x = 0; x < imageWidth; x++) {
for (int y = imageHeight - 1; y >= 0; y--) {
yuv[i] = data[y * imageWidth + x];
i++;
}
}
// Rotate the U and V color components
i = imageWidth * imageHeight * 3 / 2 - 1;
for (int x = imageWidth - 1; x > 0; x = x - 2) {
for (int y = 0; y < imageHeight / 2; y++) {
yuv[i] = data[(imageWidth * imageHeight) + (y * imageWidth) + x];
i--;
yuv[i] = data[(imageWidth * imageHeight) + (y * imageWidth) + (x - 1)];
i--;
}
}
return yuv;
}
用于图片数据的转换。
到此为止,基本可以满足大多数手机的扫码需求了。
四 相机显示优化
到现在为止,我们基本可以很快速的进行扫码识别,但是在某些手机上,特别是现在的全面屏手机,因为较高,所以在竖直方向上总有一些拉升,虽然不影响扫码识别,但看起来总是不舒服,就下来就让我们来看看能不能解决这个问题。
首先在CameraConfigurationManager的initFromCameraParameters(OpenCamera camera) 方法中是设置最佳分辨率的地方。代码如下
cameraResolution = CameraConfigurationUtils.findBestPreviewSizeValue(parameters, screenResolution);
Log.i(TAG, "Camera resolution: " + cameraResolution);
bestPreviewSize = CameraConfigurationUtils.findBestPreviewSizeValue(parameters, screenResolution);
Log.i(TAG, "Best available preview size: " + bestPreviewSize);
哪具体选择哪个分辨率为最佳分辨率就需要看CameraConfigurationUtils.findBestPreviewSizeValue()方法了
findBestPreviewSizeValue()方法具体做了说明,了解了之后我们知道需要对入参做处理
修改如下