1. 程式人生 > >Zxing二維碼實現

Zxing二維碼實現

更多幹貨

前言:

  專案中我們也許只會用到二維碼的掃描和生成兩個功能,所以不必下載完整的jar包,使用簡化版的即可,下文可見。

  這篇文章講述:1、如果快速在專案中整合zxing,實現掃描和生成二維碼功能                  

         2、根據專案需求去修改原始碼實現我們的要求並進行優化

一、快速整合zxing二維碼

   下載完成後可以看到:

  

  我們從這些檔案中拷貝需要的到自己的專案中,下面開始:

  ①、res 目錄下 : raw資料夾 整個複製到個人專案相對位置

  ②、res --> values目錄下:ids.xml檔案中的內容全部複製到個人專案相對位置,個人專案沒有則直接複製檔案到相對位置

  ③、res --> values目錄下:colors.xml檔案中的內容全部複製到個人專案的相對位置

  ④、res --> layout目錄下:camera.xml 佈局檔案複製到個人專案相對位置

  ⑤、res --> drawable_mdpi 目錄下:navbar.9.png圖片複製到個人專案相對位置,這張圖片是標題欄背景圖片,這裡建議先改成navbar.png 不要使用.9圖片 

  ⑥、libs目錄下:zxing.jar檔案複製到個人專案相對位置,並且右鍵點選as library

  ⑦、src --> com目錄下:zxing 資料夾複製到個人專案相對位置 ,會報錯,修改R的目錄結構即可

  ⑧、AndroidManifest.xml檔案中 新增 (二維碼掃描activity,這個需要後面自己去修改,用於實現自己的要求)

 <activity android:name="com.zxing.activity.CaptureActivity"/>

  ⑨、AndroidManifest.xml檔案中 新增許可權

  <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

2、準備工作完成了,下面開始寫demo

  現在需求是一個主介面MainActivity.java 裡面有兩個按鈕,分別跳轉 生成二維碼介面和 掃描二維碼介面

  

  然後分別開始寫兩個activity功能的實現:

  ①、 生成二維碼 

    先寫佈局檔案  ,一個圖片 , 一個開始生成按鈕 , 一個輸入框(二維碼需要根據文字資訊生成,沒有文字資訊無法生成)

 activity_create.xml

    activity程式碼: 程式碼比較簡單 ,不在此解釋了

複製程式碼

   private ImageView create_img;
    private Button create_btn;
    private EditText create_edit;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_create);

        initView();
        initEvent();

    }

    private void initEvent() {
        create_btn.setOnClickListener(this);
    }

    private void initView() {
        create_img = (ImageView) findViewById(R.id.create_img);
        create_btn = (Button) findViewById(R.id.create_btn);
        create_edit = (EditText) findViewById(R.id.create_edit);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.create_btn:
                String content = "" ;
                if (create_edit.getText().toString().equals("")){
                    Toast.makeText(this,"請輸入二維碼資訊",Toast.LENGTH_SHORT).show();
                    return;
                }
                content = create_edit.getText().toString();
                try {
                    //生成二維碼圖片,第一個引數是二維碼的內容,第二個引數是正方形圖片的邊長,單位是畫素
                    Bitmap qrcodeBitmap = EncodingHandler.createQRCode(content, 800);
                    if (qrcodeBitmap!=null) {
                        create_img.setImageBitmap(qrcodeBitmap);
                    }else{
                        Toast.makeText(this,"生成二維碼失敗",Toast.LENGTH_SHORT).show();
                    }
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                break;
        }
    }

    public byte[] Bitmap2Bytes(Bitmap bm) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
        return baos.toByteArray();
    }

複製程式碼

  效果圖:

         

 ②、掃描二維碼

  這個就更簡單了,只需要開啟一個zxing提供的activity 然後獲取到掃描得到的字串即可

  看ScanActivity(掃描Activity)的關鍵程式碼

複製程式碼

private TextView zxing_content;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_scan);
    zxing_content = (TextView) findViewById(R.id.zxing_content);
    Intent startScan = new Intent(this,CaptureActivity.class);
    startActivityForResult(startScan, 0);  //實際打開了一個zxing提供給我們的掃描activity,當然我們後面會對這個activity進行一些優化修改

}

/**
 * 掃一掃,成功後返回值進行判斷
 */
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == -1) {
        String result = data.getExtras().getString("result");
        zxing_content.setText(result);  //顯示掃描二維碼得到的資料
    }
}

複製程式碼

佈局檔案:

 activity_scan

效果圖:

        

二、修改原始碼,實現專案的需求

1、修改掃描二維碼的介面

  對應的是 zxing-->activity-->CaptureActivity.java   ,佈局檔案為 camera.xml

  所以修改介面只需要在 camera.xml檔案中修改即可。

  無非就是把原來的“CANCEL”取消按鈕去掉,把頂部的標題欄換一下。

  佈局裡面有一個 <SurfaceView>控制元件 用於顯示相機拍出的畫面預覽,這裡可以根據需求改是全介面顯示還是顯示區域性

            <com.zxing.view.ViewfinderView>控制元件,即掃描框,預設的是寬高比1:1.5,實際需要修改寬高,在下面介紹

2、修改掃描框的寬高

 第1步操作做完之後會發現,我們沒法修改掃描框的寬高。

 修改掃描框寬高很簡單,找到 zxing-->camera-->CameraManager.java 檔案

 這裡較為頂部的程式碼中看到:

  private static final int MIN_FRAME_WIDTH = 240;
  private static final int MIN_FRAME_HEIGHT = 240;
  private static final int MAX_FRAME_WIDTH = 480;
  private static final int MAX_FRAME_HEIGHT = 480;

  這四個屬性的值即掃描框的寬高,然後可以根據需求直接修改,當然這個值在不同解析度的裝置上寬高不一致 , 有需要的話可以進行一下單位轉換

  public static  int Dp2Px( Context context,float dp) {
    final float scale = context.getResources().getDisplayMetrics().density;
    return (int) (dp * scale + 0.5f);
  }

 效果圖: 我修改了掃描框的最小最大寬高分別一致,並且載camera.xml佈局中刪去了“CANCEL”取消按鈕

  

3、給掃描框新增文字提示

  看一下微信的掃描介面,會發現掃描框下面有一段文字提示。 那麼我們這裡沒有,需要新增

  找到zxing-->view-->Viewfinderview.java

  這裡是自定義掃描框的類

  找到程式碼:

    canvas.drawRect(frame.left + 2, middle - 1, frame.right - 1, middle + 2, paint);

      Collection<ResultPoint> currentPossible = possibleResultPoints;

  在這兩行程式碼之間我們畫上文字提示

複製程式碼

    canvas.drawRect(frame.left + 2, middle - 1, frame.right - 1, middle + 2, paint);
    TextPaint textPaint = new TextPaint();
      textPaint.setARGB(0xFF, 0xFF, 0xFF,0xFF);   //字型顏色
      textPaint.setTextSize(32);    //字型大小
      textPaint.setAntiAlias(true);  //設定抗鋸齒,否則字跡會很模糊
      StaticLayout layout = new StaticLayout("將二維碼放入框內,即可自動掃描",textPaint,
              frame.right-frame.left, Layout.Alignment.ALIGN_NORMAL,1.0F,0.0F,true);
      canvas.translate(frame.left+5, (float) (frame.bottom + (float)30)); //繪製起始位置
      layout.draw(canvas);
    Collection<ResultPoint> currentPossible = possibleResultPoints;

複製程式碼

  然後在看下掃描介面效果圖:

  

4、解決掃描介面相機預覽拉伸變形問題

      實現了上面幾步的優化,仔細的同學可能會發現,如果我們給SurfaceView設定全屏顯示(可以看到的相機畫面很多),會發現相機拍攝出來的預覽圖有些拉伸變形

  原因:zxing橫屏變豎屏之後,Camera的程式碼還是採用的橫屏程式碼設定的引數

    優化方法:找到 zxing-->camera--> CameraConfigurationManager.java 

複製程式碼

initFromCameraParameters方法中,

在 Log.d(TAG, "Screen resolution: " + screenResolution);這句之後增加
Point screenResolutionForCamera = new Point();
screenResolutionForCamera.x = screenResolution.x;
screenResolutionForCamera.y = screenResolution.y;
        
if (screenResolution.x < screenResolution.y) {
screenResolutionForCamera.x = screenResolution.y;
screenResolutionForCamera.y = screenResolution.x;
 }
再將cameraResolution = getCameraResolution(parameters, screenResolution);

更改為

cameraResolution = getCameraResolution(parameters, screenResolutionForCamera);

複製程式碼

 完成之後,在進行掃描操作,這時候相機拍出來的預覽介面就正常顯示,不再有拉伸變形問題。

 至此便給專案引入了一個可以使用的二維碼模組功能了。