Android二维码之zxing

一、下载源码

地址:https://github.com/zxing/zxing 下载master分支
地址:https://github.com/zxing/zxing/releases 下载,release下有历史版本

其目录结构如下:
这里写图片描述


其中:

  1. core文件夹下为核心代码,解析码,生成码等实现都在此
  2. android-core文件夹下就一个文件,关于camera的设置。core与android core是项目的核心目录以及android开发需要的核心,基本上需要二次开发的话需要引用这两个目录
  3. android是一个叫做“条码扫描器”(Barcode Scanner)的程序,是官方利用core与android core实现的一个扫码程序
  4. android-integration提供了一种简单的让你在你的app中调用Barcode Scanner(简称BS)的实现,用它的话有一个弊端,需要在手机上同时安装你的app和BS,扫码是你的app会调用BS这个app,
  5. androidtest就是一个利用android-integration调用BS的例子。

与android开发相关的基本上就这5个目录,在实际开发中,考虑到integration的弊端,我们舍弃这种方式,而是将ZXing整合到我们的项目中去,而考虑到引入core与android core来进行二次开发的周期比较长,决定直接在项目用引用Barcode Scanner。

二、获取jar包

获取jar包有两种方式,一种下载已经编译好的,二是自己编译。

2.1 下载已编译的jar包

地址:http://repo1.maven.org/maven2/com/google/zxing/
地址:http://central.maven.org/maven2/com/google/zxing/
两个地址都可以下载
在Android studio中也可以这样引用

compile ‘com.google.zxing:core:3.3.0’
compile ‘com.google.zxing:android-core:3.3.0’


备注:同时引用jcenter和mavenCentral在project下的build.gradle中如下修改:

原始的配置:

这里写图片描述


修改成

allprojects {
    repositories {
        jcenter()
        mavenCentral()
    }
}

2.2 自己编译

1、 参考https://github.com/zxing/zxing/wiki/Getting-Started-Developing 进行编译。


摘要:

The Android SDK must be installed of course. Run the tool called android and ensure that platform support for the Android releases targeted by the Andrdoid app(s) you’re interested in are installed. At the time of this writing, for the Barcode Scanner app in android/, that’s platform level 22 / Android 5.1.

export ANDROID_HOME=/change/this/path/to/android-sdk


From the root of the project, run mvn install to compile, test and assemble all modules. Add -DskipTests to skip unit tests. Note that Android-related modules and apps will not be built unless ANDROID_HOME is set.


简单点讲就是:

  • 第一步设置Android SDK的路径,
  • 第二步在下载的zxing源码根目录下输入mvn install进行编译

2、关于maven安装(mvn)

请参考这篇博文:http://blog.csdn.net/liuqz2009/article/details/70853239

三、使用介绍

二维码,我们也称作QRCode,QR表示quick response即快速响应,在很多App中我们都能见到二维码的身影,最常见的莫过于微信了。那么今天我们就来看看怎么样在我们自己的App中集成二维码的扫描与生成功能。OK,废话不多说,我们就开始做吧。

二维码的使用我主要想分为两部分来给大家介绍,一部分就是二维码的生成,这里的知识点都很简单,还有一部分是二维码的识别,这里稍微麻烦一些,不过细心来做其实也很简单。二维码的开发使用我们大多都是使用Google提供的zxing这个类库,使用这个类库我们需要先下载核心jar包,下载地址,如果我们只想生成二维码那么这个就够了,但是如果我们还想做二维码的识别,那么我们需要在刚才的基础上继续添加GitHub上的开源项目,这个我们在后面再说。

3.1 二维码的生成

先来看一张效果图:

这里写图片描述

1、 准备工作

如果我们只做二维码的生成,那么只需要添加核心jar包即可,如下:
这里写图片描述


2、 二维码生成

OK,添加完jar包之后我们就可以开始写二维码生成代码了,二维码本身就是一张Bitmap图片,所以我们这里主要就是看怎么样来生成这张图片,我在主界面添加一个按钮和一个ImageView,当点击按钮时生成一张二维码图片显示在ImageView上。布局如下:

    <?xml version="1.0" encoding="utf-8"?>  
    <RelativeLayout  
        xmlns:android="http://schemas.android.com/apk/res/android"  
        xmlns:tools="http://schemas.android.com/tools"  
        android:layout_width="match_parent"  
        android:layout_height="match_parent"  
        tools:context="org.mobiletrain.qrwriter.MainActivity">  

        <Button  
            android:layout_width="wrap_content"  
            android:layout_height="wrap_content"  
            android:onClick="generate"  
            android:text="生成二维码"/>  

        <ImageView  
            android:id="@+id/iv"  
            android:layout_width="256dp"  
            android:layout_height="256dp"  
            android:layout_centerInParent="true"/>  
    </RelativeLayout>  

当我点击按钮时生成二维码图片,那我们就来看看生成二维码图片的核心代码:

    private Bitmap generateBitmap(String content,int width, int height) {  
        QRCodeWriter qrCodeWriter = new QRCodeWriter();  
        Map<EncodeHintType, String> hints = new HashMap<>();  
        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");  
        try {  
            BitMatrix encode = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, width, height, hints);  
            int[] pixels = new int[width * height];  
            for (int i = 0; i < height; i++) {  
                for (int j = 0; j < width; j++) {  
                    if (encode.get(j, i)) {  
                        pixels[i * width + j] = 0x00000000;  
                    } else {  
                        pixels[i * width + j] = 0xffffffff;  
                    }  
                }  
            }  
            return Bitmap.createBitmap(pixels, 0, width, width, height, Bitmap.Config.RGB_565);  
        } catch (WriterException e) {  
            e.printStackTrace();  
        }  
        return null;  
    }  

首先这个方法接收三个参数,这三个参数分别表示生成二维码的文本内容(你要把哪一个文本用二维码图片表示出来),第二个和第三个参数分别表示生成的二维码图片的宽和高。在这里,我们首先要获得一个QRCodeWriter实例,该实例中有一个方法叫做encode,通过该方法对文本内容进行编码,该方法共有五个参数,第一个参数表示生成二维码的文本内容,第二个参数表示编码格式,第三个参数表示生成的二维码的宽度,第四个参数表示生成的二维码的高度,第五个参数可选,可以用来设置文本的编码,encode方法的返回值是一个BitMatrix,你可以把BitMatrix理解成一个二维数组,这个二维数组的每一个元素都表示一个像素点是否有数据。OK,接下来我们需要定义一个int数组用来存放Bitmap中所有像素点的颜色,可是我们又怎么知道每一个像素点是什么颜色呢?这个时候就需要我们遍历BitMatrix了,如果BitMatrix上的点表示 该点有数据,那么对应在Bitmap上的像素点就是黑色,否则就是白色。BitMatrix中的get方法的返回值为一个boolean类型,true表示该点有数据,false表示该点没有数据。通过两个嵌套的for循环将BitMatrix遍历一遍,然后给pixels数组都赋上值,OK,pixels数组有值之后,接下来调用Bitmap的createBitmap方法创建一个Bitmap出来就可以了,createBitmap方法共接收6个参数,第一个参数表示Bitmap中所有像素点的颜色,第二个参数表示像素点的偏移量,第三个参数表示Bitmap每行有多少个像素点,第四个参数表示生成的Bitmap的宽度,第五个参数表示生成的Bitmap的高度,第六个参数表示生成的Bitmap的色彩模式,因为二维码只有黑白两种颜色,所以我们可以不用考虑透明度,直接使用RGB_565即可。OK,这样的话我们就获取到了二维码的图片了,最后我们再来看看点击事件:

    public void generate(View view) {  
        Bitmap qrBitmap = generateBitmap("http://www.csdn.net",400, 400);  
        iv.setImageBitmap(qrBitmap);  
    }  

效果图如下:
这里写图片描述

OK,如果你没有特殊的需求那么这样就OK了,但是我们见到的大多数二维码的正中心都有一个Logo,那么这个效果要怎么实现呢?这里就是图片绘制的内容了,我封装了一个方法专门来解决这个问题,代码如下:

    private Bitmap addLogo(Bitmap qrBitmap, Bitmap logoBitmap) {  
        int qrBitmapWidth = qrBitmap.getWidth();  
        int qrBitmapHeight = qrBitmap.getHeight();  
        int logoBitmapWidth = logoBitmap.getWidth();  
        int logoBitmapHeight = logoBitmap.getHeight();  
        Bitmap blankBitmap = Bitmap.createBitmap(qrBitmapWidth, qrBitmapHeight, Bitmap.Config.ARGB_8888);  
        Canvas canvas = new Canvas(blankBitmap);  
        canvas.drawBitmap(qrBitmap, 0, 0, null);  
        canvas.save(Canvas.ALL_SAVE_FLAG);  
        float scaleSize = 1.0f;  
        while ((logoBitmapWidth / scaleSize) > (qrBitmapWidth / 5) || (logoBitmapHeight / scaleSize) > (qrBitmapHeight / 5)) {  
            scaleSize *= 2;  
        }  
        float sx = 1.0f / scaleSize;  
        canvas.scale(sx, sx, qrBitmapWidth / 2, qrBitmapHeight / 2);  
        canvas.drawBitmap(logoBitmap, (qrBitmapWidth - logoBitmapWidth) / 2, (qrBitmapHeight - logoBitmapHeight) / 2, null);  
        canvas.restore();  
        return blankBitmap;  
    }  

addLogo这个方法接收两个参数,第一个参数就是我们在1.2节中生成的二维码的Bitmap图片,第二个参数就是我们的logo图片,在该方法中我先获取到两张Bitmap各自的宽高,然后创建一个新的空白的Bitmap,这个新的空白的Bitmap的宽高和二维码的宽高一致,然后创建一个Canvas对象,创建Canvas对象的时候将blankBitmap传入,这样我一会绘制的东西相当于都是绘制在了blankBitmap上了。canvas的drawBitmap方法接收四个参数,第一个是你要绘制的Bitmap对象,第二个和第三个是你要绘制的Bitmap的左上角的坐标,第四个参数是一个画笔,一般情况下我们给一个null就可以了,如果你要设置重复模式等等效果的时候可以不给null。我们使用drawBitmap方法先将原本的二维码图片绘制出来,绘制完成之后,调用canvas的save方法,将当前的绘制状态保存下来,然后对画布进行缩放,缩小画布之后我们来绘制Logo,一帮情况下logo的宽高为二维码原图宽高的1/5(中心logo图片不宜过大,否则会影响到二维码的识别),所以我们先通过一个while循环获得缩放比例,然后调用canvas的scale方法对画布进行缩放,前两个参数表示宽高的缩放比例,大于1表示放大,小于1表示缩小,后两个参数表示缩放的中心点。缩放完成之后我们就可以绘制logo了,logo绘制完成之后,调用canvas的restore方法将画布恢复为原来的状态,最后将blankBitmap返回。在点击事件中调用这个方法即可,代码如下:

    public void generate(View view) {  
        Bitmap qrBitmap = generateBitmap("http://www.csdn.net",400, 400);  
        Bitmap logoBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);  
        Bitmap bitmap = addLogo(qrBitmap, logoBitmap);  
        iv.setImageBitmap(bitmap);  
    }  

效果图如下:
这里写图片描述
OK,至此,我们的二维码生成就说完了,就是这么简单。

3.2 二维码的识别

二维码的识别是一个稍微麻烦的事情,一般情况下,我们直接使用GitHub上的开源项目zxing即可,这个项目就是在我们之前的那个核心包的基础上完成的(下载地址)。当然,如果你需要自己定义相关的页面等等也都可以,这个我们到后面再说。这里我们先来看看怎么把GitHub上的开源项目引入到我们的项目中来。

导入工程我们主要分为如下几个步骤:

  1. 创建一个新的Project,命名为QRReader(这一步不是必须的,可以根据你的项目需求来)

  2. 下载ZXing项目

  3. android studio中导入 android整个项目,import module。在新的Project中创建一个新的Module,在创建的过程中选择Android Library,如下图:
    这里写图片描述
    这里写图片描述

  4. build中要注意的地方

    apply plugin: ‘com.android.library’
    compile ‘com.google.zxing:core:3.2.1’
    compile ‘com.google.zxing:android-core:3.2.1’

如下图:
这里写图片描述
5. 在我们的项目中引用这个module,然后对项目进行编译。
6. 编译之后项目会报错,这个时候需要我们将library中所有的switch语句改为if…else if …else if的形式。
7. 完成第6步之后还是会报错,这个时候需要我们将library的清单文件中Application节点的icon属性删除,再编译就没有任何问题了。

OK,经过上面7个步骤这个开源项目就被我们成功的引入到我们自己的项目中了,在这个开源项目中有一个CaptureActivity,这个Activity专门用来扫描二维码,所以我们只需要在自己的项目中直接来启动这个Activity就可以了,另外,由于默认情况下CaptureActivity是启动项,所以我们要在library的清单文件中删除CaptureActivity作为启动项的配置。

OK,现在我的项目中有一个按钮,点击这个按钮我就可以扫描二维码,代码如下:

    public void go(View view) {  
        startActivity(new Intent(this, CaptureActivity.class));  
    }  

OK,至此,一个简陋的二维码扫描就完成了,大家有木有觉得很麻烦啊?麻烦也就这一次,因为我把ZXing当作library使用的时候系统会自动生成一个aar包,有了这个aar包,以后的开发就会变得非常简单了,那么这个aar包在哪里呢?如下图:
这里写图片描述
对应的文件夹路径大家自己去找,有了这个aar包之后,如果我再需要使用二维码扫描功能的时候就只需要如下几个简单的步骤:

  1. 创建项目

  2. 创建Module,在创建Module时选择Import .JAR/.AAR Package,然后选择刚刚的aar包

  3. 在我的app中引用这个Module即可。

3.3 扫码方向调整

1、版本在3.2.1左右就可以不用改摄像头方向了。只用改下activity的竖屏属性。

这里写图片描述

2、handleDecode(Result rawResult, Bitmap barcode, float scaleFactor)

这里写图片描述

3、handleDecodeInternally(Result rawResult, ResultHandler resultHandler, Bitmap barcode)

这个方法中

//    statusView.setVisibility(View.GONE);
//    viewfinderView.setVisibility(View.GONE);
//    resultView.setVisibility(View.VISIBLE);    
/*********** 自己的修改 S ************************/ 
   resultView.setVisibility(View.GONE);    
   /*********** 自己的修改 E ************************/

这里写图片描述
这个地方主要是隐藏 扫描完弹出了显示结果。和我们用不到的功能按钮。
用喜欢删除多余方法的,可以自己慢慢删除多余的部分。(到以上步骤,基本就整合完成了。)

最后,我将我自己生成的aar包提供给大家,可以直接在项目中使用,非常方便,不过建议还是大家自己尝试生成一个aar包,整个过程还是非常有意思。

zxinglibrary-release.aar下载

以上。
备注:如果直接引入了android-core.jar则无需做合并的动作。

参考:
1、https://github.com/zxing/zxing/wiki/Getting-Started-Developing
2、http://blog.sina.com.cn/s/blog_76adb0160102uxqb.html
3、http://www.cnblogs.com/jojinshallar/articles/3723818.html
4、http://blog.csdn.net/ollins136/article/details/21538907
5、http://blog.csdn.net/u012702547/article/details/51501350
6、http://www.cnblogs.com/ksmile/p/4778055.html
7、https://segmentfault.com/q/1010000004298469
8、http://jingyan.baidu.com/article/c843ea0ba83d0677921e4a52.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值