Android項目實戰(二十八):Zxing二維碼實現及優化

来源:http://www.cnblogs.com/xqxacm/archive/2016/11/21/6078729.html
-Advertisement-
Play Games

前言: 多年之前接觸過zxing實現二維碼,沒想到今日項目中再此使用竟然使用的還是zxing,百度之,竟是如此牛的玩意。 當然,項目中我們也許只會用到二維碼的掃描和生成兩個功能,所以不必下載完整的jar包,使用簡化版的即可,下文可見。 這篇文章講述:1、如果快速在項目中集成zxing,實現掃描和生成 ...


前言:

  多年之前接觸過zxing實現二維碼,沒想到今日項目中再此使用竟然使用的還是zxing,百度之,竟是如此牛的玩意。

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

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

         2、根據項目需求去修改源碼實現我們的要求併進行優化

 

一、快速集成zxing二維碼

1、下載庫文件 : http://download.csdn.NET/detail/u013210620/9036083   ,文件名:BarCodeTest

   下載完成後可以看到:

  

  我們從這些文件中拷貝需要的到自己的項目中,下麵開始:

  ①、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功能的實現:

  ①、 生成二維碼 

    先寫佈局文件  ,一個圖片 , 一個開始生成按鈕 , 一個輸入框(二維碼需要根據文本信息生成,沒有文本信息無法生成)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.maiji.zxingdemo.CreateActivity">


    <ImageView
        android:id="@+id/create_img"
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:scaleType="fitXY"
        android:layout_gravity="center_horizontal"
        />

    <Button
        android:id="@+id/create_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="開始生成二維碼"
        />

    <EditText
        android:id="@+id/create_edit"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>
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); //顯示掃描二維碼得到的數據
}
}

佈局文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.maiji.zxingdemo.ScanActivity">

    <TextView
        android:id="@+id/zxing_content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:textSize="30sp"
        />
</RelativeLayout>
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);

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

 至此便給項目引入了一個可以使用的二維碼模塊功能了。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 說到RecyclerView,相信大家都不陌生,它是我們經典級ListView的升級版,升級後的RecyclerView展現了極大的靈活性。同時內部直接封裝了ViewHolder,不用我們自己定義ViewHolder就能實現item的回收和復用功能。當然它肯定不止這些好處,比如我們可以自定義分割線,... ...
  • 1、打開CornerStone,找到偏號設置,找到Subversion選項 2、去看“Use default global ignores”前面的“勾”,刪除".a" 3、github上搜索“gitignore”,找到"Objective-C.gitignore",打開,對照著添加 4、添加以下幾項 ...
  • 一、寫在最前面 本次,來介紹一下安卓中為控制項--Button綁定事件的五種方式。 二、具體的實現 第一種:直接綁定在Button控制項上: 步驟1.在Button控制項上設置android:onClick=",其中這個屬性的屬性值對應的是MainActivity類中的方法名字(自己創建的方法): 步驟2 ...
  • 項目中經常需要底部彈出框,這裡我整理一下其中我用的比較順手的一個方式(底部彈出一個橫向滿屏的dialog)。 效果圖如下所示(只顯示關鍵部分): 步驟如下所示: 1.定義一個dialog的佈局(lay_share.xml) 1 <?xml version="1.0" encoding="utf-8" ...
  • 多線程學習 每一個iOS應用(進程)運行都會有一個主線程(UI線程),UI上的更新推薦在主線程中去完成。多線程本身並不複雜,難點在於多個線程在其生命周期的管理,如線程的執行順序、線程間的數據共用以及資源競爭等問題。 本文主要記錄開發中常用的3種多線程模式: NSThread NSOperation ...
  • 前言 學習本系列內容需要具備一定 HTML 開發基礎,沒有基礎的朋友可以先轉至 "HTML快速入門(一)" 學習 本人接觸 React Native 時間並不是特別長,所以對其中的內容和性質瞭解可能會有所偏差,在學習中如果有錯會及時修改內容,也歡迎萬能的朋友們批評指出,謝謝 文章第一版出自簡書,如果 ...
  • 就目前來說Retrofit2使用的已相當的廣泛,那麼我們先來瞭解下兩個問題: 1 . 什麼是Retrofit? Retrofit是針對於Android/Java的、基於okHttp的、一種輕量級且安全的、並使用註解方式的網路請求框架。 2 . 我們為什麼要使用Retrofit,它有哪些優勢? ... ...
  • 模擬器的位置: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs 文檔安裝位置: /Applications/Xcode.app/Contents/Develope ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...