ZXing源码解析二:掌握解码步骤1

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: ZXing源码解析二:掌握解码步骤

前言:上篇文章已经让源码运行起来了,但是还存在很多与扫描二维码无关的代码,本篇将删除无用的代码只保留与扫码有关的代码,同时分析解码的步骤。

精简代码

  本篇文章的目标是分析出解码的步骤,为了不被无关的代码干扰,将会对源码进行精简,只保留与解码有关的代码。

  主要删减的代码就是识别出二维码的内容后,一些其他的操作,如分享,记录扫描的历史,搜索解析结果等。删除之后的android模块的结构如下

当然,这不是最终删减的版本,可能在分析源码的时候,发现无用的代码,会继续删除,最终的代码,我会在文末给出Github链接。

源码分析

  为了方便理解及记忆ZXing解码的步骤,我会边分析边画UML的序列图,最后,分析完解码的步骤,会有一个完整的序列图。现在,从主程序的入口开始分析,就是CaptureActivityonCreate方法。

onCreate源码分析

代码如下

public void onCreate(Bundle icicle) {
    super.onCreate(icicle);
    //扫码的时候屏幕长亮
    Window window = getWindow();
    window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    setContentView(R.layout.capture);
    hasSurface = false;
    //控制activity在一段时间无操作自动finish
    inactivityTimer = new InactivityTimer(this);
    //管理扫码后是否有声音和震动
    beepManager = new BeepManager(this);
    //用来根据环境的明暗,自动开启关闭闪光灯
    ambientLightManager = new AmbientLightManager(this);
    //加载一些默认的配置
    PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
  }

这个方法,主要是用来实例化一些对象和获取配置信息,上面的代码中已经有注释,就不再细说。

onResume源码分析

下面继续看Activity生命周期的第二个方法,代码如下

  protected void onResume() {
    super.onResume();
    // CameraManager must be initialized here, not in onCreate(). This is necessary because we don't
    // want to open the camera driver and measure the screen size if we're going to show the help on
    // first launch. That led to bugs where the scanning rectangle was the wrong size and partially
    // off screen.
    cameraManager = new CameraManager(getApplication());//1
    viewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view);
    viewfinderView.setCameraManager(cameraManager);
    resultView = findViewById(R.id.result_view);
    statusView = (TextView) findViewById(R.id.status_view);
    handler = null;
    //省略不重要代码
    //.....
    SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view);
    SurfaceHolder surfaceHolder = surfaceView.getHolder();//2
    if (hasSurface) {
      // The activity was paused but not stopped, so the surface still exists. Therefore
      // surfaceCreated() won't be called, so init the camera here.
      initCamera(surfaceHolder);
    } else {
      // Install the callback and wait for surfaceCreated() to init the camera.
      surfaceHolder.addCallback(this);//3
    }
  }

上面代码中的一些语句标记了序号,现在来看序号“1”处的代码都做了什么,进入CameraManager类的构造方法中,代码如下

public CameraManager(Context context) {
    this.context = context;
    this.configManager = new CameraConfigurationManager(context);//1.1
    previewCallback = new PreviewCallback(configManager);//1.2
  }

继续跟进代码,看下“1.1”处的代码,CameraConfigurationManager构造方法中做了什么,代码如下

CameraConfigurationManager(Context context) {
    this.context = context;
  }

上面的代码就是注入了context。现在看“1.2”处的代码,PreviewCallback构造方法中做了什么,代码如下

PreviewCallback(CameraConfigurationManager configManager) {
    this.configManager = configManager;
  }

上面的这段代码可以看出,在PreviewCallback构造方法中,将CameraConfigurationManager类的实例,注入到了PreviewCallback类中。跟完了“1”处的代码,继续往下看onResume方法中的代码,这里介绍一下“2”处的代码,SurfaceHolder的作用,介绍如下

SurfaceHolder是一个接口,其作用就像一个Surface的监听器。提供访问和控制SurfaceView背后的Surface 相关的方法 (providingaccess and control over this SurfaceView's underlying surface),它通过三个回调方法,让我们可以感知到Surface的创建、销毁或者改变。

继续往下看代码,因为在onCreate方法中,hasSurface值为false,所以,会进入else语句,也就是“3”处的代码,这句代码的作用就是绑定Surface的监听器,就是在当前的Activity中绑定Surface生命周期的回调方法。SurfaceHolder.Callback 中定义了三个接口方法:

public void surfaceChanged(SurfaceHolder holder, int format, int width, int height);
  • 当surface发生任何结构性的变化时(格式或者大小),该方法就会被立即调用。
public void surfaceCreated(SurfaceHolder holder);
  • 当surface对象创建后,该方法就会被立即调用。
public void surfaceDestroyed(SurfaceHolder holder);
  • 当surface对象在将要销毁前,该方法会被立即调用。

知道了这三个方法在什么时候会调用,所以,这里绑定回调之后,会首先调用surfaceCreated这个回调方法,看下这个方法中的代码,如下

public void surfaceCreated(SurfaceHolder holder) {
    if (holder == null) {
      Log.e(TAG, "*** WARNING *** surfaceCreated() gave us a null surface!");
    }
    if (!hasSurface) {
      hasSurface = true;
      initCamera(holder);
    }
  }

继续跟进代码,看下initCamera(holder);方法都做了什么,代码如下

private void initCamera(SurfaceHolder surfaceHolder) {
    if (surfaceHolder == null) {
      throw new IllegalStateException("No SurfaceHolder provided");
    }
    //相机已经打开
    if (cameraManager.isOpen()) {
      Log.w(TAG, "initCamera() while already open -- late SurfaceView callback?");
      return;
    }
    try {
    //打开相机并初始化硬件参数
      cameraManager.openDriver(surfaceHolder);
      // 实例化一个handler并开始预览.
      if (handler == null) {
        //3.1
        handler = new CaptureActivityHandler(this, decodeFormats, decodeHints, characterSet, cameraManager);
      }
      decodeOrStoreSavedBitmap(null, null);
    } catch (IOException ioe) {
      Log.w(TAG, ioe);
      displayFrameworkBugMessageAndExit();
    } catch (RuntimeException e) {
      // Barcode Scanner has seen crashes in the wild of this variety:
      // java.?lang.?RuntimeException: Fail to connect to camera service
      Log.w(TAG, "Unexpected error initializing camera", e);
      displayFrameworkBugMessageAndExit();
    }
  }

“3.1”处的代码实例化了一个CaptureActivityHandler,看下CaptureActivityHandler的构造方法,代码如下

  CaptureActivityHandler(CaptureActivity activity,
                         Collection<BarcodeFormat> decodeFormats,
                         Map<DecodeHintType,?> baseHints,
                         String characterSet,
                         CameraManager cameraManager) {
    this.activity = activity;//注入activity
    //新建一个线程并启动
    //3.1.1
    decodeThread = new DecodeThread(activity, decodeFormats, baseHints, characterSet,
        new ViewfinderResultPointCallback(activity.getViewfinderView()));
    decodeThread.start();
    state = State.SUCCESS;
    // 注入cameraManager
    this.cameraManager = cameraManager;
    //要求相机硬件开始将预览帧绘制到屏幕上
    cameraManager.startPreview();
    //开始预览,并且解码
    //3.1.2
    restartPreviewAndDecode();
  }


相关文章
|
20天前
|
前端开发 JavaScript
React 步骤条组件 Stepper 深入解析与常见问题
步骤条组件是构建多步骤表单或流程时的有力工具,帮助用户了解进度并导航。本文介绍了在React中实现简单步骤条的方法,包括基本结构、状态管理、样式处理及常见问题解决策略,如状态管理库的使用、自定义Hook的提取和CSS Modules的应用,以确保组件的健壮性和可维护性。
55 17
|
2月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
86 2
|
8天前
|
存储 设计模式 算法
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。 行为型模式分为: • 模板方法模式 • 策略模式 • 命令模式 • 职责链模式 • 状态模式 • 观察者模式 • 中介者模式 • 迭代器模式 • 访问者模式 • 备忘录模式 • 解释器模式
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
|
8天前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。 结构型模式分为以下 7 种: • 代理模式 • 适配器模式 • 装饰者模式 • 桥接模式 • 外观模式 • 组合模式 • 享元模式
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
|
8天前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
创建型模式的主要关注点是“怎样创建对象?”,它的主要特点是"将对象的创建与使用分离”。这样可以降低系统的耦合度,使用者不需要关注对象的创建细节。创建型模式分为5种:单例模式、工厂方法模式抽象工厂式、原型模式、建造者模式。
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
|
2月前
|
缓存 监控 Java
Java线程池提交任务流程底层源码与源码解析
【11月更文挑战第30天】嘿,各位技术爱好者们,今天咱们来聊聊Java线程池提交任务的底层源码与源码解析。作为一个资深的Java开发者,我相信你一定对线程池并不陌生。线程池作为并发编程中的一大利器,其重要性不言而喻。今天,我将以对话的方式,带你一步步深入线程池的奥秘,从概述到功能点,再到背景和业务点,最后到底层原理和示例,让你对线程池有一个全新的认识。
56 12
|
27天前
|
PyTorch Shell API
Ascend Extension for PyTorch的源码解析
本文介绍了Ascend对PyTorch代码的适配过程,包括源码下载、编译步骤及常见问题,详细解析了torch-npu编译后的文件结构和三种实现昇腾NPU算子调用的方式:通过torch的register方式、定义算子方式和API重定向映射方式。这对于开发者理解和使用Ascend平台上的PyTorch具有重要指导意义。
|
9天前
|
安全 搜索推荐 数据挖掘
陪玩系统源码开发流程解析,成品陪玩系统源码的优点
我们自主开发的多客陪玩系统源码,整合了市面上主流陪玩APP功能,支持二次开发。该系统适用于线上游戏陪玩、语音视频聊天、心理咨询等场景,提供用户注册管理、陪玩者资料库、预约匹配、实时通讯、支付结算、安全隐私保护、客户服务及数据分析等功能,打造综合性社交平台。随着互联网技术发展,陪玩系统正成为游戏爱好者的新宠,改变游戏体验并带来新的商业模式。
|
3月前
|
缓存 Java 程序员
Map - LinkedHashSet&Map源码解析
Map - LinkedHashSet&Map源码解析
87 0
|
3月前
|
算法 Java 容器
Map - HashSet & HashMap 源码解析
Map - HashSet & HashMap 源码解析
68 0

推荐镜像

更多