2021SC@SDUSC Zxing开源代码(十六)android-integration 代码分析


前言

在前面的博客中,我们已经将 Zxing开源代码中 android包的代码都进行了分析。综合来看,整个 android包实际上就是一个安卓应用“条码扫描器”,其调用 core包中的核心扫码编码算法,来提供相应功能。不过 Zxing除了可以直接使用其提供的应用外,还可以把它集成在自己的 Android项目中,来实现扫码解码等一系列功能。这所依赖的就是 android-integration包中的代码


IntentIntegrator 代码分析

IntentIntegrator是一个实用类,通过 Intent与 android包对应的应用“条码扫描器”集成,可以简单的调用扫码编码功能并接收结果,无需修改或学习项目的源代码

扫码功能集成方法如下:
1、 在自己的项目中,创建 IntentIntegrator对象,调用 initiateScan() 方法
2、如果用户还未下载应用程序“条码扫描器”,initiateScan() 方法会返回一个 AlertDialog 对象,来提示用户下载
3、在自己项目的 Activity中,需要有方法 onActivityResult(int, int, Intent)来处理扫描后返回的结果

public void onActivityResult(int requestCode, int resultCode, Intent intent) {
	IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
	if (scanResult != null) {
		// handle scan result
	}
	// else continue with any other code you need in the method
	 ...
}

initiateScan

如果外部程序希望利用 Zxing 实现扫码功能,则首先需要调用这一方法,传入参数为:

参数含义
desiredBarcodeFormats将要扫描的条码格式
cameraId要调用哪一个摄像头(前置/后置)

方法代码如下:

  public final AlertDialog initiateScan(Collection<String> desiredBarcodeFormats, int cameraId) {
    // BS_PACKAGE = "com.google.zxing.client.android"
    // 为 Intent 设置action:SCAN
    Intent intentScan = new Intent(BS_PACKAGE + ".SCAN");
    intentScan.addCategory(Intent.CATEGORY_DEFAULT);

    // 判断要扫描的何种类型的条码
    if (desiredBarcodeFormats != null) {
      // 设置希望的码制类型
      StringBuilder joinedByComma = new StringBuilder();
      for (String format : desiredBarcodeFormats) {
        if (joinedByComma.length() > 0) {
          joinedByComma.append(',');
        }
        joinedByComma.append(format);
      }
      intentScan.putExtra("SCAN_FORMATS", joinedByComma.toString());
    }

    // 设置需要的 caremaId
    if (cameraId >= 0) {
      intentScan.putExtra("SCAN_CAMERA_ID", cameraId);
    
    // 在已安装的程序中寻找,是否有“条码扫描器”
    String targetAppPackage = findTargetAppPackage(intentScan);
    // 没找到的话就要显示弹窗,提示安装
    if (targetAppPackage == null) {
      return showDownloadDialog();
    }
    // 为 intent 设定包名
    intentScan.setPackage(targetAppPackage);
    intentScan.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    intentScan.addFlags(FLAG_NEW_DOC);
    attachMoreExtras(intentScan);
    // 跳转到intentScan中的Activity(这里应是CaptureActivity 的实例对象)进行扫码处理
    startActivityForResult(intentScan, REQUEST_CODE);
    return null;
    }

方法中首先设置了 Intent 需要携带的信息(如扫描码制、cameraId)等,而后通过方法 findTargetAppPackage 找到目标app的包名,最终通过 startActivityForResult 跳转到了相应 app的 Activity中进行具体的扫码操作

findTargetAppPackage

findTargetAppPackage 方法代码实现如下:

  private String findTargetAppPackage(Intent intent) {
    // 获得一个PackageManger(管理所有应用程序包的类)的对象
    PackageManager pm = activity.getPackageManager();
    // 根据 intent 对所有的安装程序进行匹配查询,找到满足条件的app
    List<ResolveInfo> availableApps = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
    if (availableApps != null) {
      // 判断满足条件的app是否在事先定义好的目标app列表中
      for (String targetApp : targetApplications) {
        if (contains(availableApps, targetApp)) {
          return targetApp;
        }
      }
    }
    return null;
  }

PackageManager的介绍:通过PackageManager,我们可以获取应用程序信息,这些信息来自AndroidManifest.XML。PackageManager除了负责Android系统中Package的安装、升级、卸载外,还有一项很重要的职责,就是对外提供统一的信息查询功能,其中包括查询系统中匹配某Intent的Activities、BroadCastReceivers或Services等

showDownloadDialog()

若发现在已安装的应用程序中没有目标app, 则调用了 showDownloadDialog() 方法,来显示弹窗提示下载app

  private AlertDialog showDownloadDialog() {
    // 创建AlertDialog实例对象
    AlertDialog.Builder downloadDialog = new AlertDialog.Builder(activity);
    // 为弹窗设置标题
    downloadDialog.setTitle(title);
    // 为弹窗设置显示内容
    downloadDialog.setMessage(message);
    // 为点击“Yes”按钮设置监听
    downloadDialog.setPositiveButton(buttonYes, new DialogInterface.OnClickListener() {
      @Override
      public void onClick(DialogInterface dialogInterface, int i) {
        String packageName;
        if (targetApplications.contains(BS_PACKAGE)) {
          // 如果目标app列表中存在BS_PACKAGE(也就是Zxing的安卓端应用),那么设置要安装的包名为BS_PACKAGE
          packageName = BS_PACKAGE;
        } else {
          // 否则选择目标app列表的第一个
          packageName = targetApplications.get(0);
        }
        //  跳转到应用商场
        Uri uri = Uri.parse("market://details?id=" + packageName);
        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
        try {
          if (fragment == null) {
            activity.startActivity(intent);
          } else {
            fragment.startActivity(intent);
          }
        } catch (ActivityNotFoundException anfe) {
          // Hmm, market is not installed
          Log.w(TAG, "Google Play is not installed; cannot install " + packageName);
        }
      }
    });
    downloadDialog.setNegativeButton(buttonNo, null);
    downloadDialog.setCancelable(true);
    return downloadDialog.show();
  }

shareText

除了可以通过 IntentIntegrator 集成扫码操作,也可以利用 Zxing的编码功能,将给定文本编码为条形码来共享,以便其他用户可以扫描

  public final AlertDialog shareText(CharSequence text, CharSequence type) {
    Intent intent = new Intent();
    intent.addCategory(Intent.CATEGORY_DEFAULT);
    // Intent的action为ENCODE
    intent.setAction(BS_PACKAGE + ".ENCODE");
    intent.putExtra("ENCODE_TYPE", type);
    intent.putExtra("ENCODE_DATA", text);
    // 找到目标app 包名
    String targetAppPackage = findTargetAppPackage(intent);
    // 如果没有找到则弹窗提示下载
    if (targetAppPackage == null) {
      return showDownloadDialog();
    }
    intent.setPackage(targetAppPackage);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    intent.addFlags(FLAG_NEW_DOC);
    attachMoreExtras(intent);
    // 跳转到对应app的Activity中处理
    if (fragment == null) {
      activity.startActivity(intent);
    } else {
      fragment.startActivity(intent);
    }
    return null;
  }

其基本流程与扫码类似,只是 Intent 中 Action 设置不同,这样跳转到“条码扫描器”的 Activity后就可以执行编码功能


总结

到这里,整个 Zxing开源代码中与 Android相关的部分就分析完毕了。从一开始面对近八十个类感觉无从下手,到后面从主线——扫码功能出发,一步步对功能逐个进行分析,最后已经基本完全理清 Zxing项目 Android部分的代码逻辑了。

与此同时,也学习了解了 Android的基本组件、Handler消息传递机制、View体系、Adapter机制等等 Android相关的重要知识。

对比以往自己开发的课设项目,整个 Zxing项目的安卓端应用体量庞大,功能处理逻辑完善,并且考虑了各种各样的情况,包括多种解析格式、长时间无活动自动销毁机制等。这也是我第一次阅读大型项目的源码,其中的开发思想、处理逻辑等都对我今后进行软件工程项目实践有很大启发

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
最近2013-11-29(Nov 29, 2013)更新的Android ZXing 2.3.0 release源码及编译后的core-2.3.0.jar和android-integration-2.3.0.jar打包亲测可用,如大家有兴趣自己编译的话请参考下面的教程。 下面我写的教程修改自sonikk的csdn博客http://blog.csdn.net/sonikk/article/details/9228481在此向博主sonikk表示敬意! 下载后解压缩ZXing-2.3.0 目录当中我们用的文件夹有: android ——这是一个Android的示例工程 android-integration ——这是使用QR码工程需要引用的一个源码 androidtest ——这是一个Android的简单测试工程,好像是需要先安装android目录中的应用才能运行 core ——这是核心代码 其它文件夹都用不到的。。。 第一步: 下面将android目录下的工程带入Eclipse 包名:com.google.zxing.client.android 默认工程名:CaptureActivity 第二步: 导入引用代码: 右键工程名 -> Properties -> Java Build Path -> Source -> Link Source... -> 用browse..按钮 选择ZXing-2.3.0\core\src\main\java这个绝对路径,起名core 选择ZXing-2.3.0\android-integration\src\main\java这个绝对路径,起名android-integration (名称需要手动修改,可以起不一样的名字,但是我个人感觉这样命名比较合理) 第三步: 清除android-integration路径下的IntentIntegratorSupportV4.java文件的报错: 我把android的Project Build Target改成了4.0.3(API-15)并在其他的项目的libs中复制了一个android-support-v4.jar到CaptureActivity新建的libs文件夹下。(eclipse没有其他项目的话手动建一个就有了,Android是在Android 3.0 (API level 11)始引入Fragment的,3.0以上始起为了兼容3.0以下的需要加入这个jar)。 第四步: 右键分别点击core目录和android-integration目录,选择Export.. 打Java目录,选中JAR file 勾选 Export generated class files and resources Export Java source files and resources 勾选Options: Compress the contents of the JAR file 单击Browse...导出选择的目录,起名: core-2.3.0.jar android-integration-2.3.0.jar 大功告成!这样需要的jar文件就生成好了。 zxing主页 https://code.google.com/p/zxing/ 源码下载: https://code.google.com/p/zxing/downloads/list Eclipse生成jar的一般方法,请参考: http://www.cnblogs.com/lan0725/archive/2008/08/28/1873947.html 下一步,如何精简代码?请参考这篇文章: http://www.cnblogs.com/keyindex/archive/2011/06/08/2074900.html 接着,如何将横屏更改为竖屏?请参考这篇文章: http://blog.csdn.net/duqiuke/article/details/8289921 扫描时如何打闪光灯?请参考: http://www.cnblogs.com/lee0oo0/archive/2012/04/05/2433815.html 希望对大家有所帮助,有问题请加我QQ472950043,android发大家一起进步!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值