轉載自:http://blog.csdn.net/u010574567/article/details/51916604
*********************1.源碼分析*************************
針對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();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
在restartPreviewAndDecode()中
private void restartPreviewAndDecode() {
if (state == State.SUCCESS) {
state = State.PREVIEW;
cameraManager.requestPreviewFrame(decodeThread.getHandler(), R.id.decode);
activity.drawViewfinder();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
如果狀態是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);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
相機的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);
- 1
- 1
進而我們看handleDecode類
public void handleDecode(Result rawResult, Bitmap barcode, float scaleFactor) {
inactivityTimer.onActivity();
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;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
源碼中一些類的簡單介紹,詳細介紹在以後具體項目中再做詳述。
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。
*****************2.jar包導入Android Studio*****************
如果項目中沒有看到libs文件夾,把項目目錄切換到project而不是Android目錄 然後新建文件夾libs
首先是官方鏈github源碼鏈接 注意在Branch裏面選擇版本,這裏以3.2.1最新版爲例
https://github.com/zxing/zxing
之後我們下載core.jar 地址在下面,選擇對應版本,注意要與之前的源碼一樣,因爲會有很多改動及函數增加,不同版本會認不到
http://repo1.maven.org/maven2/com/google/zxing/
在README中有一些簡單的介紹,包括支持的語言,支持的code格式,可以去看一下。
對Android來說,只有android-core、android、android-integration、androidteset有用(由於我們直接去下core.jar 所以core文件夾裏的內容可以不用去管了)
android-integration 提供了一種簡單的方式將掃碼整合到調用的應用中
androidtest是模擬調用方
android文件裏面是一整個demo,包含識別多種格式的條形碼,多國語言,二維碼分享,建有掃描歷史數據庫,還包括一些輔助功能如燈光、震動、聲音、聯網查詢書籍等等,在下一篇源碼分析當中再做介紹。
這裏我們只關心android 這個demo,所以直接導入android文件夾到AS裏,然後在project中新建libs文件夾(一般是沒有的),然後把我們下載的core-3.2.1.jar粘貼進來,然後右鍵jar文件,點擊add as library,然後發現我們可以去查看jar庫裏的文件了。
這裏有可能出現問題,注意查看project structure裏面是否正確的導入了。
之後我們將android-core文件夾裏的CameraConfigurationUtils.java文件拷到com.google.zxing.client.android/camera中
如圖,應該現在可以運行了。