从空白到扫码:ZXing与Android Camera无缝集成实战指南

从空白到扫码:ZXing与Android Camera无缝集成实战指南

【免费下载链接】zxing ZXing ("Zebra Crossing") barcode scanning library for Java, Android 【免费下载链接】zxing 项目地址: https://gitcode.com/gh_mirrors/zx/zxing

你是否还在为集成扫码功能时遇到的预览变形、对焦失效、解码延迟等问题烦恼?本文将带你通过ZXing库的Android实现,从0到1掌握相机预览到条码识别的完整流程,解决90%开发者会遇到的技术痛点。

读完本文你将获得:

  • 相机权限动态申请的最佳实践
  • 自定义扫码框的绘制技巧
  • 预览帧数据高效处理方案
  • 条码解码结果的优化展示
  • 闪光灯与自动对焦的智能控制

开发环境准备与权限配置

ZXing(ZXing ("Zebra Crossing"))是一个开源的条码扫描库,支持多种条码格式的识别。在Android项目中集成ZXing时,首先需要配置必要的权限和相机特性声明。

核心权限配置

ZXing的AndroidManifest.xml中声明了相机、闪光灯等必要权限:

<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.FLASHLIGHT"/>

同时需要声明相机特性支持:

<uses-feature android:name="android.hardware.camera.any"/>
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
<uses-feature android:name="android.hardware.camera.flash" android:required="false"/>

完整权限配置可参考android/AndroidManifest.xml文件。

项目结构概览

ZXing Android模块的核心代码组织如下:

android/
├── src/com/google/zxing/client/android/
│   ├── CaptureActivity.java        # 扫码主活动
│   ├── camera/                     # 相机管理模块
│   │   ├── CameraManager.java      # 相机控制核心类
│   │   └── OpenCameraInterface.java # 相机打开接口
│   └── ViewfinderView.java         # 自定义扫码框视图
└── res/layout/
    └── capture.xml                 # 扫码界面布局

相机初始化与预览控制

相机初始化是扫码功能的基础,ZXing通过CameraManager类封装了复杂的相机操作逻辑。

相机管理核心类

CameraManager负责相机的打开、参数配置和预览控制:

// 初始化相机
cameraManager = new CameraManager(getApplication());
// 设置扫码框
viewfinderView.setCameraManager(cameraManager);

android/src/com/google/zxing/client/android/camera/CameraManager.java中,openDriver方法处理了相机的打开和参数配置:

public synchronized void openDriver(SurfaceHolder holder) throws IOException {
  OpenCamera theCamera = camera;
  if (theCamera == null) {
    theCamera = OpenCameraInterface.open(requestedCameraId);
    if (theCamera == null) {
      throw new IOException("Camera.open() failed to return object from driver");
    }
    camera = theCamera;
  }
  // 配置相机参数...
  cameraObject.setPreviewDisplay(holder);
}

预览界面布局

扫码界面布局文件capture.xml定义了相机预览区域和扫码框:

<merge xmlns:android="http://schemas.android.com/apk/res/android">
  <!-- 相机预览视图 -->
  <SurfaceView android:id="@+id/preview_view"
               android:layout_width="fill_parent"
               android:layout_height="fill_parent"/>
  
  <!-- 自定义扫码框视图 -->
  <com.google.zxing.client.android.ViewfinderView
      android:id="@+id/viewfinder_view"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"/>
  
  <!-- 结果展示视图 -->
  <LinearLayout android:id="@+id/result_view"
                android:orientation="vertical"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:visibility="gone">
    <!-- 结果展示内容 -->
  </LinearLayout>
</merge>

布局中包含三个主要部分:相机预览(SurfaceView)、扫码框(ViewfinderView)和结果展示区域(LinearLayout)。

自定义扫码框绘制

ZXing通过ViewfinderView实现了扫码框的绘制,包括扫描线动画和条码定位点。

扫码框视图实现

ViewfinderView是一个自定义View,负责绘制扫码区域、扫描线和结果点:

@Override
public void onDraw(Canvas canvas) {
  if (cameraManager == null) {
    return; // not ready yet
  }
  Rect frame = cameraManager.getFramingRect();
  Rect previewFrame = cameraManager.getFramingRectInPreview();
  if (frame == null || previewFrame == null) {
    return;
  }
  // 绘制扫码框...
  // 绘制扫描线...
  // 绘制结果点...
}

扫码框的实际效果如图所示:

扫码界面预览

扫码区域计算

CameraManager中的getFramingRect方法计算扫码框的位置和大小:

public synchronized Rect getFramingRect() {
  if (framingRect == null) {
    if (camera == null) {
      return null;
    }
    Point screenResolution = configManager.getScreenResolution();
    if (screenResolution == null) {
      return null;
    }
    
    int width = findDesiredDimensionInRange(screenResolution.x, MIN_FRAME_WIDTH, MAX_FRAME_WIDTH);
    int height = findDesiredDimensionInRange(screenResolution.y, MIN_FRAME_HEIGHT, MAX_FRAME_HEIGHT);
    
    int leftOffset = (screenResolution.x - width) / 2;
    int topOffset = (screenResolution.y - height) / 2;
    framingRect = new Rect(leftOffset, topOffset, leftOffset + width, topOffset + height);
  }
  return framingRect;
}

该方法确保扫码框在屏幕中间,大小在MIN_FRAME_WIDTH到MAX_FRAME_WIDTH之间。

预览帧处理与条码解码

ZXing通过Camera.PreviewCallback获取相机预览帧数据,经过处理后进行条码解码。

预览帧数据获取

在CaptureActivity中,通过Handler周期性获取预览帧:

private void restartPreviewAfterDelay(long delayMS) {
  if (handler != null) {
    handler.sendEmptyMessageDelayed(R.id.restart_preview, delayMS);
  }
}

public void handleDecode(Result rawResult, Bitmap barcode, float scaleFactor) {
  inactivityTimer.onActivity();
  lastResult = rawResult;
  ResultHandler resultHandler = ResultHandlerFactory.makeResultHandler(this, rawResult);
  // 处理解码结果...
}

条码解码流程

DecodeHandler负责在后台线程中处理预览帧数据:

public void handleMessage(Message message) {
  switch (message.what) {
    case R.id.decode:
      decode((byte[]) message.obj, message.arg1, message.arg2);
      break;
    case R.id.quit:
      Looper.myLooper().quit();
      break;
  }
}

private void decode(byte[] data, int width, int height) {
  // 处理预览帧数据...
  Result rawResult = multiFormatReader.decodeWithState(source);
  // 发送解码结果...
}

解码结果处理与用户反馈

条码解码成功后,ZXing会通过震动、声音提示用户,并展示解码结果。

结果处理逻辑

CaptureActivity中的handleDecode方法处理解码结果:

public void handleDecode(Result rawResult, Bitmap barcode, float scaleFactor) {
  inactivityTimer.onActivity();
  lastResult = rawResult;
  ResultHandler resultHandler = ResultHandlerFactory.makeResultHandler(this, rawResult);
  
  boolean fromLiveScan = barcode != null;
  if (fromLiveScan) {
    historyManager.addHistoryItem(rawResult, resultHandler);
    // 播放提示音和震动
    beepManager.playBeepSoundAndVibrate();
    drawResultPoints(barcode, scaleFactor, rawResult);
  }
  
  // 根据不同来源处理结果...
}

结果展示界面

解码成功后,会显示结果展示界面,包含条码图片、格式、内容等信息:

扫码结果展示

结果展示布局在capture.xml的result_view中定义,包含条码图片、格式、类型、时间等信息。

高级功能:闪光灯与自动对焦

ZXing提供了闪光灯控制和自动对焦功能,提升在不同环境下的扫码体验。

闪光灯控制

CameraManager中的setTorch方法控制闪光灯开关:

public synchronized void setTorch(boolean newSetting) {
  OpenCamera theCamera = camera;
  if (theCamera != null && newSetting != configManager.getTorchState(theCamera.getCamera())) {
    // 保存自动对焦状态
    boolean wasAutoFocusManager = autoFocusManager != null;
    if (wasAutoFocusManager) {
      autoFocusManager.stop();
      autoFocusManager = null;
    }
    // 设置闪光灯状态
    configManager.setTorch(theCamera.getCamera(), newSetting);
    // 恢复自动对焦
    if (wasAutoFocusManager) {
      autoFocusManager = new AutoFocusManager(context, theCamera.getCamera());
      autoFocusManager.start();
    }
  }
}

自动对焦管理

AutoFocusManager类处理自动对焦逻辑:

public void start() {
  if (started) {
    return;
  }
  Camera.Parameters parameters = camera.getParameters();
  if (parameters != null) {
    String currentFocusMode = parameters.getFocusMode();
    if (FOCUS_MODES_CALLING_AF.contains(currentFocusMode)) {
      // 已经是自动对焦模式
      started = true;
      camera.autoFocus(this);
    }
  }
}

总结与最佳实践

通过ZXing库,我们可以快速实现稳定高效的条码扫描功能。以下是一些最佳实践:

  1. 权限处理:在Android 6.0+设备上,需要动态申请相机权限
  2. 扫码框优化:根据实际需求调整扫码框大小,平衡识别率和用户体验
  3. 性能优化:在低配置设备上降低预览分辨率,提高解码速度
  4. 错误处理:添加扫码超时、相机不可用等异常情况的处理
  5. 用户引导:提供清晰的扫码引导,帮助用户正确对准条码

ZXing的完整实现可参考android/src/com/google/zxing/client/android/CaptureActivity.java,包含了从相机初始化到结果处理的完整流程。

通过本文的介绍,相信你已经掌握了ZXing与Android Camera集成的核心技术,能够在自己的项目中实现专业的条码扫描功能。如有更多需求,可以深入研究ZXing的源码,定制更符合业务需求的扫码解决方案。

如果觉得本文对你有帮助,欢迎点赞收藏,关注作者获取更多Android开发实战教程!

【免费下载链接】zxing ZXing ("Zebra Crossing") barcode scanning library for Java, Android 【免费下载链接】zxing 项目地址: https://gitcode.com/gh_mirrors/zx/zxing

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值