1. 程式人生 > >Android 基於zxing的二維碼掃描功能的簡單實現及優化

Android 基於zxing的二維碼掃描功能的簡單實現及優化

由於專案中需要接入一下簡單的二維碼掃描功能,最終使用 zxing 來實現,把官方例子中的部分程式碼摘除出來做了簡單的封裝,並進行了一些優化。這裡簡單做一個記錄。

掃描二維碼

Android 中關於二維碼掃描的庫有很多,但是歸根到底無外乎下面這幾種實現方案:

其中基於以上兩者實現的比較知名的庫有:

後面這兩個開源庫做的都挺好,可定製化也挺高。不過什麼事情都要根據需求來定,就目前的需求而言用不到這麼複雜的功能,所以就自己來對官方的專案做一些改造。

整合 zxing

因為之前做二維碼掃描都是直接整合別人做好的開源方案,也沒有看過官方的專案,所以第一眼看到 zxing 官方的專案是懵逼的,不知道從哪下手。不過官方很人性化的寫了wiki——

Getting Started Developing,仔細閱讀以下也挺簡單,在 Android 中使用主要有以下兩步:

  • 將需要的東西(例如 core)編譯成 jar 包或者直接從 maven 中下載
  • 編譯 android 這個模組

不過官方文件中使用的是 mvn 命令,由於沒有使用過 mvn,所以也不用按照官方的文件來做了,不過步驟大同小異。

  • 方法一

首先 clone 下需要的模組:

然後將 core 編譯成 jar 包,將 android 作為工程或者module匯入到 Android stuido 中,然後引入 jar 包就可以了。

  • 方法二

這裡還有一個更省力的辦法,只 clone android 模組,然後作為工程或者 modlue 匯入到 Android stuido 中,然後再 gradle 中新增 zxing 的依賴就行了

compile group: ‘com.google.zxing’, name: ‘core’, version: ‘3.3.2’

這個執行會提示缺少 CameraConfigurationUtils 類,這個類在 android-core 這個模組中,我的做法是直接把這個類拷貝到工程中。

然後執行專案即可,執行成功以後是一個 Android 二維碼掃描器,apk 下載

優化

官方的 demo 中功能挺多,開啟http、分享、生成二維碼等等。不過專案中用不了這麼多功能。梳理一下官方的程式碼:

  • CaptureActivity 掃描二維碼的 activity;
  • ViewfinderView 掃描框 view;
  • CameraManager 相機管理;
  • OpenCameraInterface 開啟相機的具體操作類;
  • CaptureActivityHandler 是 CaptureActivity 類中使用的 handler,主要通過他來完成訊息傳遞;
  • DecodeThread 圖片解碼執行緒;

其他的因為沒有使用到暫時沒有去管。然後根據需要把一些不必要的程式碼和邏輯刪除剩下的就是一些優化工作。

在使用中主要對他做了兩個地方的優化:

  • 增加了許可權檢查
  • 把相機的關閉和開啟放在了子執行緒中

把相機的關閉和開啟放在子執行緒中

因為相機的開啟和關閉是耗時操作,會造成主執行緒阻塞,然後開啟頁面卡頓,參考支付寶和微信在開啟的時候有一個短暫的載入框,所以這裡把相機的開啟關閉放在了子執行緒中來做。主要程式碼有下面這這些:

開啟相機

public final class OpenCameraInterface extends Thread {

    private static final String TAG = OpenCameraInterface.class.getName();

    private OpenCamera openCamera;

    private CaptureActivityHandler handler;
    // handler 用來和主執行緒通訊
    public void setHandler(CaptureActivityHandler handler) {
        this.handler = handler;
    }
    // 由於 camera 物件不能通過 handler 來傳遞,所以放在這裡通過 get 的方式來獲取。
    public OpenCamera getOpenCamera() {
        return openCamera;
    }

    private OpenCamera open() {
        int numCameras = Camera.getNumberOfCameras();
        if (numCameras == 0) {
            Log.w(TAG, "No cameras!");
            return null;
        }

        int cameraId = 0;
        while (cameraId < numCameras) {
            Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
            Camera.getCameraInfo(cameraId, cameraInfo);
            if (CameraFacing.values()[cameraInfo.facing] == CameraFacing.BACK) {
                break;
            }
            cameraId++;
        }
        if (cameraId == numCameras) {
            Log.i(TAG, "No camera facing " + CameraFacing.BACK + "; returning camera #0");
            cameraId = 0;
        }

        Log.i(TAG, "Opening camera #" + cameraId);
        Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
        Camera.getCameraInfo(cameraId, cameraInfo);
        Camera camera = Camera.open(cameraId);
        if (camera == null) {
            return null;
        }
        return new OpenCamera(cameraId,
                camera,
                CameraFacing.values()[cameraInfo.facing],
                cameraInfo.orientation);
    }

    @Override
    public void run() {
        try {
            openCamera = open();
        } catch (Exception e) {
            openCamera = null;
        }
        handler.sendEmptyMessage(R.id.open_camera_complete);
    }
}

在 CameraManager 中增加一個方法。

    public void openCamera(CaptureActivityHandler handler) {
        // 這裡把開啟相機放在子執行緒中
        if (camera != null) {
            return;
        }
        threadOpen = new OpenCameraInterface();
        threadOpen.setHandler(handler);
        threadOpen.start();
    }

在 CaptureActivity 中增加一個方法在接到子執行緒發來的訊息後再初始化預覽等。這裡通過標誌位來判斷是直接進行初始化還是等待 SurfaceView 建立完成以後再進行初始化。

    public void openCameraComplete() {
        // 如果已有 SurfaceView 就可以繼續建立 否則就等待SurfaceView 建立完以後自動執行
        isCameraComplete = true;

        if (hasSurface) {
            SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view);
            SurfaceHolder surfaceHolder = surfaceView.getHolder();
            initCamera(surfaceHolder);
        }
    }

關閉相機

在關閉相機的時候需要增加必要的執行緒同步,否則可能造成相機未被關閉。

    public synchronized void closeDriver() {
        // 結束也是耗時操作 方在子執行緒中
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    // 為了防止在快速切換時出現問題,這裡等待開啟操作完成後再結束
                    threadOpen.join();
                    if (camera == null) {
                        camera = threadOpen.getOpenCamera();
                    }
                } catch (InterruptedException e) {
                    Log.e(TAG, e.toString());
                }
                camera.getCamera().release();
                camera = null;
            }
        }).start();
    }

然後就是許可權檢查這一塊了,沒什麼好說的在開啟相機之前做必要的許可權檢查就行了。需要注意的是根據官方文件,在 activity onPause 的時候需要關閉相機,然後在 onResume() 中重新開啟。而申請的彈出框會導致 activity 的 onResume 重複呼叫,針對這種情況需要做好處理。

以上就是關於 zxing 的簡單整合的所有內容,原始碼已經放在了 GitHub 上,僅供參考。commonTest-zxing

參考

相關推薦

Android 基於Zxing掃描的光速實現

Android 十分鐘光速實現二維碼掃描 前言 在專案中要使用到二維碼的相關內容,我們第一時間想到的是使用大名鼎鼎的zxing或者ZBar開源框架: 除了這兩個有名的框架之外,還有@bingoogolapple大神的掃描庫 以及國外@dlaz

phonegap的掃描功能實現

    首先簡單的介紹下DOS環境下phonegap專案的結構,如下圖:    如果大家的專案結構和上圖中專案結構一樣,就可以按照下面的步驟來實現掃描二維碼的功能了,不一樣的下面的步驟也可以提供一定的參考。 ####################START#######

Android 基於zxing掃描功能簡單實現優化

由於專案中需要接入一下簡單的二維碼掃描功能,最終使用 zxing 來實現,把官方例子中的部分程式碼摘除出來做了簡單的封裝,並進行了一些優化。這裡簡單做一個記錄。 掃描二維碼 Android 中關於二維碼掃描的庫有很多,但是歸根到底無外乎下面這幾種

Android實現掃描功能)-ZXing個性化與近距離識別優化

簡介 本篇我們對掃碼介面進行優化,並對ZXing近距離無法識別的問題做出優化。 個性化定製 每個APP都有自己的表現形式,實現個性化掃碼介面定製,主要有兩個地方: activity_scanner.xml介面檔案 com.google.zxin

Android之在Fragment中使用掃描功能

最近在做一個專案,是在Fragment中使用zxing的二維碼掃描功能,在我以前寫的二維碼掃描功能的教程只適合在activity中使用地址:https://blog.csdn.net/qq_31844349/article/details/81301911 沒有辦法因為工作需要,必須在Fra

Android實現掃描功能(三)-閃光燈控制

簡介 本篇我們對光線暗淡情況下閃光燈的使用做出介紹。 效果 晚上測試時: 開燈後: 未開燈: 實現步驟 1、在activity_scanner.xml介面上加上閃光燈開關按鈕。可以是Button、Checkbox等控制元件。

Android開發之Zbar實現掃描功能

前言: 在寫這篇文章之前已經寫過兩篇關於二維碼功能的文章,有興趣的可以看看——》文章1:Android開發之利用ZXing庫實現二維碼的掃描;文章2:Android開發之利用ZXing庫實現二維碼的生成,這兩篇文章中使用到的二維碼生成庫是ZXing,在本篇

Android中Webview與原生介面互動掃描功能實現

最近專案中有一個新的需求,大致是這樣的:APP中通過WebView展示一個第三方的HTML5介面,使用者可以在HTML5介面中呼叫Android攝像頭進行二維碼掃描,並將掃描結果顯示在HTML5介面。這顯然涉及到了Android原生與WebView之前的傳值

Android Zxing掃描圖片拉伸、掃描框過小、掃描框擴大後(或不拉伸後)閃退問題

(一)Zxing二維碼掃描框大小調整 控制掃描框大小程式碼是在CameraManager類中 google在CameraManager類中設定掃描框大小主要在getFramingRect()中: private static final int MIN_F

Android開發中的掃描功能

Android開發中的二維碼掃描 現在Android開發中使用二維碼掃描功能越來越多,本篇部落格具體講一下其使用方法: 新增依賴 在自己的Activity或者Fragment中使用新增關於掃描的連結 新增二維碼掃描的相關Activity 對掃描資料進

基於MUI框架的使用HTML5+實現掃描功能並且其結果在webview中的資訊的傳遞

<!doctype html> <html> <head> <meta charset="UTF-8"> <title></title> <meta name="viewport" content="width=d

android 和 phonegap(Cordova)互動使用Zxing掃描

android方面的配置:配置環境,下載、編譯Zxing原始碼,整合進專案 1、環境下載、安裝,編譯Zxing原始碼 下載Zxing原始碼地址:https://github.com/zxing/zxing 其中android資料夾下為一個功能應用,有

基於MUI框架的使用HTML5+實現掃描功能

<!doctype html> <html> <head> <meta charset="UTF-8"> <title></title> <meta name="viewport" content="width=devi

Zxing掃描

ram zxing oss lean 預覽 surface ott serial pac 源代碼地址 有問題能夠加QQ:312122330 之前對於Zbar的二位碼掃描。到項目上線以後才發現掃描過於靈敏。導致有時候掃描到半截就啟動了。 後來翻看ZXIN

Zxing掃描的整合與優化

Zxing已經是一個很成熟的框架了,但它是用maven構建的專案,在以gradle為基礎的AS中整合起來總感覺不太方便。網上有很多種方式,我這裡主要採取了複製程式碼到自己專案中的方式,這樣有利於學習和擴充套件。 第一步:整合 官方專案地址:https://github.com

H5+ 掃描功能

二維碼在生活中的使用越來越廣泛,APP開發中,也越來越多的需求需要用到二維碼的掃描功能,以下就針對h5+的二維碼掃描功能做一些簡單的介紹; 1. var bc = new plus.barc

html5掃描功能實現

html5中可以使用二維碼掃描,也可以從相簿中選擇二維碼識別,程式碼如下 var ws = null, wo = null; var scan = null, domr

基於ZXing的使用幾行程式碼完成炫酷的效果

先來看效果圖怎樣,可以的話就留著用吧,開發中要的就是速度快,效果好,簡單易操作 1:在這裡寫個button按鈕用於啟動二維碼 2:這是開啟後的介面 左下角可以設定開啟燈光,右下角可以選擇相簿中的二維碼 一:喜歡的話往下看教你一步步實現,如果想把圖

android利用zbar掃描

原始碼下載 之前用zxing做開發,各種奇葩問題,橫屏修等等,而且效能也不搞。被測試批了,沒辦法後來換了zbar。效能好多了。 /*********************重要更新*******************************/ 有朋友提到兩個問題: 1.

zxing 掃描 配置和使用

二維碼掃描使用最多的主要有兩個庫:zbarSDK 和zxing 關於zbar的使用比較簡單,在這裡不多說了,對於zxing的使用就比較麻煩,雖然網上有很多關於zxing的使用方法,不過查了很多中文和英文的貼子。發現說的都不夠詳細,對與像我這樣第一次搞的新手來說差一步就錯了很