【Android】条形码/二维码扫描——ZXing源码分析
2016-07-15 12:07
435 查看
正在更新中
针对3.2.1版本源码 与其他版本代码可能会有出入,但核心思想基本不变。
首先从com.google.zxing.client.android包中的目录结构分析:
BrowseBookListener 实现了adapter的点击事项响应,通过获取ISBN,然后跳转到Google books中查询响应的详细信息。
SearchBookContentsActivity 通过google books查询图书相关信息的具体实现
SearchBookContentsAdapter,SearchBookContentsListItem 为listview的适配器和item类的内容,这在之前的文章中介绍过,不再赘述。
SearchBookContentsResult 包含了searchbookcontent类的基本内容,成员变量及get、set方法等
CameraFacing 枚举变量 值为0代表后置摄像头、1代表前置摄像头
OpenCamera 表示一个已打开的摄像头,同时保存着camera的原始数据CameraInfo以及摄像头朝向、方位等信息。
OpenCameraInterface 帮助我们打开摄像头的一个类,如果没有特殊偏好,默认打开后置摄像头。
AutoFocusManager自动对焦相关的函数
CameraConfigurationManager initFromCameraParameters通过屏幕分辨率和相机分辨率,去寻找最合适的预览分辨率。 setDesiredCameraParameters读取配置设置相机的对焦模式、闪光灯模式以及屏幕到相机的转动角度等信息
CameraConfigurationUtils 配置android相机的一些方法
FrontLightMode 枚举闪光灯是否开启
CameraManager camera的核心类,其他类都是在这里调用的。openDriver用于camera的打开及初始化。
PreviewCallback 回调类,当扫描到结果时会调用这个类返回结果。
WifiConfigManager 网络配置管理,修改网络类型等内容。
AmbientLightManager
—根据外界光线情况选择是否打开闪光灯补光
BeepManager
—管理声音
CaptureActivity ———程序的主入口
在restartPreviewAndDecode()中
如果状态是SUCCESS将会开始绘制预览框,通过调用viewfinderView.drawViewfinder();
相机的preview界面显示出来后即可开始扫描,所以需要监听preview是否已经显示这个事件,这就是Camera.PreviewCallback的作用。PreviewCallback.onPreviewFrame做的事便是当preview界面展示出来的时候向DecodeHandler发送一个decode消息,DecodeHandler收到该消息后会执行decode方法来解码。
注意,检测并触发捕获画面动作的,是Camera.setOneShotPreviewCallback()这个方法。该函数被调用后,如果预览界面已经打开,就会将包含当前preview
frame的byte数组传给回调函数,此时再向DecodeHandler发送decode消息。
DecodeHandler
得到了扫描的结果,调用handleDecode进行解码
进而我们看handleDecode类
源码中一些类的简单介绍,详细介绍在以后具体项目中再做详述。
Rect类:用于表示一个矩形区域,并可以对这个区域进行一些操作。有4个参数代表4个边缘(left, top, right,bottom),要注意的是left,top是包含的,而right,bottom是不包含的。例如(20,10,50,100)指的是(20,10)到(49,99)这个矩形区域的内容。
WindowManager类:http://blog.csdn.net/xieqibao/article/details/6567814这里有比较精炼的介绍,就不多说了。
Display类: 引用Display.java中的注释
Provides information about the size and density of a logical display.
A logical display does not necessarily represent a particular physical display device such as the built-in screen or an external monitor. The contents of a logical display may be presented on one or more physical displays according to the devices that are currently attached and whether mirroring has been enabled.
其中有个很重要的getRotation()方法,由于官方demo只能横屏,所以需要理解后进行修改。
这里返回的Surface.ROTATION_X(X=0,90,180,270) 值得是图像要弥补渲染所需要顺时针转动的角度,他和设备所处的转动角度是相反的。比如设备竖直朝上是一开始的位置,将设备逆时针旋转90度,图像为了保持不变,需要顺时针旋转90度,所以这样rotation的值就是Surface.ROTATION_90。
针对3.2.1版本源码 与其他版本代码可能会有出入,但核心思想基本不变。
首先从com.google.zxing.client.android包中的目录结构分析:
Book:
这个文件夹中有5个类:BrowseBookListener 实现了adapter的点击事项响应,通过获取ISBN,然后跳转到Google books中查询响应的详细信息。
SearchBookContentsActivity 通过google books查询图书相关信息的具体实现
SearchBookContentsAdapter,SearchBookContentsListItem 为listview的适配器和item类的内容,这在之前的文章中介绍过,不再赘述。
SearchBookContentsResult 包含了searchbookcontent类的基本内容,成员变量及get、set方法等
Camera
这是一个控制摄像头的类,open文件中是打开摄像头及一些配置方法,open文件夹外面的是一些camera属性的操作。CameraFacing 枚举变量 值为0代表后置摄像头、1代表前置摄像头
OpenCamera 表示一个已打开的摄像头,同时保存着camera的原始数据CameraInfo以及摄像头朝向、方位等信息。
OpenCameraInterface 帮助我们打开摄像头的一个类,如果没有特殊偏好,默认打开后置摄像头。
AutoFocusManager自动对焦相关的函数
CameraConfigurationManager initFromCameraParameters通过屏幕分辨率和相机分辨率,去寻找最合适的预览分辨率。 setDesiredCameraParameters读取配置设置相机的对焦模式、闪光灯模式以及屏幕到相机的转动角度等信息
CameraConfigurationUtils 配置android相机的一些方法
FrontLightMode 枚举闪光灯是否开启
CameraManager camera的核心类,其他类都是在这里调用的。openDriver用于camera的打开及初始化。
PreviewCallback 回调类,当扫描到结果时会调用这个类返回结果。
Cliboard
ClipboardInterface 剪贴板接口,实现内容的复制粘贴Encode
根据内容实现各种格式的从新编码History
历史扫描记录,这里google采用了数据库的存储方式并用listView显示出来,基本与作者之前的文章一致,可以看数据库操作 和 listview显示Result
result文件夹下内容很多,首先看入口ResultHandlerFactory这个类。他根据条形码的类型启动不同的Handler,具体的类型可以看ParsedResultType这个枚举中的内容,每个Handler具体就不介绍了。Share
主要实现分享app应用,书签等内容Wifi
NetworkType 网络类型枚举类WifiConfigManager 网络配置管理,修改网络类型等内容。
AmbientLightManager
—根据外界光线情况选择是否打开闪光灯补光
BeepManager
—管理声音
CaptureActivity ———程序的主入口
CaptureActivityHandler(CaptureActivity activity, Collection<BarcodeFormat> decodeFormats, Map<DecodeHintType,?> baseHints, String characterSet, CameraManager cameraManager) { this.activity = activity; //启动扫描解码线程 decodeThread = new DecodeThread(activity, decodeFormats, baseHints, characterSet, new ViewfinderResultPointCallback(activity.getViewfinderView())); decodeThread.start(); state = State.SUCCESS; // Start ourselves capturing previews and decoding. //开启预览框 this.cameraManager = cameraManager; cameraManager.startPreview(); //preview回调函数与DecodeHandler绑定、绘制扫描框 restartPreviewAndDecode(); }
在restartPreviewAndDecode()中
private void restartPreviewAndDecode() { if (state == State.SUCCESS) { state = State.PREVIEW; cameraManager.requestPreviewFrame(decodeThread.getHandler(), R.id.decode); activity.drawViewfinder(); } }
如果状态是SUCCESS将会开始绘制预览框,通过调用viewfinderView.drawViewfinder();
public synchronized void requestPreviewFrame(Handler handler, int message) { OpenCamera theCamera = camera; if (theCamera != null && previewing) { previewCallback.setHandler(handler, message); theCamera.getCamera().setOneShotPreviewCallback(previewCallback); } }
相机的preview界面显示出来后即可开始扫描,所以需要监听preview是否已经显示这个事件,这就是Camera.PreviewCallback的作用。PreviewCallback.onPreviewFrame做的事便是当preview界面展示出来的时候向DecodeHandler发送一个decode消息,DecodeHandler收到该消息后会执行decode方法来解码。
注意,检测并触发捕获画面动作的,是Camera.setOneShotPreviewCallback()这个方法。该函数被调用后,如果预览界面已经打开,就会将包含当前preview
frame的byte数组传给回调函数,此时再向DecodeHandler发送decode消息。
DecodeHandler
得到了扫描的结果,调用handleDecode进行解码
activity.handleDecode((Result) message.obj, barcode, scaleFactor);
进而我们看handleDecode类
public void handleDecode(Result rawResult, Bitmap barcode, float scaleFactor) { inactivityTimer.onActivity 4000 (); lastResult = rawResult; //根据扫描结果 调用resulthandler工厂分析类型 ResultHandler resultHandler = ResultHandlerFactory.makeResultHandler(this, rawResult); boolean fromLiveScan = barcode != null; if (fromLiveScan) { //加入历史 historyManager.addHistoryItem(rawResult, resultHandler); // Then not from history, so beep/vibrate and we have an image to draw on beepManager.playBeepSoundAndVibrate(); drawResultPoints(barcode, scaleFactor, rawResult); } switch (source) { case NATIVE_APP_INTENT: case PRODUCT_SEARCH_LINK: handleDecodeExternally(rawResult, resultHandler, barcode); break; case ZXING_LINK: if (scanFromWebPageManager == null || !scanFromWebPageManager.isScanFromWebPage()) { handleDecodeInternally(rawResult, resultHandler, barcode); } else { handleDecodeExternally(rawResult, resultHandler, barcode); } break; case NONE: SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); if (fromLiveScan && prefs.getBoolean(PreferencesActivity.KEY_BULK_MODE, false)) { Toast.makeText(getApplicationContext(), getResources().getString(R.string.msg_bulk_mode_scanned) + " (" + rawResult.getText() + ')', Toast.LENGTH_SHORT).show(); // Wait a moment or else it will scan the same barcode continuously about 3 times restartPreviewAfterDelay(BULK_MODE_SCAN_DELAY_MS); } else { //将结果显示出来 handleDecodeInternally(rawResult, resultHandler, barcode); } break; } }
源码中一些类的简单介绍,详细介绍在以后具体项目中再做详述。
Rect类:用于表示一个矩形区域,并可以对这个区域进行一些操作。有4个参数代表4个边缘(left, top, right,bottom),要注意的是left,top是包含的,而right,bottom是不包含的。例如(20,10,50,100)指的是(20,10)到(49,99)这个矩形区域的内容。
WindowManager类:http://blog.csdn.net/xieqibao/article/details/6567814这里有比较精炼的介绍,就不多说了。
Display类: 引用Display.java中的注释
Provides information about the size and density of a logical display.
A logical display does not necessarily represent a particular physical display device such as the built-in screen or an external monitor. The contents of a logical display may be presented on one or more physical displays according to the devices that are currently attached and whether mirroring has been enabled.
其中有个很重要的getRotation()方法,由于官方demo只能横屏,所以需要理解后进行修改。
这里返回的Surface.ROTATION_X(X=0,90,180,270) 值得是图像要弥补渲染所需要顺时针转动的角度,他和设备所处的转动角度是相反的。比如设备竖直朝上是一开始的位置,将设备逆时针旋转90度,图像为了保持不变,需要顺时针旋转90度,所以这样rotation的值就是Surface.ROTATION_90。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories