首先,我们先把zxing的源代码给下载下来,这个网上有很多,我下载的是2.3的,不得不说这个谷歌提供的包包含的功能还是很全面的。
我把下载的包解压后,找到android文件夹,导入到ecplise中,我们来分析一下,里面的架构
一、book,如果查询的结果是图书信息,用户可以选择查询该书的进一步详细信息,该包,包含了搜索与展示书籍的相关类。
二、camera/camera.open 这个一个关于摄像头的类,核心类是CameraManager
三、clipboard 剪贴板
四、encode:编码功能的各个组件集合,核心类为QRCodeEncoder,最终实施编码的是MultiFormatWriter类
五、history:扫描历史管理,核心类是HistoryManager
六、result: 条形码扫描的结果被分为不同的类型,所有的类型,都定义在com.google.zxing.client.result.ParsedResultType中,对于不同的类型都有对应的处理方法;xxxResultHandler,所有的ResultHandler都包含在此包中。不同的xxxResultHandler还提供了扫描结果页面要展示几个button,每个button的文本及需要绑定的事件等等
我们先从相机的源码部分开始分析,因为我只会用到扫描和输出结果部分,其它的部分将会去掉
相机部分一共有六个类,分别是
OpenCameraInterface :打开相机类
CameraConfigurationManager:相机配置类
CameraManager: 核心类,相机管理类
AutoFocusManager:暂时没有看
FrontLightMode:枚举
PreviewCallback:预览回调类
一、OpenCameraInterface,这是一个摄像头打开的类,里面的方法为open(),即打开摄像头,我注释了一下
public static Camera open() { // 获取摄像头的数量 int numCameras = Camera.getNumberOfCameras(); //如果没有找到相机则退出 if (numCameras == 0) { Log.w(TAG, "No cameras!"); return null; } int index = 0; while (index < numCameras) { //初始化相机信息类 Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); //获取相机的信息 Camera.getCameraInfo(index, cameraInfo); //判断是否是后置摄像头 if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) { break; } index++; } //打开相机 Camera camera; if (index < numCameras) { Log.i(TAG, "Opening camera #" + index); camera = Camera.open(index); } else { Log.i(TAG, "No camera facing back; returning camera #0"); camera = Camera.open(0); } return camera; }
从这个方法中把摄像头打开
二、CameraConfigurationManager摄像头配置类,在这个类中主要是配置了预览分辨率、闪光灯和焦点等参数
下面的方法主要有 initFromCameraParameters(),通过调findBestPreviewSizeValue方法,来获取最佳的相机预览分辨率
void initFromCameraParameters(Camera camera) { //获取相机的参数 Camera.Parameters parameters = camera.getParameters(); WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); Display display = manager.getDefaultDisplay(); //构造一个点 Point theScreenResolution = new Point(); //给点进行赋值,屏幕的宽和高 Resolution分辨率的意思 display.getSize(theScreenResolution); screenResolution = theScreenResolution; Log.i(TAG, "Screen resolution: " + screenResolution); cameraResolution = findBestPreviewSizeValue(parameters, screenResolution); Log.i(TAG, "Camera resolution: " + cameraResolution); }
setDesiredCameraParameters() 方法,设置相机的闪光灯和焦点等参数
findBestPreviewSizeValue() 方法,去除掉不合适的分辨率,来选择最佳的分辨率
三、CameraManager是整个摄像头的核心类,另外几个类都是在这个类中调用的,用它来对相机的初始化和参数进行统一的管理
openDriver方法()
public synchronized void openDriver(SurfaceHolder holder) throws IOException { Camera theCamera = camera; if (theCamera == null) { theCamera = OpenCameraInterface.open(); if (theCamera == null) { throw new IOException(); } camera = theCamera; } //设置摄像头预览功能 theCamera.setPreviewDisplay(holder); //初始化执行的操作 if (!initialized) { initialized = true; //初始化相机的参数,选择最佳的预览分辨率 configManager.initFromCameraParameters(theCamera); if (requestedFramingRectWidth > 0 && requestedFramingRectHeight > 0) { setManualFramingRect(requestedFramingRectWidth, requestedFramingRectHeight); requestedFramingRectWidth = 0; requestedFramingRectHeight = 0; } } Camera.Parameters parameters = theCamera.getParameters(); String parametersFlattened = parameters == null ? null : parameters.flatten(); // Save these, temporarily try { //设置必要的参数,包括焦点,闪光灯等 configManager.setDesiredCameraParameters(theCamera, false); } catch (RuntimeException re) { // Driver failed Log.w(TAG, "Camera rejected parameters. Setting only minimal safe-mode parameters"); Log.i(TAG, "Resetting to saved camera params: " + parametersFlattened); // Reset: if (parametersFlattened != null) { parameters = theCamera.getParameters(); parameters.unflatten(parametersFlattened); try { theCamera.setParameters(parameters); configManager.setDesiredCameraParameters(theCamera, true); } catch (RuntimeException re2) { // Well, darn. Give up Log.w(TAG, "Camera rejected even safe-mode parameters! No configuration"); } } } }
以上这些都是Camera的核心方法,我们可以看到,程序是通过调用CaptureActivity来实现运行的,在CaptureActivity中调用了Camera的一些方法,在CaptureActivity中通过initCamera(surfaceHolder);这个方法,开始扫描,最后得到扫描的结果。而布局文件中
<SurfaceView android:id="@+id/preview_view" android:layout_width="fill_parent" android:layout_height="fill_parent"/> <com.google.zxing.client.android.ViewfinderView android:id="@+id/viewfinder_view" android:layout_width="fill_parent" android:layout_height="fill_parent" android:visibility="gone" />
一个是预览的窗口,一个是用来自定义显示的扫描的窗口。到此,就总结完了,基本上弄懂了它是怎么运行的,以及Camera的核心方法的作用。