首先,我們先把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的核心方法的作用。