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
參考
版權宣告:本文為博主原創文章,轉載請宣告出處,請尊重別人的勞動成果,謝謝!
相關文章
- 基於ZXing Android實現生成二維碼圖片和相機掃描二維碼圖片即時解碼的功能Android
- Android 基於Zxing掃碼實現(三)、從相簿選取二維碼Android
- Google zxing實現二維碼掃描完美解決方案Go
- Android實現掃描二維碼Android
- zxing第三方框架實現二維碼掃描以及生成框架
- 簡單易用的二維碼掃描工具:QR Capture for MacAPTMac
- 使用 Swift 建立簡單的二維碼掃描應用Swift
- Android 二維碼掃描和生成二維碼Android
- 基於ZXingAndroid實現生成二維碼圖片和相機掃描二維碼圖片即時解碼的功能Android
- React Native 實現二維碼掃描React Native
- Android二維碼生成與掃描Android
- ZXing實現二維碼的生成與解析
- iOS二維碼掃描iOS
- 自定義 React Native 二維碼掃描元件(簡單,易用!)React Native元件
- iOS中二維碼掃描iOS
- 基於 Zxing 封裝的 Hndxing 掃碼庫封裝
- cocos2dx-lua在ios上實現生成及掃描二維碼iOS
- iOS 使用CIDetector掃描相簿二維碼、原生掃描iOSIDE
- 掃描二維碼登入思路
- 安卓自定義二維碼掃描安卓
- IOS 使用 ZbarSDK 二維碼掃描iOS
- iOS 掃描二維碼/條形碼iOS
- 優化Oracle with全表掃描的問題(二)優化Oracle
- 使用ionic2開發一個二維碼掃描功能
- ubuntu安裝zbar二維碼掃描Ubuntu
- iOS開發之掃描二維碼iOS
- Android | 教你如何開發掃二維碼功能Android
- iOS開發-原生二維碼的掃描和生成iOS
- 使用HTML5實現掃描PC二維碼且觸發WAP端上傳資源功能HTML
- Android----二維碼掃描、生成、相簿識別(16號)Android
- 一對一直播系統開發如何在頁面內實現掃描二維碼功能
- 關於索引掃描的極速調優實戰(第二篇)索引
- iOS 掃描二維碼(ZBarSDK)遇到的坑~解決方法iOS
- 最完善,快速的 react-native 二維碼掃描React
- 如此簡單遠端漏洞掃描實現雲安全
- 基於python編寫一個簡單的多執行緒埠掃描指令碼Python執行緒指令碼
- XQRCode 一個非常方便實用的二維碼掃描、解析、生成庫
- 聊天室原始碼開發,如何簡單的實現掃碼登入功能?原始碼