Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 玩轉Android之二維碼生成與識別

玩轉Android之二維碼生成與識別

編輯:關於Android編程

二維碼,我們也稱作QRCode,QR表示quick response即快速響應,在很多App中我們都能見到二維碼的身影,最常見的莫過於微信了。那麼今天我們就來看看怎麼樣在我們自己的App中集成二維碼的掃描與生成功能。OK,廢話不多說,我們就開始做吧。

二維碼的使用我主要想分為兩部分來給大家介紹,一部分就是二維碼的生成,這裡的知識點都很簡單,還有一部分是二維碼的識別,這裡稍微麻煩一些,不過細心來做其實也很簡單。二維碼的開發使用我們大多都是使用Google提供的zxing這個類庫,使用這個類庫我們需要先下載核心jar包,下載地址,如果我們只想生成二維碼那麼這個就夠了,但是如果我們還想做二維碼的識別,那麼我們需要在剛才的基礎上繼續添加GitHub上的開源項目,這個我們在後面再說。

1.二維碼的生成

先來看一張效果圖:

\

1.1 准備工作

如果我們只做二維碼的生成,那麼只需要添加核心jar包即可,如下:

\

1.2 二維碼生成

OK,添加完jar包之後我們就可以開始寫二維碼生成代碼了,二維碼本身就是一張Bitmap圖片,所以我們這裡主要就是看怎麼樣來生成這張圖片,我在主界面添加一個按鈕和一個ImageView,當點擊按鈕時生成一張二維碼圖片顯示在ImageView上。布局如下:

 



當我點擊按鈕時生成二維碼圖片,那我們就來看看生成二維碼圖片的核心代碼:

 

 

    private Bitmap generateBitmap(String content,int width, int height) {
        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        Map hints = new HashMap<>();
        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
        try {
            BitMatrix encode = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, width, height, hints);
            int[] pixels = new int[width * height];
            for (int i = 0; i < height; i++) {
                for (int j = 0; j < width; j++) {
                    if (encode.get(j, i)) {
                        pixels[i * width + j] = 0x00000000;
                    } else {
                        pixels[i * width + j] = 0xffffffff;
                    }
                }
            }
            return Bitmap.createBitmap(pixels, 0, width, width, height, Bitmap.Config.RGB_565);
        } catch (WriterException e) {
            e.printStackTrace();
        }
        return null;
    }

首先這個方法接收三個參數,這三個參數分別表示生成二維碼的文本內容(你要把哪一個文本用二維碼圖片表示出來),第二個和第三個參數分別表示生成的二維碼圖片的寬和高。在這裡,我們首先要獲得一個QRCodeWriter實例,該實例中有一個方法叫做encode,通過該方法對文本內容進行編碼,該方法共有五個參數,第一個參數表示生成二維碼的文本內容,第二個參數表示編碼格式,第三個參數表示生成的二維碼的寬度,第四個參數表示生成的二維碼的高度,第五個參數可選,可以用來設置文本的編碼,encode方法的返回值是一個BitMatrix,你可以把BitMatrix理解成一個二維數組,這個二維數組的每一個元素都表示一個像素點是否有數據。OK,接下來我們需要定義一個int數組用來存放Bitmap中所有像素點的顏色,可是我們又怎麼知道每一個像素點是什麼顏色呢?這個時候就需要我們遍歷BitMatrix了,如果BitMatrix上的點表示 該點有數據,那麼對應在Bitmap上的像素點就是黑色,否則就是白色。BitMatrix中的get方法的返回值為一個boolean類型,true表示該點有數據,false表示該點沒有數據。通過兩個嵌套的for循環將BitMatrix遍歷一遍,然後給pixels數組都賦上值,OK,pixels數組有值之後,接下來調用Bitmap的createBitmap方法創建一個Bitmap出來就可以了,createBitmap方法共接收6個參數,第一個參數表示Bitmap中所有像素點的顏色,第二個參數表示像素點的偏移量,第三個參數表示Bitmap每行有多少個像素點,第四個參數表示生成的Bitmap的寬度,第五個參數表示生成的Bitmap的高度,第六個參數表示生成的Bitmap的色彩模式,因為二維碼只有黑白兩種顏色,所以我們可以不用考慮透明度,直接使用RGB_565即可。OK,這樣的話我們就獲取到了二維碼的圖片了,最後我們再來看看點擊事件:

 

 

    public void generate(View view) {
        Bitmap qrBitmap = generateBitmap("http://www.csdn.net",400, 400);
        iv.setImageBitmap(qrBitmap);
    }

效果圖如下:

 

\

1.3 給二維碼中心添加Logo

OK,如果你沒有特殊的需求那麼這樣就OK了,但是我們見到的大多數二維碼的正中心都有一個Logo,那麼這個效果要怎麼實現呢?這裡就是圖片繪制的內容了,我封裝了一個方法專門來解決這個問題,代碼如下:

 

    private Bitmap addLogo(Bitmap qrBitmap, Bitmap logoBitmap) {
        int qrBitmapWidth = qrBitmap.getWidth();
        int qrBitmapHeight = qrBitmap.getHeight();
        int logoBitmapWidth = logoBitmap.getWidth();
        int logoBitmapHeight = logoBitmap.getHeight();
        Bitmap blankBitmap = Bitmap.createBitmap(qrBitmapWidth, qrBitmapHeight, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(blankBitmap);
        canvas.drawBitmap(qrBitmap, 0, 0, null);
        canvas.save(Canvas.ALL_SAVE_FLAG);
        float scaleSize = 1.0f;
        while ((logoBitmapWidth / scaleSize) > (qrBitmapWidth / 5) || (logoBitmapHeight / scaleSize) > (qrBitmapHeight / 5)) {
            scaleSize *= 2;
        }
        float sx = 1.0f / scaleSize;
        canvas.scale(sx, sx, qrBitmapWidth / 2, qrBitmapHeight / 2);
        canvas.drawBitmap(logoBitmap, (qrBitmapWidth - logoBitmapWidth) / 2, (qrBitmapHeight - logoBitmapHeight) / 2, null);
        canvas.restore();
        return blankBitmap;
    }

addLogo這個方法接收兩個參數,第一個參數就是我們在1.2節中生成的二維碼的Bitmap圖片,第二個參數就是我們的logo圖片,在該方法中我先獲取到兩張Bitmap各自的寬高,然後創建一個新的空白的Bitmap,這個新的空白的Bitmap的寬高和二維碼的寬高一致,然後創建一個Canvas對象,創建Canvas對象的時候將blankBitmap傳入,這樣我一會繪制的東西相當於都是繪制在了blankBitmap上了。canvas的drawBitmap方法接收四個參數,第一個是你要繪制的Bitmap對象,第二個和第三個是你要繪制的Bitmap的左上角的坐標,第四個參數是一個畫筆,一般情況下我們給一個null就可以了,如果你要設置重復模式等等效果的時候可以不給null。我們使用drawBitmap方法先將原本的二維碼圖片繪制出來,繪制完成之後,調用canvas的save方法,將當前的繪制狀態保存下來,然後對畫布進行縮放,縮小畫布之後我們來繪制Logo,一幫情況下logo的寬高為二維碼原圖寬高的1/5(中心logo圖片不宜過大,否則會影響到二維碼的識別),所以我們先通過一個while循環獲得縮放比例,然後調用canvas的scale方法對畫布進行縮放,前兩個參數表示寬高的縮放比例,大於1表示放大,小於1表示縮小,後兩個參數表示縮放的中心點。縮放完成之後我們就可以繪制logo了,logo繪制完成之後,調用canvas的restore方法將畫布恢復為原來的狀態,最後將blankBitmap返回。在點擊事件中調用這個方法即可,代碼如下:

 

 

    public void generate(View view) {
        Bitmap qrBitmap = generateBitmap("http://www.csdn.net",400, 400);
        Bitmap logoBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
        Bitmap bitmap = addLogo(qrBitmap, logoBitmap);
        iv.setImageBitmap(bitmap);
    }

效果圖如下:

 

\

OK,至此,我們的二維碼生成就說完了,就是這麼簡單。

2.二維碼的識別

二維碼的識別是一個稍微麻煩的事情,一般情況下,我們直接使用GitHub上的開源項目zxing即可,這個項目就是在我們之前的那個核心包的基礎上完成的(下載地址)。當然,如果你需要自己定義相關的頁面等等也都可以,這個我們到後面再說。這裡我們先來看看怎麼把GitHub上的開源項目引入到我們的項目中來。

導入工程我們主要分為如下幾個步驟:

1.創建一個新的Project,命名為QRReader(這一步不是必須的,可以根據你的項目需求來)

2.下載ZXing項目

3.在新的Project中創建一個新的Module,在創建的過程中選擇Android Library,如下圖:

\

4.在文件夾中打開我們的項目,找到第三步創建的Library,將第二步下載的ZXing項目中的android和android-core兩個文件夾合並到library中,如下圖:

 

\

其中android文件夾中主要合並如下幾個項目文件:

\

合並完成之後再將我們之前下載的核心jar包夜拷貝到我們library的libs文件夾中,然後我們再來看看我們的library:

\

5.在我們的項目中引用這個module,然後對項目進行編譯。

6.編譯之後項目會報錯,這個時候需要我們將library中所有的switch語句改為if...else if ...else if的形式。

7.完成第6步之後還是會報錯,這個時候需要我們將library的清單文件中Application節點的icon屬性刪除,再編譯就沒有任何問題了。

OK,經過上面7個步驟這個開源項目就被我們成功的引入到我們自己的項目中了,在這個開源項目中有一個CaptureActivity,這個Activity專門用來掃描二維碼,所以我們只需要在自己的項目中直接來啟動這個Activity就可以了,另外,由於默認情況下CaptureActivity是啟動項,所以我們要在library的清單文件中刪除CaptureActivity作為啟動項的配置。

OK,現在我的項目中有一個按鈕,點擊這個按鈕我就可以掃描二維碼,代碼如下:

 

    public void go(View view) {
        startActivity(new Intent(this, CaptureActivity.class));
    }

 

OK,至此,一個簡陋的二維碼掃描就完成了,大家有木有覺得很麻煩啊?麻煩也就這一次,因為我把ZXing當作library使用的時候系統會自動生成一個aar包,有了這個aar包,以後的開發就會變得非常簡單了,那麼這個aar包在哪裡呢?如下圖:

\

對應的文件夾路徑大家自己去找,有了這個aar包之後,如果我再需要使用二維碼掃描功能的時候就只需要如下幾個簡單的步驟:

1.創建項目

2.創建Module,在創建Module時選擇Import .JAR/.AAR Package,然後選擇剛剛的aar包

3.在我的app中引用這個Module即可。

 


最後,我將我自己生成的aar包提供給大家,可以直接在項目中使用,非常方便,不過建議還是大家自己嘗試生成一個aar包,整個過程還是非常有意思。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved