(抱歉文章还在修改但是不小心发布了= =)
最近在用ZXing这个开源库做二维码的扫描模块,开发过程的一些代码修改和裁剪的经验和大家分享一下。
我的代码库:
https://github.com/SickWorm/ZXingDialog
代码没有在github维护,所以没有log。但是所有修改的地方我都加上了“@ch”的注释,以方便定位
官方源码:
https://github.com/zxing/zxing
实现功能:
1、功能裁剪(只保留QRCode二维码扫描功能,去掉条形码等其他码扫描功能)
2、移除资源依赖,提供Dialog形式的扫码功能
3、API兼容(源码只兼容4.0以上,现兼容至2.1)
4、转换为竖屏(源码为横屏)
5、扫码速度优化(主要分三点,现只完成了一点)
6、设备兼容(针对低分辨率设备)
本文还会提到:
7、自定义界面
8、优化调试方法
ZXing源码并没有提供一个完整的实例工程给我们使用,构建一个工程我们需要源码下的三个文件夹的文件:
core/
android-core/
android/
大概步骤如下:
1、创建一个新工程
2、把android目录下的所有文件覆盖到新工程(内含有资源文件和AndroidManifest.xml等构建app所需的文件)
3、把android-core所有Java文件拷入到src目录下(注意!android-core中的src文件夹需要进行一些改动,原来路径是android-core/src/main/java/com/google/zxing/client/android/camera,我们要把中间的main/java两层文件夹去掉,不然在Eclipse中无法识别包路径)
4、把core目录下的所有Java文件拷入到src目录下(注意!和步骤3一样需要去掉main/java两层文件夹)。这样ZXing已经可以运行了,我的src目录是这样的:
可以直接运行,效果还不错。如果你遇到一些错误,有可能是编译的JDK版本低于1.7导致的。源码里使用了ArrayList<>这样的写法,1.7以前是不支持的。你可以选择修改源码或者提高编译JDK版本。
但你可能不满足于这个界面,扫描框太大了,而且是横屏全屏的,还要求API 15(Android 4.0.3)。下面我们会对这些需求进行修改。
我的目标是只保留二维码识别,不需要其他多余的功能。这一部分的步骤我不打算详细说明,因为我已经不记得了。。大家可以直接看我的代码的结果。
可以直接删掉的是:
com.google.zxing.aztec.** aztec格式的二维码
com.google.zxing.client.android.book.* Google 图书相关的功能
com.google.zxing.client.android.clickboard.* 不清楚,复制黏贴?
com.google.zxing.client.android.encode.* 用于生成各种码
com.google.zxing.client.android.history.* 保存扫码记录
com.google.zxing.client.android.result.** 扫码应用功能相关的功能性代码
com.google.zxing.client.android.share.* 分享功能
com.google.zxing.client.android.wifi.* WiFi相关,不清楚具体用途
com.google.zxing.datamatrix.** datamatrix格式二维码
com.google.zxing.maxicode.** maxicode格式二维码
com.google.zxing.multi.** 貌似是用于多格式支持的?我没有用到这个包,如果有了解的麻烦告知
com.google.zxing.oned.** one dimension一维码,也就是条形码(你去百度搜oned会发现奇怪的东西。。)
com.google.zxing.pdf417.** PDF417格式条形码
需要修改的是:
com.google.zxing.client.android.CaptureActivity:去掉其他功能的相关代码,只保留核心功能,即扫码功能。界面为一个FrameLayout里面包含一个SurfaceView。代码移除就不详细说了,直接看上传的代码吧,这个文件我参考了 http://www.cnblogs.com/keyindex/archive/2011/06/08/2074900.html 这个链接里的CaptureActivity的修改。
com.google.zxing.MultiFormatReader:这个是指定支持解码的格式,需要把除QR_CODE以外的格式全部去掉,否则会因为删掉了解码包而报错。具体也请看上传的代码。
com.google.zxing.client.result.ProductResultParser:parse函数中,同上。
com.google.zxing.client.android.DecodeThread:构造器中,同上。
另外:
com.google.zxing.client.result 我没有删减这个包的代码,应该也是能优化的
经过了第1步的精简,其实只剩下了2个地方需要修改:
1.扫描界面
2.扫描成功时播放的beep声音文件
1:去除了其余功能后,对于核心功能我们只需要一个SurfaceView和一个画界面的View就可以了。代码如下:
/** * use Java code to build layout instead of xml file * @ch */ private void buildLayout() { requestWindowFeature(Window.FEATURE_NO_TITLE); FrameLayout layout = new FrameLayout(this); LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); layout.setLayoutParams(params); surfaceView = new SurfaceView(this); surfaceView.setLayoutParams(params); layout.addView(surfaceView); viewfinderView = new ViewfinderView(this, null); layout.addView(viewfinderView); setContentView(layout); }
ViewfinderView是ZXing自带的View,如果要修改界面,直接修改它就可以了,我们第7点会提到。
2:由于我最终的目的是能打包成jar包,所以beep文件不能放在res里,而是放在assets里。
//待补充
这部分修改在源码中标记为//@ch api compatible。
CaptureActivity.java: //@ch api compatible if (VERSION.SDK_INT < 11) { //surfaceview will push buffer automatically surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } //API 11之前需要手动设置,否则会无法显示。API11之后为默认设置。 CameraConfigurationManager.java: //@ch api compatible if (VERSION.SDK_INT < 13) { theScreenResolution.x = display.getWidth(); theScreenResolution.y = display.getHeight(); } else { display.getSize(theScreenResolution); } //getSize是API 13之后的新API,之前需要用getWidth和getHeight。 AutoFocusManager.java //@ch api compatible if (VERSION.SDK_INT > 11) { newTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } else { newTask.execute(); } //源码中这里设置了多线程的模式,THREAD_POOL_EXECUTOR表示这个task最多只有5个线程同时运行,超过5个的就要等待。在低于API 11的版本中,此为默认选项。其实这里只有单线程,所以随便执行吧。 OpenCameraInterface.java: //@ch api compatible if (VERSION.SDK_INT < 9) { return openWithLowApi(); } ...... /** * for lower than API 9 * @ch api compatible */ public static Camera openWithLowApi() { //If the device does not have a back-facing camera, this returns null Camera camera = Camera.open(); return camera; } //源码的打开摄像头是能区分前后摄像头的,然而API 9之前并没有前置摄像头这个概念,所以做了一下处理
就几个地方,不过也找了我个把小时了。
ZXing默认是横屏,但是我们一般的APP都会做成竖屏,如果扫码的时候强制切换成横屏那样体验就不好了。在修改ZXing的竖屏的时候,我按照的是一般APP的竖屏设置方法,结果发现没有源码的效果好,需要把码放到很小才能完成。后面在调试过程中发现扫码解析的区域和屏幕画出来的区域不一样,才知道这部分的修改出了问题。然后我搜索找到一篇前辈的文章,参考了一下发现没有改完全。