這是個(gè)人對(duì)Zxing的一些流程上的梳理,后續(xù)繼續(xù)完善
CaptureActivity主流程梳理:
onResume中會(huì)對(duì)來(lái)源做判斷,如果想要修改掃描框的大小可以做如下操作:
//在action里添加"com.google.zxing.client.android.SCAN"
//傳遞對(duì)應(yīng)的大小、decodeFormats、decodeHints等
取出對(duì)應(yīng)的decodeFormats
Intents.Scan.FORMATS — 支持的格式,使用英文 “, ” 分隔,包括以下的格式:
AZTEC,
CODABAR,
CODE_39,
CODE_93,
CODE_128,
DATA_MATRIX,
EAN_8,
EAN_13,
ITF,
MAXICODE,
PDF_417,
QR_CODE,
RSS_14,
RSS_EXPANDED,
UPC_A,
UPC_E,
UPC_EAN_EXTENSION;
這些格式會(huì)在 DecodeFormatManager 中去解析,具體可以看 parseDecodeFormats 和 parseDecodeFormats 方法,這里有一個(gè)比較好用的解析技巧:
Arrays.asList(COMMA_PATTERN.split(scanFormatsString)); //通過(guò)","把所有的數(shù)據(jù)格式化成list
Set<BarcodeFormat> formats = EnumSet.noneOf(BarcodeFormat.class); //創(chuàng)建一個(gè)空的枚舉類
for (String format : scanFormats) {
formats.add(BarcodeFormat.valueOf(format)); //valueOf方法會(huì)把一個(gè)String類型的名稱轉(zhuǎn)變成枚舉項(xiàng)
}
解析對(duì)應(yīng)的decodeHints
如果想要定制的自定義的decodeHints,也可以包到 intent里面?zhèn)鬟M(jìn)來(lái)。可以通過(guò)intent.putExtra(hintType, type) 來(lái)傳輸,具體詳情可以看:DecodeHintType 這個(gè)類
,不過(guò) DecodeHintType.CHARACTER_SET DecodeHintType.NEED_RESULT_POINT_CALLBACK DecodeHintType.POSSIBLE_FORMATS 不在這里進(jìn)行解析
解析掃描的寬度和高度等
通過(guò) Intents.Scan.WIDTH 和 Intents.Scan.HEIGHT 來(lái)獲取對(duì)應(yīng)寬長(zhǎng)
通過(guò) Intents.Scan.CAMERA_ID 來(lái)獲取前置攝像頭掃描還是后置攝像頭掃描
通過(guò) Intents.Scan.PROMPT_MESSAGE 來(lái)設(shè)置界面上的提示信息
設(shè)置對(duì)應(yīng)的Intents.Scan.CHARACTER_SET
通過(guò) Intents.Scan.CHARACTER_SET 來(lái)設(shè)置
初始化SurfaceView和camera
注冊(cè)surface 回調(diào)函數(shù),在surfaceCreated中使用SurfaceHolder(可以了解下surfaceholder) 來(lái)調(diào)用 initCamera
initCamera
通過(guò)CameraManager的openDriver函數(shù)來(lái)初始化攝像頭參數(shù)等,OpenCamera 是用來(lái)抽象一個(gè)邏輯的攝像頭;
1.1 通過(guò)OpenCameraInterface 打開(kāi)了一個(gè)攝像頭
1.2 configManager:initFromCameraParameters 來(lái)根據(jù)surceView的displayRotation旋轉(zhuǎn)角度來(lái)匹配攝像頭的參數(shù),findBestPreviewSizeValue 來(lái)確定最佳的預(yù)覽分辨率
1.3 setManualFramingRect 設(shè)置掃描框的寬高
1.4 configManager:setDesiredCameraParameters 真正把配置設(shè)置到Camera中
1.5 通過(guò)camera 的 setPreviewDisplay(holder) 來(lái)對(duì)接攝像頭和surfaceview初始化CaptureActivityHandler來(lái)啟動(dòng)攝像頭預(yù)覽
2.1 啟動(dòng)解碼的線程 ,這個(gè)線程里面會(huì)啟動(dòng)一個(gè)DecodeHandler,activity可以通過(guò)這個(gè)handler和線程通信
2.2 restartPreviewAndDecode -> cameraManager的requestPreviewFrame 此時(shí)持有decode的handler,可以和decodeThread通信 -> 在camera的PreviewCallback回調(diào)函數(shù)onPreviewFrame 中 會(huì)向decodeThread 發(fā)送解碼的data和resolution,這樣decodeThread就會(huì)去解碼
2.3 ViewfinderView 通過(guò) drawViewfinder 繪制取景框和掃描線開(kāi)始實(shí)時(shí)掃描并解碼
其中說(shuō)到cameraManager中會(huì)將實(shí)時(shí)的圖像發(fā)送到解碼的handler中去,DecodeHandler會(huì)調(diào)用 decode 來(lái)解碼
3.1 通過(guò)cameraManager中buildLuminanceSource 來(lái)獲取到取景框中的數(shù)據(jù)
3.2 通過(guò)new BinaryBitmap(new HybridBinarizer(source)) 把數(shù)據(jù)轉(zhuǎn)換成bitmap
3.3 通過(guò)multiFormatReader中的decodeWithState函數(shù)就能解碼圖片(以后如果想直接解碼圖片可以直接使用這個(gè)函數(shù),對(duì)應(yīng)的,也有multiFormatWriter可以直接生成二維碼)
3.4 掃描成功,壓縮掃碼成功后的預(yù)覽圖片并發(fā)送相應(yīng)消息到CaptureActivityHandler中CaptureActivityHandler 處理掃描成功或者失敗消息
4.1 收到R.id.decode_succeeded,回調(diào)到activity中處理,可以跳轉(zhuǎn)到相應(yīng)的地方等
4.2 收到R.id.decode_failed,直接調(diào)用 requestPreviewFrame 重啟掃描
繪制可能出現(xiàn)的點(diǎn)
在看到掃描的時(shí)候?qū)赡苁嵌S碼地方會(huì)有一個(gè)黃點(diǎn)出現(xiàn),這是怎么實(shí)現(xiàn)的呢?
這是在解碼的時(shí)候會(huì)在hint加一個(gè)參數(shù)叫做ResultPointCallback, 而 reader在解碼的時(shí)候就會(huì)回調(diào)這個(gè)Callback的foundPossibleResultPoint函數(shù),而viewfinderView就會(huì)在界面上畫(huà)出對(duì)應(yīng)的點(diǎn)
OnPause
- OnPause首先會(huì)調(diào)用 quitSynchronously 這將中止攝像頭的預(yù)覽stopPreview 并退出decodeThread
- 然后會(huì)暫停一些傳感器的響應(yīng),release攝像頭的持有
- 最后remove掉surfaceView的callback