您的位置:首頁>正文

基於 zxing 的二維碼掃描

前言

現在的應用中二維碼掃描已經成為一個應用必不可少的功能, 現在大部分Android二維碼掃描都是基於zxing和Zbar, 這文章就來介紹一下基於zxing的二維碼掃描。 先看下效果圖

雖然現在的關於二維碼的文章有很多, 但是很多都是交我們怎麼使用, 在使用的時候我也遇到了很多問題, 比如。 UI介面太醜,沒有用的檔太多, 掃描太慢, 版本太老。 本Demo使用的是3.x的是比較新的版本。 我用的小米2A(api=19)親測在正常情況下掃描時間和QQ微信差不多, 我的介面是類防QQ的也是比較美觀的。 那麼我們看看如何使用和檔的作用。

zxing

zxing官網 這是zxing官網。 想瞭解更多的可以去官網, 裡面有文檔不過在我看來。 協力廠商庫的使用我們沒有必要完全瞭解, 整體上我們瞭解所需要功能即可, 這樣減少了學習時間。

為什麼選擇zxing

google的開源項目, 高可定制性

可以識別多種碼, 不僅僅是二維碼

不依賴協力廠商庫,

使用起來簡單

zxing的使用

zixng JAR

我們可以去官網, 如果是Android Studio的話也可以線上搜索zxing jar, 導入完成後別忘了ADD library。

res文件

drawable

檔中主要放的是一些我們顯示介面的圖片和一些點擊按鈕的background

layout

activity qrcodecapture_layout.xml是zxing掃描的主介面, 另外兩個佈局就是我們在開始圖片中看到的, 一個頭部, 一個腳部的佈局

colors, dis, strings, styles, raw, xml

這些是zxing中一些類的資源檔和我們自訂佈局的一些資源檔, 不導入會報錯, raw是我們掃描完成後的音效, 我們也可以根據需求改成自己的音效(但是要注意的是檔案格式和名字儘量要相同, 避免出錯和資源找不到), xml就是zxing用到的資源檔, 我們直接複製過來就行。

PS:如果你是從官網拷貝, 那麼你自需要拷貝和我一樣的就行。 我這裡只是多了一些drawwable中的佈局圖片和頭部腳部2個佈局

關鍵類

app

CaptureActivity 主要是我們的掃碼介面, 在這裡我們引入我們自己的頭部腳部佈局, 並給控制項點擊事件, 在這個類中我們重點看這幾個方法:

/** * 閃光燈點擊事件 */ private OnClickListener click = new OnClickListener { @Override public void onClick(View v) { int id = v.getId; if (id == R.id.button_back) {//返回按鈕 finish; } else if (id == R.id.flash_btn) {//打開關閉閃光燈 if (!isFlash) { CameraManager.get.turnLightOn; } else { CameraManager.get.turnLightOff; } isFlash = !isFlash; } else if (id == R.id.photo_btn) {//掃描二維碼圖片 // 打開手機中的相冊 Intent innerIntent = new Intent(Intent.ACTION_GET_CONTENT); // "android.intent.action.GET_CONTENT" innerIntent.setType("image/*"); //封裝intent Intent wrapperIntent = Intent.createChooser(innerIntent, "選擇二維碼圖片"); startActivityForResult(wrapperIntent, REQUEST_CODE); } else if (id == R.id.qrcode_btn) { // 跳轉到生成二維碼頁面 Bitmap b = createQRCode; Intent intent = getIntent; intent.putExtra("QR_CODE", b); setResult(200, intent); finish; } } };

所有掃碼介面的點擊事件都在這個Activity中, 可以看到zxing給我做了比較好的封裝, 只需要2行代碼我們就可以控制閃光燈的開關。 掃描圖片二維碼的點擊事件也比較簡單我們自需要打開相冊。 並用startActivityForResult啟動相冊。

@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_OK) {//圖片選擇返回 uri = data.getData;//獲取圖片Uri //啟動執行緒完成圖片掃碼 new Thread(new Runnable { @Override public void run { Result result = scanningImage(uri); if (result == null) { Looper.prepare; Toast.makeText(getApplicationContext, "圖片格式有誤", Toast.LENGTH_SHORT).show; Looper.loop; } else { // 資料返回,
在這裡去處理掃碼結果 String recode = (result.toString); Intent data = new Intent; data.putExtra("result", recode); //返回啟動掃碼介面的Activity setResult(300, data); finish; } } }).start; } }

這個方法主要是處理上個方法打開相冊選取圖片後結果返回的處理。 可以看到, 我們拿到結果將掃碼掃碼介面finish掉, 並通過setResult方法將資料交給跳轉我們的掃碼介面的活動去處理。 下面我們再來看下生成二維碼

生成二維碼:可以看到生成二維碼主要是調用了createQRCode;這個方法, 那我來看下這個方法:

private Bitmap createQRCode { int QR_WIDTH = 100;//生成二維碼的寬 int QR_HEIGHT = 100;//生成二維碼的高 try { // 需要引入core包 QRCodeWriter writer = new QRCodeWriter; String text = Util.getIMEI(this); if (text == null || "".equals(text) || text.length < 1) { return null; } // 把輸入的文本轉為二維碼 BitMatrix martix = writer.encode(text, BarcodeFormat.QR_CODE, QR_WIDTH, QR_HEIGHT); System.out.println("w:" + martix.getWidth + "h:" + martix.getHeight); Hashtable hints = new Hashtable; hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); BitMatrix bitMatrix = new QRCodeWriter.encode(text, BarcodeFormat.QR_CODE, QR_WIDTH, QR_HEIGHT, hints); int pixels = new int[QR_WIDTH * QR_HEIGHT]; for (int y = 0; y < QR_HEIGHT; y++) { for (int x = 0; x < QR_WIDTH; x++) { if (bitMatrix.get(x, y)) { pixels[y * QR_WIDTH + x] = 0xff000000; } else { pixels[y * QR_WIDTH + x] = 0xffffffff; } } } // 生成的二維碼 Bitmap bitmap = Bitmap.createBitmap(QR_WIDTH, QR_HEIGHT, Bitmap.Config.ARGB_8888); bitmap.setPixels(pixels, 0, QR_WIDTH, 0, 0, QR_WIDTH, QR_HEIGHT); return bitmap; } catch (WriterException e) { e.printStackTrace; } return null; }

它主要就是將一個文本生成了一個寬高為100*100的bitmap。 那我們就把這個方法簡單就修改下, 寬高由我們傳入。 文本也是由我們自己來決定。 因為生成二維碼並不依賴掃描的Activity,所以不管在那裡我們只要調用createQRcode,就能生成二維碼。

camera 主要是一些相機的管理類,FlashlightManager閃光燈的管理類,CameraManager相機的管理類,比如剛才我們的開關閃光燈。

decode 這裡面主要是解碼,因為解碼也是比較耗時的炒作,所以我們是放在執行緒中去執行並通過handle來進行消息傳遞。這裡重要的類是CaptureActivityHandler。處理的結果都是通過這個類傳給我們的Activity的。既然是handle,那麼我們就來看下handleMessage方法

@Override public void handleMessage(Message message) { if (message.what == R.id.auto_focus) { // Log.d(TAG, "Got auto-focus message"); // When one auto focus pass finishes, start another. This is the // closest thing to // continuous AF. It does seem to hunt a bit, but I'm not sure what // else to do. if (state == State.PREVIEW) { CameraManager.get.requestAutoFocus(this, R.id.auto_focus); } } else if (message.what == R.id.restart_preview) { Log.d(TAG, "Got restart preview message"); restartPreviewAndDecode; } else if (message.what == R.id.decode_succeeded) { Log.d(TAG, "Got decode succeeded message"); state = State.SUCCESS; Bundle bundle = message.getData; Bitmap barcode = bundle == null ? null : (Bitmap) bundle.getParcelable(DecodeThread.BARCODE_BITMAP); activity.handleDecode((Result) message.obj, barcode); Result result = (Result) message.obj; Intent mIntent = new Intent; mIntent.putExtra("SCAN_RESULT", result.getText); activity.setResult(Activity.RESULT_OK, mIntent); activity.finish; } else if (message.what == R.id.decode_failed) { // We're decoding as fast as possible, so when one decode fails, // start another. state = State.PREVIEW; CameraManager.get.requestPreviewFrame(decodeThread.getHandler, R.id.decode); } else if (message.what == R.id.return_scan_result) { Log.d(TAG, "Got return scan result message"); activity.setResult(Activity.RESULT_OK, (Intent) message.obj); activity.finish; } else if (message.what == R.id.launch_product_query) { Log.d(TAG, "Got product query message"); String url = (String) message.obj; Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); activity.startActivity(intent); } }

可以看到處理的結果都在這裡。有成功失敗和其他一些情況的處理,這裡我們主要看成功時會返回resultCode=RESULT OK,掃描的結果放在inent中key=SCANRESULT,這樣我們就可以根據intent攜帶的key和value去做們相應的處理

BeepManager是控制我們的消息音。

BeepManager manager = new BeepManager(activity);//開啟提示音 manager.playBeepSoundAndVibrate;

encode,util,就是編碼和工具類,這裡我們就不看了

view中我們重點來看下ViewfinderView。這個就是我們掃碼介面的主佈局。他和我們自己添加的頭部和腳部不同,它不是通過引入佈局,而是自訂view畫上去的。既然是畫上去的那麼就去看看onDraw方法做了什麼

@Override public void onDraw(Canvas canvas) { /** * 想修改掃描框的位置修改CameraManager中的參數 */ Rect frame = CameraManager.get.getFramingRect; if (frame == null) { return; } if (!isFirst) { isFirst = true; slideTop = frame.top; slideBottom = frame.bottom; } int width = canvas.getWidth; int height = canvas.getHeight; /** * 畫白線矩形 */ paint.setStyle(Paint.Style.STROKE); paint.setColor(Color.WHITE); path.moveTo(frame.left + CORNER_OFFEST, frame.top + CORNER_OFFEST); path.lineTo(frame.right - CORNER_OFFEST, frame.top + CORNER_OFFEST); path.lineTo(frame.right - CORNER_OFFEST, frame.bottom - CORNER_OFFEST); path.lineTo(frame.left + CORNER_OFFEST, frame.bottom - CORNER_OFFEST); path.close; canvas.drawPath(path, paint); // Draw the exterior (i.e. outside the framing rect) darkened paint.setColor(resultBitmap != null ? resultColor : maskColor); paint.setStyle(Paint.Style.FILL); /** * 畫上下左右4個位置的半透明黑色佈局 */ canvas.drawRect(0, 0, width, frame.top, paint); canvas.drawRect(0, frame.top, frame.left, frame.bottom + 1, paint); canvas.drawRect(frame.right + 1, frame.top, width, frame.bottom + 1, paint); canvas.drawRect(0, frame.bottom + 1, width, height, paint); if (resultBitmap != null) { // Draw the opaque result bitmap over the scanning rectangle paint.setAlpha(OPAQUE); canvas.drawBitmap(resultBitmap, null, frame, paint); } else { /** * 畫4個角的小矩形,每個角2個矩形 共8個 */ paint.setColor(getResources.getColor(R.color.view_rect)); canvas.drawRect(frame.left, frame.top, frame.left + ScreenRate, frame.top + CORNER_WIDTH, paint); canvas.drawRect(frame.left, frame.top, frame.left + CORNER_WIDTH, frame.top + ScreenRate, paint); canvas.drawRect(frame.right - ScreenRate, frame.top, frame.right, frame.top + CORNER_WIDTH, paint); canvas.drawRect(frame.right - CORNER_WIDTH, frame.top, frame.right, frame.top + ScreenRate, paint); canvas.drawRect(frame.left, frame.bottom - CORNER_WIDTH, frame.left + ScreenRate, frame.bottom, paint); canvas.drawRect(frame.left, frame.bottom - ScreenRate, frame.left + CORNER_WIDTH, frame.bottom, paint); canvas.drawRect(frame.right - ScreenRate, frame.bottom - CORNER_WIDTH, frame.right, frame.bottom, paint); canvas.drawRect(frame.right - CORNER_WIDTH, frame.bottom - ScreenRate, frame.right, frame.bottom, paint); /** * 定義每秒的移動速度 */ slideTop += SPEEN_DISTANCE; if (slideTop >= frame.bottom) { slideTop = frame.top; } lineRect.left = frame.left; lineRect.right = frame.right; lineRect.top = slideTop; lineRect.bottom = slideTop + 18; canvas.drawBitmap(((BitmapDrawable) (getResources .getDrawable(R.drawable.fle))).getBitmap, null, lineRect, paint); paint.setColor(Color.WHITE); paint.setTextSize(TEXT_SIZE * density); paint.setAlpha(0x40); paint.setTypeface(Typeface.create("System", Typeface.BOLD)); String text = getResources.getString(R.string.scan_text); float textWidth = paint.measureText(text); canvas.drawText( text, (width - textWidth) / 2, (float) (frame.bottom + (float) TEXT_PADDING_TOP * density), paint); Collection currentPossible = possibleResultPoints; Collection currentLast = lastPossibleResultPoints; if (currentPossible.isEmpty) { lastPossibleResultPoints = null; } else { possibleResultPoints = new HashSet(5); lastPossibleResultPoints = currentPossible; paint.setAlpha(OPAQUE); paint.setColor(resultPointColor); for (ResultPoint poin t : currentPossible) { canvas.drawCircle(frame.left + point.getX, frame.top + point.getY, 6.0f, paint); } } if (currentLast != null) { paint.setAlpha(OPAQUE / 2); paint.setColor(resultPointColor); for (ResultPoint point : currentLast) { canvas.drawCircle(frame.left + point.getX, frame.top + point.getY, 3.0f, paint); } } //不斷重繪 完成游標移動 postInvalidateDelayed(ANIMATION_DELAY, frame.left, frame.top, frame.right, frame.bottom); } }

注釋比較清晰,掌握基本的自訂View只是就可以畫出來我們展示的效果。

最後我們在看下我們MainActivity的調用:

@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == 200) { if (resultCode == Activity.RESULT_OK) { //還記得我們在講CaptureActivityHandler時 成功就會發送SCAN_RESULT這個key值的intent嘛? String code = data.getStringExtra("SCAN_RESULT"); Log.d(TAG, "onActivityResult:----> " + code); if (code.contains("http") || code.contains("https")) { //二維碼 mTextView.setText(code); } else if ((!code.contains("http") || !code.contains("https")) && code != null && TextUtils.isEmpty(code)) { //條碼數字 //這裡注意:如果你掃描的是商品條碼。返回的條碼數字 //這裡如果你使用webview是無法解析的,一般我們需要查詢 //的api介面或是資料庫查找才能展示我們想要的結果 mTextView.setText(code); } else { Toast.makeText(this, "error", Toast.LENGTH_SHORT).show; } } if (resultCode == 300) { //掃描圖片 String code = data.getStringExtra("result"); Log.d(TAG, "onActivityResult:---->result " + code); mTextView.setText(code); } if (resultCode == 200) { //生成二維碼回檔 Bitmap bitmap = Util.createQRCode(dip2px(this, 200), dip2px(this, 200), "https://www.baidu.com/"); mImageView.setImageBitmap(bitmap); } } }

好了,zxing的使用和相關類的功能我們有了一個大致的瞭解。回頭我們在看看zxing的優點:可以看到封裝性比較好我們不需要多做什麼處理,我們需要什麼功能就在基礎上加什麼功能,源碼都給我們了,我們也知道每個類是什麼作用還不是想怎麼改怎麼改嘛(高可定制性),還有在使用協力廠商庫的時候我們比較擔心的就是我們需要一個庫的功能,但是這個庫卻依賴很多其他的庫,當其他庫發生改動的時候我們需要的庫也要改這就很煩。

結束

在這裡我只是做一個抛磚引玉的作用,不管你想要什麼樣的UI還是什麼樣的佈局,我在方法中加了注釋不喜歡那裡將代碼刪除寫上自己想要的效果就好。畢竟我還是個小白菜鳥。如果你也在學習的路上,想在你自己應用加上掃碼功能,希望這篇文章能給你一些幫助。如果像直接使用下面我給出了源碼,可以直接放入項目中也可導入library。

寫的不好大家多多諒解。如有錯誤真心希望大家提出來。最後希望大家一起進步。加油!!!

源碼地址

https://github.com/guzhigang001/Zxing/tree/master

因為生成二維碼並不依賴掃描的Activity,所以不管在那裡我們只要調用createQRcode,就能生成二維碼。

camera 主要是一些相機的管理類,FlashlightManager閃光燈的管理類,CameraManager相機的管理類,比如剛才我們的開關閃光燈。

decode 這裡面主要是解碼,因為解碼也是比較耗時的炒作,所以我們是放在執行緒中去執行並通過handle來進行消息傳遞。這裡重要的類是CaptureActivityHandler。處理的結果都是通過這個類傳給我們的Activity的。既然是handle,那麼我們就來看下handleMessage方法

@Override public void handleMessage(Message message) { if (message.what == R.id.auto_focus) { // Log.d(TAG, "Got auto-focus message"); // When one auto focus pass finishes, start another. This is the // closest thing to // continuous AF. It does seem to hunt a bit, but I'm not sure what // else to do. if (state == State.PREVIEW) { CameraManager.get.requestAutoFocus(this, R.id.auto_focus); } } else if (message.what == R.id.restart_preview) { Log.d(TAG, "Got restart preview message"); restartPreviewAndDecode; } else if (message.what == R.id.decode_succeeded) { Log.d(TAG, "Got decode succeeded message"); state = State.SUCCESS; Bundle bundle = message.getData; Bitmap barcode = bundle == null ? null : (Bitmap) bundle.getParcelable(DecodeThread.BARCODE_BITMAP); activity.handleDecode((Result) message.obj, barcode); Result result = (Result) message.obj; Intent mIntent = new Intent; mIntent.putExtra("SCAN_RESULT", result.getText); activity.setResult(Activity.RESULT_OK, mIntent); activity.finish; } else if (message.what == R.id.decode_failed) { // We're decoding as fast as possible, so when one decode fails, // start another. state = State.PREVIEW; CameraManager.get.requestPreviewFrame(decodeThread.getHandler, R.id.decode); } else if (message.what == R.id.return_scan_result) { Log.d(TAG, "Got return scan result message"); activity.setResult(Activity.RESULT_OK, (Intent) message.obj); activity.finish; } else if (message.what == R.id.launch_product_query) { Log.d(TAG, "Got product query message"); String url = (String) message.obj; Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); activity.startActivity(intent); } }

可以看到處理的結果都在這裡。有成功失敗和其他一些情況的處理,這裡我們主要看成功時會返回resultCode=RESULT OK,掃描的結果放在inent中key=SCANRESULT,這樣我們就可以根據intent攜帶的key和value去做們相應的處理

BeepManager是控制我們的消息音。

BeepManager manager = new BeepManager(activity);//開啟提示音 manager.playBeepSoundAndVibrate;

encode,util,就是編碼和工具類,這裡我們就不看了

view中我們重點來看下ViewfinderView。這個就是我們掃碼介面的主佈局。他和我們自己添加的頭部和腳部不同,它不是通過引入佈局,而是自訂view畫上去的。既然是畫上去的那麼就去看看onDraw方法做了什麼

@Override public void onDraw(Canvas canvas) { /** * 想修改掃描框的位置修改CameraManager中的參數 */ Rect frame = CameraManager.get.getFramingRect; if (frame == null) { return; } if (!isFirst) { isFirst = true; slideTop = frame.top; slideBottom = frame.bottom; } int width = canvas.getWidth; int height = canvas.getHeight; /** * 畫白線矩形 */ paint.setStyle(Paint.Style.STROKE); paint.setColor(Color.WHITE); path.moveTo(frame.left + CORNER_OFFEST, frame.top + CORNER_OFFEST); path.lineTo(frame.right - CORNER_OFFEST, frame.top + CORNER_OFFEST); path.lineTo(frame.right - CORNER_OFFEST, frame.bottom - CORNER_OFFEST); path.lineTo(frame.left + CORNER_OFFEST, frame.bottom - CORNER_OFFEST); path.close; canvas.drawPath(path, paint); // Draw the exterior (i.e. outside the framing rect) darkened paint.setColor(resultBitmap != null ? resultColor : maskColor); paint.setStyle(Paint.Style.FILL); /** * 畫上下左右4個位置的半透明黑色佈局 */ canvas.drawRect(0, 0, width, frame.top, paint); canvas.drawRect(0, frame.top, frame.left, frame.bottom + 1, paint); canvas.drawRect(frame.right + 1, frame.top, width, frame.bottom + 1, paint); canvas.drawRect(0, frame.bottom + 1, width, height, paint); if (resultBitmap != null) { // Draw the opaque result bitmap over the scanning rectangle paint.setAlpha(OPAQUE); canvas.drawBitmap(resultBitmap, null, frame, paint); } else { /** * 畫4個角的小矩形,每個角2個矩形 共8個 */ paint.setColor(getResources.getColor(R.color.view_rect)); canvas.drawRect(frame.left, frame.top, frame.left + ScreenRate, frame.top + CORNER_WIDTH, paint); canvas.drawRect(frame.left, frame.top, frame.left + CORNER_WIDTH, frame.top + ScreenRate, paint); canvas.drawRect(frame.right - ScreenRate, frame.top, frame.right, frame.top + CORNER_WIDTH, paint); canvas.drawRect(frame.right - CORNER_WIDTH, frame.top, frame.right, frame.top + ScreenRate, paint); canvas.drawRect(frame.left, frame.bottom - CORNER_WIDTH, frame.left + ScreenRate, frame.bottom, paint); canvas.drawRect(frame.left, frame.bottom - ScreenRate, frame.left + CORNER_WIDTH, frame.bottom, paint); canvas.drawRect(frame.right - ScreenRate, frame.bottom - CORNER_WIDTH, frame.right, frame.bottom, paint); canvas.drawRect(frame.right - CORNER_WIDTH, frame.bottom - ScreenRate, frame.right, frame.bottom, paint); /** * 定義每秒的移動速度 */ slideTop += SPEEN_DISTANCE; if (slideTop >= frame.bottom) { slideTop = frame.top; } lineRect.left = frame.left; lineRect.right = frame.right; lineRect.top = slideTop; lineRect.bottom = slideTop + 18; canvas.drawBitmap(((BitmapDrawable) (getResources .getDrawable(R.drawable.fle))).getBitmap, null, lineRect, paint); paint.setColor(Color.WHITE); paint.setTextSize(TEXT_SIZE * density); paint.setAlpha(0x40); paint.setTypeface(Typeface.create("System", Typeface.BOLD)); String text = getResources.getString(R.string.scan_text); float textWidth = paint.measureText(text); canvas.drawText( text, (width - textWidth) / 2, (float) (frame.bottom + (float) TEXT_PADDING_TOP * density), paint); Collection currentPossible = possibleResultPoints; Collection currentLast = lastPossibleResultPoints; if (currentPossible.isEmpty) { lastPossibleResultPoints = null; } else { possibleResultPoints = new HashSet(5); lastPossibleResultPoints = currentPossible; paint.setAlpha(OPAQUE); paint.setColor(resultPointColor); for (ResultPoint poin t : currentPossible) { canvas.drawCircle(frame.left + point.getX, frame.top + point.getY, 6.0f, paint); } } if (currentLast != null) { paint.setAlpha(OPAQUE / 2); paint.setColor(resultPointColor); for (ResultPoint point : currentLast) { canvas.drawCircle(frame.left + point.getX, frame.top + point.getY, 3.0f, paint); } } //不斷重繪 完成游標移動 postInvalidateDelayed(ANIMATION_DELAY, frame.left, frame.top, frame.right, frame.bottom); } }

注釋比較清晰,掌握基本的自訂View只是就可以畫出來我們展示的效果。

最後我們在看下我們MainActivity的調用:

@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == 200) { if (resultCode == Activity.RESULT_OK) { //還記得我們在講CaptureActivityHandler時 成功就會發送SCAN_RESULT這個key值的intent嘛? String code = data.getStringExtra("SCAN_RESULT"); Log.d(TAG, "onActivityResult:----> " + code); if (code.contains("http") || code.contains("https")) { //二維碼 mTextView.setText(code); } else if ((!code.contains("http") || !code.contains("https")) && code != null && TextUtils.isEmpty(code)) { //條碼數字 //這裡注意:如果你掃描的是商品條碼。返回的條碼數字 //這裡如果你使用webview是無法解析的,一般我們需要查詢 //的api介面或是資料庫查找才能展示我們想要的結果 mTextView.setText(code); } else { Toast.makeText(this, "error", Toast.LENGTH_SHORT).show; } } if (resultCode == 300) { //掃描圖片 String code = data.getStringExtra("result"); Log.d(TAG, "onActivityResult:---->result " + code); mTextView.setText(code); } if (resultCode == 200) { //生成二維碼回檔 Bitmap bitmap = Util.createQRCode(dip2px(this, 200), dip2px(this, 200), "https://www.baidu.com/"); mImageView.setImageBitmap(bitmap); } } }

好了,zxing的使用和相關類的功能我們有了一個大致的瞭解。回頭我們在看看zxing的優點:可以看到封裝性比較好我們不需要多做什麼處理,我們需要什麼功能就在基礎上加什麼功能,源碼都給我們了,我們也知道每個類是什麼作用還不是想怎麼改怎麼改嘛(高可定制性),還有在使用協力廠商庫的時候我們比較擔心的就是我們需要一個庫的功能,但是這個庫卻依賴很多其他的庫,當其他庫發生改動的時候我們需要的庫也要改這就很煩。

結束

在這裡我只是做一個抛磚引玉的作用,不管你想要什麼樣的UI還是什麼樣的佈局,我在方法中加了注釋不喜歡那裡將代碼刪除寫上自己想要的效果就好。畢竟我還是個小白菜鳥。如果你也在學習的路上,想在你自己應用加上掃碼功能,希望這篇文章能給你一些幫助。如果像直接使用下面我給出了源碼,可以直接放入項目中也可導入library。

寫的不好大家多多諒解。如有錯誤真心希望大家提出來。最後希望大家一起進步。加油!!!

源碼地址

https://github.com/guzhigang001/Zxing/tree/master

同類文章
Next Article
喜欢就按个赞吧!!!
点击关闭提示