安卓zxing標(biāo)準(zhǔn)掃描器
文章出處:研維官網(wǎng)人氣:
發(fā)表時(shí)間2019-09-10 09:08:10
zxing是基于多種1D/2D條碼處理的開源庫,是一個(gè)完整的項(xiàng)目。它可以通過手機(jī)攝像頭實(shí)現(xiàn)條碼的掃描以及解碼,功能及其強(qiáng)大。那么如果要實(shí)現(xiàn)二維碼的掃描以及解碼,我們需要在該開源項(xiàng)目的基礎(chǔ)上進(jìn)行簡化,并修改。讓我們來看一下
二維碼掃描結(jié)果
上圖是仿照QQ的掃一掃進(jìn)行修改的zxing項(xiàng)目,以zxing項(xiàng)目為基礎(chǔ),結(jié)合實(shí)際應(yīng)用,這里作了三點(diǎn)改變:
(1)豎屏掃描
(2)自定義取景框
(3)重新定義掃描結(jié)果處理
一、第一步:下載zxing項(xiàng)目,并簡化出掃描框架
1、首先,下載新zxing開源項(xiàng)目。 下載地址:http://code.google.com/p/zxing/
2、分析項(xiàng)目結(jié)構(gòu),明確掃描框架需求。在zxing中,有很多其他的功能,項(xiàng)目結(jié)構(gòu)比較復(fù)雜;針對(duì)二維碼QRCode掃描,我們需要幾個(gè)包:
(1)com.google.zxing.client.android.Camera 基于Camera調(diào)用以及參數(shù)配置,核心包
(2)DecodeFormatManager、DecodeThread、DecodeHandler 基于解碼格式、解碼線程、解碼結(jié)果處理的解碼類
(3)ViewfinderView、ViewfinderResultPointCallBack 基于取景框視圖定義的View類
(4)CaptureActivity、CaptureActivityHandler 基于掃描Activity以及掃描結(jié)果處理的Capture類
(5)InactivityTimer、BeepManager、FinishListener 基于休眠、聲音、退出的輔助管理類
(6)Intents、IntentSource、PrefrencesActivity 基于常量存儲(chǔ)的常量類
3、新建工程,添加如下權(quán)限:
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
permission
添加core.jar文件,并BuildPath;將上述類或包加入工程后,會(huì)報(bào)一系列錯(cuò)誤,原因有幾點(diǎn):
(1)資源文件缺乏,將zxing下需要的資源文件copy到新工程下
(2)版本兼容問題,zxing下很多技術(shù)都是使用4.0版本及以上,集成到低版本之后,須做相應(yīng)改動(dòng),詳情參照項(xiàng)目源碼
(3)包結(jié)構(gòu)引用問題,需要重新導(dǎo)入包引用
4、簡化CapyureActivity, camera包以及decode各類異常解決以后,即可對(duì)CaptureActivity進(jìn)行代碼簡化 ,首先看一下capture.xml布局
1 <merge xmlns:android="http://schemas.android.com/apk/res/android"
2 xmlns:tools="http://schemas.android.com/tools" >
3
4 <!-- 整體透明畫布 -->
5 <SurfaceView
6 android:id="@+id/preview_view"
7 android:layout_width="fill_parent"
8 android:layout_height="fill_parent" />
9
10 <!-- 掃描取景框 -->
11 <com.karics.library.zxing.view.ViewfinderView
12 android:id="@+id/viewfinder_view"
13 android:layout_width="fill_parent"
14 android:layout_height="fill_parent" />
15
16 <!-- 標(biāo)題欄 -->
17 <RelativeLayout
18 android:layout_width="fill_parent"
19 android:layout_height="50dp"
20 android:layout_gravity="top"
21 android:background="#99000000">
22
23 <ImageButton
24 android:id="@+id/capture_imageview_back"
25 android:layout_width="42dp"
26 android:layout_height="42dp"
27 android:layout_centerVertical="true"
28 android:background="@drawable/selector_capture_back"/>
29
30 <TextView
31 android:layout_width="wrap_content"
32 android:layout_height="wrap_content"
33 android:layout_centerInParent="true"
34 android:textColor="#ffffffff"
35 android:textSize="20sp"
36 android:text="掃一掃"/>
37
38 </RelativeLayout>
39
40 </merge>
capture.xml
capture.xml布局去掉結(jié)果顯示,添加標(biāo)題欄。那么captureActivity中,onCreate(),onPause(),onResume(),onDestroy涉及到Camera的初始化或銷毀
1 @Override
2 public void onCreate(Bundle icicle) {
3 super.onCreate(icicle);
4 // 保持Activity處于喚醒狀態(tài)
5 Window window = getWindow();
6 window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
7 setContentView(R.layout.capture);
8
9 hasSurface = false;
10
11 inactivityTimer = new InactivityTimer(this);
12 beepManager = new BeepManager(this);
13
14 imageButton_back = (ImageButton) findViewById(R.id.capture_imageview_back);
15 imageButton_back.setOnClickListener(new View.OnClickListener() {
16
17 @Override
18 public void onClick(View v) {
19 finish();
20 }
21 });
22 }
23
24 @Override
25 protected void onResume() {
26 super.onResume();
27
28 // CameraManager必須在這里初始化,而不是在onCreate()中。
29 // 這是必須的,因?yàn)楫?dāng)我們第一次進(jìn)入時(shí)需要顯示幫助頁,我們并不想打開Camera,測(cè)量屏幕大小
30 // 當(dāng)掃描框的尺寸不正確時(shí)會(huì)出現(xiàn)bug
31 cameraManager = new CameraManager(getApplication());
32
33 viewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view);
34 viewfinderView.setCameraManager(cameraManager);
35
36 handler = null;
37
38 SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view);
39 SurfaceHolder surfaceHolder = surfaceView.getHolder();
40 if (hasSurface) {
41 // activity在paused時(shí)但不會(huì)stopped,因此surface仍舊存在;
42 // surfaceCreated()不會(huì)調(diào)用,因此在這里初始化camera
43 initCamera(surfaceHolder);
44 } else {
45 // 重置callback,等待surfaceCreated()來初始化camera
46 surfaceHolder.addCallback(this);
47 }
48
49 beepManager.updatePrefs();
50 inactivityTimer.onResume();
51
52 source = IntentSource.NONE;
53 decodeFormats = null;
54 characterSet = null;
55 }
56
57 @Override
58 protected void onPause() {
59 if (handler != null) {
60 handler.quitSynchronously();
61 handler = null;
62 }
63 inactivityTimer.onPause();
64 beepManager.close();
65 cameraManager.closeDriver();
66 if (!hasSurface) {
67 SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view);
68 SurfaceHolder surfaceHolder = surfaceView.getHolder();
69 surfaceHolder.removeCallback(this);
70 }
71 super.onPause();
72 }
73
74 @Override
75 protected void onDestroy() {
76 inactivityTimer.shutdown();
77 super.onDestroy();
78 }
View Code
surfaceview是基于Camera而實(shí)現(xiàn),surfaceview的使用需要實(shí)現(xiàn)SurfaceHolder.Callback接口,在開啟屏幕surfaceview的時(shí)候初始化camera
1 @Override
2 public void surfaceCreated(SurfaceHolder holder) {
3 if (!hasSurface) {
4 hasSurface = true;
5 initCamera(holder);
6 }
7 }
8
9 @Override
10 public void surfaceDestroyed(SurfaceHolder holder) {
11 hasSurface = false;
12 }
13
14 @Override
15 public void surfaceChanged(SurfaceHolder holder, int format, int width,
16 int height) {
17
18 }
View Code
接下來看如何初始化Camera,代碼簡化之后如下
1 private void initCamera(SurfaceHolder surfaceHolder) {
2 if (surfaceHolder == null) {
3 throw new IllegalStateException("No SurfaceHolder provided");
4 }
5 if (cameraManager.isOpen()) {
6 return;
7 }
8 try {
9 // 打開Camera硬件設(shè)備
10 cameraManager.openDriver(surfaceHolder);
11 // 創(chuàng)建一個(gè)handler來打開預(yù)覽,并拋出一個(gè)運(yùn)行時(shí)異常
12 if (handler == null) {
13 handler = new CaptureActivityHandler(this, decodeFormats,
14 decodeHints, characterSet, cameraManager);
15 }
16 } catch (IOException ioe) {
17 Log.w(TAG, ioe);
18 displayFrameworkBugMessageAndExit();
19 } catch (RuntimeException e) {
20 Log.w(TAG, "Unexpected error initializing camera", e);
21 displayFrameworkBugMessageAndExit();
22 }
23 }
View Code
在CaptureActivity中,有一個(gè)核心方法,用來返回并處理解碼結(jié)果,也即掃描結(jié)果。handleDecode(),如果需要對(duì)解碼后的內(nèi)容進(jìn)行自己的處理,需要對(duì)該方法進(jìn)行改動(dòng),這里修改 為將解碼的bitmap以及內(nèi)容回傳到開啟掃描的Activiity進(jìn)行處理。
1 public void handleDecode(Result rawResult, Bitmap barcode, float scaleFactor) {
2 inactivityTimer.onActivity();
3
4 boolean fromLiveScan = barcode != null;
5 //這里處理解碼完成后的結(jié)果,此處將參數(shù)回傳到Activity處理
6 if (fromLiveScan) {
7 beepManager.playBeepSoundAndVibrate();
8
9 Toast.makeText(this, "掃描成功", Toast.LENGTH_SHORT).show();
10
11 Intent intent = getIntent();
12 intent.putExtra("codedContent", rawResult.getText());
13 intent.putExtra("codedBitmap", barcode);
14 setResult(RESULT_OK, intent);
15 finish();
16 }
17
18 }
View Code
5、將指定Url生成二維碼
1 /**
2 * 生成QRCode(二維碼)
3 *
4 * @param str
5 * @return
6 * @throws WriterException
7 */
8 public static Bitmap createQRCode(String url) throws WriterException {
9
10 if (url == null || url.equals("")) {
11 return null;
12 }
13
14 // 生成二維矩陣,編碼時(shí)指定大小,不要生成了圖片以后再進(jìn)行縮放,這樣會(huì)模糊導(dǎo)致識(shí)別失敗
15 BitMatrix matrix = new MultiFormatWriter().encode(url,
16 BarcodeFormat.QR_CODE, 300, 300);
17
18 int width = matrix.getWidth();
19 int height = matrix.getHeight();
20
21 // 二維矩陣轉(zhuǎn)為一維像素?cái)?shù)組,也就是一直橫著排了
22 int[] pixels = new int[width * height];
23
24 for (int y = 0; y < height; y++) {
25 for (int x = 0; x < width; x++) {
26 if (matrix.get(x, y)) {
27 pixels[y * width + x] = 0xff000000;
28 }
29
30 }
31 }
32
33 Bitmap bitmap = Bitmap.createBitmap(width, height,
34 Bitmap.Config.ARGB_8888);
35 bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
36 return bitmap;
37 }
View Code
通過以上四步,zxing項(xiàng)目的簡化工作基本完成。至于一些類需要進(jìn)行小修小改,希望可以對(duì)著源碼進(jìn)行,這里不再贅述。二維碼掃描的整體構(gòu)架主要包含三部分:
1、定義取景框,也即掃描的View,通過surfaceview進(jìn)行繪制
2、Camera, 掃描的核心在于camera的配置使用,包括預(yù)覽,自動(dòng)聚焦,打開設(shè)備等處理
3、Decode解碼,掃描完成后整個(gè)工程的核心
除去以上三個(gè)模塊,需要明確的就是CaptureActivitiy中handleDeCode()方法做自己的處理。
此文關(guān)鍵字:此文關(guān)鍵詞:
相關(guān)資訊
同類文章排行
- 部隊(duì)查手機(jī)數(shù)據(jù)的儀器
- 專變采集終端485接線圖
- 平板電腦尺寸規(guī)格
- 在線掃描條形碼
- 交警移動(dòng)執(zhí)法手持機(jī)PDA的選型應(yīng)用介紹
- 條碼掃描器在線使用
- 工業(yè)觸摸一體機(jī)是選擇電阻屏還是電容屏呢?
- pda手持設(shè)備
- MES系統(tǒng)二維碼條碼掃描器手持終端PDA
- 工業(yè)觸摸屏顯示器生產(chǎn)廠家,國產(chǎn)工業(yè)觸摸屏生產(chǎn)廠家
最新資訊文章
- 15英寸工業(yè)平板電腦哪個(gè)牌子好
- 安卓系統(tǒng)12寸手持工業(yè)平板電腦支持條碼掃描識(shí)別
- 17英寸卡扣式嵌入式工業(yè)平板電腦機(jī)型
- 10英寸移動(dòng)式無線工業(yè)平板電腦支持車載安裝的機(jī)型推薦
- 手持終端pda應(yīng)用行業(yè)_二維碼數(shù)據(jù)采集器服務(wù)廠家
- 制造業(yè)條碼手持終端推薦_手持機(jī) 二維碼制造商
- PDA手持終端數(shù)據(jù)采集應(yīng)用領(lǐng)域_移動(dòng)手持終端平板電腦價(jià)格
- 餐桌安全手持終端推薦應(yīng)用_手持?jǐn)?shù)據(jù)采集終端生產(chǎn)廠家
- PDA手持終端優(yōu)點(diǎn)是什么_串口超高頻rfid 掃描平板哪家好
- 產(chǎn)品追溯工業(yè)手持終端推薦_云南省uhf工業(yè)平板哪家好