Android 二維碼 生成和識別二維碼 附源碼下載
今天講一下目前移動領(lǐng)域很常用的技術(shù)——二維碼?,F(xiàn)在大街小巷、各大網(wǎng)站都有二維碼的蹤跡,不管是IOS、Android、WP都有相關(guān)支持的軟件。之前我就想了解二維碼是如何工作,最近因為工作需要使用相關(guān)技術(shù),所以做了初步了解。今天主要是講解如何使用ZXing庫,生成和識別二維碼。這篇文章實用性為主,理論性不會講解太多,有興趣可以自己查看源碼。
1、ZXing庫介紹
這里簡單介紹一下ZXing庫。ZXing是一個開放源碼的,用Java實現(xiàn)的多種格式的1D/2D條碼圖像處理庫,它包含了聯(lián)系到其他語言的端口。Zxing可以實現(xiàn)使用手機(jī)的內(nèi)置的攝像頭完成條形碼的掃描及解碼。該項目可實現(xiàn)的條形碼編碼和解碼。目前支持以下格式:UPC-A,UPC-E、EAN-8,EAN-13、39碼、93碼。ZXing是個很經(jīng)典的條碼/二維碼識別的開源類庫,以前在功能機(jī)上,就有開發(fā)者使用J2ME運(yùn)用ZXing了,不過要支持JSR-234規(guī)范(自動對焦)的手機(jī)才能發(fā)揮其威力。
下面是ZXing的demo運(yùn)行,我這里創(chuàng)建了一個二維碼,大伙可以用微信的掃一掃功能,試一下。就可以直接打開下面的網(wǎng)址。
2、ZXing庫主要類
下面給大家介紹一下,ZXing庫里面主要的類以及這些類的作用:
CaptureActivity。這個是啟動Activity 也就是掃描器。
CaptureActivityHandler 解碼處理類,負(fù)責(zé)調(diào)用另外的線程進(jìn)行解碼。
DecodeThread 解碼的線程。
com.google.zxing.client.android.camera 包,攝像頭控制包。
ViewfinderView 自定義的View,就是我們看見的拍攝時中間的框框了。
3、使用ZXing生成二維碼
下面針對二維碼生成和解析做個簡單介紹,至于詳細(xì)的使用方法,建議大家還是自己看看源碼,使用起來很簡單,不過這個開源項目的代碼,值得好好看看。首先給出二維碼生成的方法:
//要轉(zhuǎn)換的地址或字符串,可以是中文 public void createQRImage(String url) { try { //判斷URL合法性 if (url == null || "".equals(url) || url.length() < 1) { return; } Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>(); hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); //圖像數(shù)據(jù)轉(zhuǎn)換,使用了矩陣轉(zhuǎn)換 BitMatrix bitMatrix = new QRCodeWriter().encode(url, BarcodeFormat.QR_CODE, QR_WIDTH, QR_HEIGHT, hints); int[] pixels = new int[QR_WIDTH * QR_HEIGHT]; //下面這里按照二維碼的算法,逐個生成二維碼的圖片, //兩個for循環(huán)是圖片橫列掃描的結(jié)果 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; } } } //生成二維碼圖片的格式,使用ARGB_8888 Bitmap bitmap = Bitmap.createBitmap(QR_WIDTH, QR_HEIGHT, Bitmap.Config.ARGB_8888); bitmap.setPixels(pixels, 0, QR_WIDTH, 0, 0, QR_WIDTH, QR_HEIGHT); //顯示到一個ImageView上面 sweepIV.setImageBitmap(bitmap); } catch (WriterException e) { e.printStackTrace(); } }
上面就是二維碼生成的方法接口,如果你只是使用者方法,很簡單,只要傳入一個URL即可,就像我截圖里面一樣,傳入一個合法的網(wǎng)址即可?;蛘呦瘳F(xiàn)在一些移動APP的推廣,把APP下載地址轉(zhuǎn)為二維碼,只要掃一下就可以下載相應(yīng)的APP。這個也是目前比較流行的APP的推廣方式。
上面代碼做的事情不多,主要是調(diào)用ZXing庫里面QRCodeWriter().encode的方法對我們傳進(jìn)去的URL進(jìn)行編碼,具體如何編碼,這個我這里就不詳細(xì)說,有興趣可以看ZXing的源碼。文章最后會給出ZXing的源碼和例子代碼。
4、掃描二維碼獲取信息
掃描獲取二維碼信息的工作稍微復(fù)雜一些,主要是需要編寫Camera的使用,這個跟我們一般使用Camera一樣,需要使用Surfaceview作為預(yù)覽,這一部我這里就不說了,這個應(yīng)該不是太復(fù)雜。對于使用過Camera做預(yù)覽的朋友,應(yīng)該是挺簡單的事情。獲取二維碼數(shù)據(jù)的關(guān)鍵處理是在Camera的自動對焦回調(diào)函數(shù)哪里,調(diào)用ZXing的解碼接口。
private void restartPreviewAndDecode() { if (state == State.SUCCESS) { state = State.PREVIEW; CameraManager.get().requestPreviewFrame(decodeThread.getHandler(), R.id.decode); CameraManager.get().requestAutoFocus(this, R.id.auto_focus); activity.drawViewfinder(); } }
這里稍微多說一句,由于解碼需要一定時間,所以ZXing的解碼調(diào)用,都是使用了Handler作為線程通信機(jī)制,解碼的工作都是放在獨立線程里面使用的,如果你直接在主線程解碼,恐怕ANR問題是避免不了。
public void handleMessage(Message message) { switch (message.what) { case 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); } break; case R.id.restart_preview: Log.d(TAG, "Got restart preview message"); restartPreviewAndDecode(); break; case R.id.decode_succeeded: //解碼成功,獲取到界面的結(jié)果和原來的二維碼數(shù)據(jù) 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); break; case 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); break; case R.id.return_scan_result: Log.d(TAG, "Got return scan result message"); activity.setResult(Activity.RESULT_OK, (Intent) message.obj); activity.finish(); break; case 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); break; } }
上面是解碼的線程處理不同狀態(tài)的時候需要注意的地方,我們這里只看獲取圖像成功的地方,成功獲取圖片解碼的實在DecodeThread里面實現(xiàn),DecodeThread里面解碼成功后,會把數(shù)據(jù)序列化,然后保存到Bundle里面,我們可以直接通過Bundle的序列化,獲取到圖片數(shù)據(jù)。同時會把解碼后的結(jié)果保存到MSG里面,然后就可以根據(jù)實際情況進(jìn)行處理,例如上面代碼,解碼成功后,會調(diào)用一個處理函數(shù):
public void handleDecode(final Result obj, Bitmap barcode) { inactivityTimer.onActivity(); playBeepSoundAndVibrate(); AlertDialog.Builder dialog = new AlertDialog.Builder(this); if (barcode == null) { dialog.setIcon(null); } else { Drawable drawable = new BitmapDrawable(barcode); dialog.setIcon(drawable); } dialog.setTitle("掃描結(jié)果"); dialog.setMessage(obj.getText()); dialog.setNegativeButton("確定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //用默認(rèn)瀏覽器打開掃描得到的地址 Intent intent = new Intent(); intent.setAction("android.intent.action.VIEW"); Uri content_url = Uri.parse(obj.getText()); intent.setData(content_url); startActivity(intent); finish(); } }); dialog.setPositiveButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { finish(); } }); dialog.create().show(); }
上面就是整個二維碼的解碼流程,里面因為涉及很多Camera的使用,所以你如果需要使用二維碼識別,需要注意一下你的程序需要申請下面的權(quán)限,一般的Camera使用以及Camera的自動對焦等。
<uses-permission android:name="android.permission.CAMERA"></uses-permission> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission> <uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.camera.autofocus" />
5、結(jié)語
上面就是生成和識別二維碼的關(guān)鍵流程和代碼,有興趣的朋友可以自己查看ZXing的源碼,里面有很多圖像分析的知識可以學(xué)習(xí)。具體使用也可以參考我下面給出的Demo。二維碼對于現(xiàn)在移動開發(fā)來說很是很常用的技術(shù),所以有空可以了解一下,說不定什么時候就用上了。另外,ZXing庫除了二維碼外,其實對于條形碼也是支持的,只是我這里沒有介紹。有需要的自己去看看源碼即可。
ZXing開源項目Google Code地址:https://code.google.com/p/zxing/
ZXingDemo下載:ZXingDemo.rar
以上就是本文的全部內(nèi)容,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Android Studio三方引用報錯但是項目可以運(yùn)行的解決方案
今天小編就為大家分享一篇關(guān)于Android Studio三方引用報錯但是項目可以運(yùn)行的解決方案,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-03-03Android中使用開源框架eventbus3.0實現(xiàn)fragment之間的通信交互
本文主要介紹了Android中使用開源框架eventbus3.0實現(xiàn)fragment之間的通信交互的方法,具有很好的參考價值,下面跟著小編一起來看下吧2017-02-02Android開發(fā)獲取當(dāng)前系統(tǒng)日期和時間功能示例
這篇文章主要介紹了Android開發(fā)獲取當(dāng)前系統(tǒng)日期和時間功能,結(jié)合實例形式分析了Android布局、事件響應(yīng)、監(jiān)聽以及時間獲取相關(guān)操作技巧,需要的朋友可以參考下2019-04-04Android之內(nèi)置和外置sdcard路徑顯示并且寫入數(shù)據(jù)的方法
今天小編就為大家分享一篇Android之內(nèi)置和外置sdcard路徑顯示并且寫入數(shù)據(jù)的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-08-08詳解Android的Splash啟動圖的兩種動態(tài)切換方式
本篇文章主要介紹了詳解Android的Splash啟動圖的兩種動態(tài)切換方式,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-06-06Android使用動畫設(shè)置ProgressBar進(jìn)度的方法
這篇文章主要為大家詳細(xì)介紹了Android使用動畫設(shè)置ProgressBar進(jìn)度的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-01-01Android回調(diào)與觀察者模式的實現(xiàn)原理
這篇文章主要為大家詳細(xì)介紹了Android回調(diào)與觀察者模式的實現(xiàn)原理,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-04-04