Android 二維碼 產生和識別(附Demo源碼)

來源:互聯網
上載者:User

標籤:

Edited by mythou

原創博文,轉載請標明出處:http://www.cnblogs.com/mythou/p/3280023.html

已測試  --  絕對靠譜

 

今天講一下目前移動領域很常用的技術——二維碼。現在大街小巷、各大網站都有二維碼的蹤跡,不管是IOS、Android、WP都有相關支援的軟體。之前我就想瞭解二維碼是如何工作,最近因為工作需要使用相關技術,所以做了初步瞭解。今天主要是講解如何使用ZXing庫,產生和識別二維碼。這篇文章實用性為主,理論性不會講解太多,有興趣可以自己查看源碼。

 

1、ZXing庫介紹

  這裡簡單介紹一下ZXing庫。ZXing是一個開放源碼的,用Java實現的多種格式的1D/2D條碼影像處理庫,它包含了聯絡到其他語言的連接埠。Zxing可以實現使用手機的內建的網路攝影機完成條碼的掃描及解碼。該項目可實現的條碼編碼和解碼。目前支援以下格式:UPC-A,UPC-E、EAN-8,EAN-13、39碼、93碼。ZXing是個很經典的條碼/二維碼識別的開源類庫,以前在功能機上,就有開發人員使用J2ME運用ZXing了,不過要支援JSR-234規範(自動對焦)的手機才能發揮其威力。

  下面是ZXing的demo運行,我這裡建立了一個二維碼,內容是我部落格的網址,大夥可以用的掃一掃功能,試一下。就可以直接開啟我部落格。 2、ZXing庫主要類

  下面給大家介紹一下,ZXing庫裡面主要的類以及這些類的作用:

  • CaptureActivity。這個是啟動Activity 也就是掃描器。
  • CaptureActivityHandler 解碼處理類,負責調用另外的線程進行解碼。
  • DecodeThread 解碼的線程。
  • com.google.zxing.client.android.camera 包,網路攝影機控制包。
  • ViewfinderView 自訂的View,就是我們看見的拍攝時中間的框框了。

 

3、使用ZXing產生二維碼

  下面針對二維碼產生和解析做個簡單介紹,至於詳細的使用方法,建議大家還是自己看看源碼,使用起來很簡單,不過這個開源項目的代碼,值得好好看看。首先給出二維碼產生的方法:

//Edited by mythou//http://www.cnblogs.com/mythou/  //要轉換的地址或字串,可以是中文    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");            //映像資料轉換,使用了矩陣轉換            BitMatrix bitMatrix = new QRCodeWriter().encode(url, BarcodeFormat.QR_CODE, QR_WIDTH, QR_HEIGHT, hints);            int[] pixels = new int[QR_WIDTH * QR_HEIGHT];            //下面這裡按照二維碼的演算法,逐個產生二維碼的圖片,            //兩個for迴圈是圖片橫列掃描的結果            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();        }    }
View Code

上面就是二維碼產生的方法介面,如果你只是使用者方法,很簡單,只要傳入一個URL即可,就像我裡面一樣,傳入一個合法的網址即可。或者像現在一些移動APP的推廣,把APP轉為二維碼,只要掃一下就可以下載相應的APP。這個也是目前比較流行的APP的推廣方式。

  上面代碼做的事情不多,主要是調用ZXing庫裡面QRCodeWriter().encode的方法對我們傳進去的URL進行編碼,具體如何編碼,這個我這裡就不詳細說,有興趣可以看ZXing的源碼。文章最後會給出ZXing的源碼和例子代碼。

 

4、掃描二維碼擷取資訊

  掃描擷取二維碼資訊的工作稍微複雜一些,主要是需要編寫Camera的使用,這個跟我們一般使用Camera一樣,需要使用Surfaceview作為預覽,這一部我這裡就不說了,這個應該不是太複雜。對於使用過Camera做預覽的朋友,應該是挺簡單的事情。擷取二維碼資料的關鍵處理是在Camera的自動對焦回呼函數哪裡,調用ZXing的解碼介面。

//Edited by mythou//http://www.cnblogs.com/mythou/   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();    }  }
View Code

這裡稍微多說一句,由於解碼需要一定時間,所以ZXing的解碼調用,都是使用了Handler作為線程通訊機制,解碼的工作都是放在獨立線程裡面使用的,如果你直接在主線程解碼,恐怕ANR問題是避免不了。

//Edited by mythou//http://www.cnblogs.com/mythou/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:    //解碼成功,擷取到介面的結果和原來的二維碼資料        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;    }  }
View Code

  上面是解碼的線程處理不同狀態的時候需要注意的地方,我們這裡只看擷取映像成功的地方,成功擷取圖片解碼的實在DecodeThread裡面實現,DecodeThread裡面解碼成功後,會把資料序列化,然後儲存到Bundle裡面,我們可以直接通過Bundle的序列化,擷取到圖片資料。同時會把解碼後的結果儲存到MSG裡面,然後就可以根據實際情況進行處理,例如上面代碼,解碼成功後,會調用一個處理函數:

//Edited by mythou//http://www.cnblogs.com/mythou/  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("掃描結果");        dialog.setMessage(obj.getText());        dialog.setNegativeButton("確定", new DialogInterface.OnClickListener()        {            @Override            public void onClick(DialogInterface dialog, int which)            {                //用預設瀏覽器開啟掃描得到的地址                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();    }
View Code

上面就是整個二維碼的解碼流程,裡面因為涉及很多Camera的使用,所以你如果需要使用二維碼識別,需要注意一下你的程式需要申請下面的許可權,一般的Camera使用以及Camera的自動對焦等。

//Edited by mythou//http://www.cnblogs.com/mythou/ <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" />
View Code

5、結語

  上面就是產生和識別二維碼的關鍵流程和代碼,有興趣的朋友可以自己查看ZXing的源碼,裡面有很多映像分析的知識可以學習。具體使用也可以參考我下面給出的Demo。二維碼對於現在移動開發來說很是很常用的技術,所以有空可以瞭解一下,說不定什麼時候就用上了。另外,ZXing庫除了二維碼外,其實對於條碼也是支援的,只是我這裡沒有介紹。有需要的自己去看看源碼即可。

 

2013-8-16

Edited by 泡泡糖

ZXing開源項目Google Code地址:https://code.google.com/p/zxing/

ZXingDemo下載:ZXingDemo2013-8-25.rar 

Android 二維碼 產生和識別(附Demo源碼)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.