Android之二维码的生成与识别

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

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

参考:http://blog.csdn.net/itluochen/article/details/52126511

一:二维码的生成

二维码的生成有两种形式:一种是不带LOGO的二维码,一种是带LOGO的二维码,看下效果图


1.生成二维码的话首先要添加jar包:

2.二维码生成

添加完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="createerweima.itcast.zz.createerweima.MainActivity">

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

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


</RelativeLayout>
看下主代码:MainActivity.java

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private ImageView iv_erweima;
    private Button btn_create_erweima;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();
    }

    private void initView() {
        iv_erweima = (ImageView) findViewById(R.id.iv_erweima);
        btn_create_erweima = (Button) findViewById(R.id.btn_create_erweima);
        iv_erweima.setOnClickListener(this);
        btn_create_erweima.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_create_erweima:
                //生成二维码不带LOGO
//                Bitmap qrBitmap = generateBitmap("http://www.csdn.net",400, 400);
//                Bitmap qrBitmap = generateBitmap("http://www.jh1000.com/",400, 400);
//                iv_erweima.setImageBitmap(qrBitmap);

                //生成二维码并且带有中间LOGO
                Bitmap qrBitmap = generateBitmap("http://www.csdn.net", 400, 400);
                Bitmap logoBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
                Bitmap bitmap = addLogo(qrBitmap, logoBitmap);
                iv_erweima.setImageBitmap(bitmap);

                break;
        }
    }

    /**
     * 自定义生成二维码的方法
     *
     * @param content 生成二维码的文本内容(你要把哪一个文本用二维码图片表示出来)
     * @param width   第二个和第三个参数分别表示生成的二维码图片的宽和高
     * @param height
     * @return
     */
    private Bitmap generateBitmap(String content, int width, int height) {
        //获得一个QRCodeWriter实例
        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        Map<EncodeHintType, String> hints = new HashMap<>();
        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
        try {
            //实例中有一个方法叫做encode,通过该方法对文本内容进行编码
            /**
             *第一个参数表示生成二维码的文本内容,第二个参数表示编码格式
             * 第三个参数表示生成的二维码的宽度,第四个参数表示生成的二维码的高度
             *第五个参数可选,可以用来设置文本的编码,encode方法的返回值是一个BitMatrix,
             * 你可以把BitMatrix理解成一个二维数组,这个二维数组的每一个元素都表示一个像素点是否有数据。
             */
            BitMatrix encode = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, width, height, hints);
            //定义一个int数组用来存放Bitmap中所有像素点的颜色
            int[] pixels = new int[width * height];
            //遍历BitMatrix,如果BitMatrix上的点表示 该点有数据,那么对应在Bitmap上的像素点就是黑色,否则就是白色。
            for (int i = 0; i < height; i++) {
                for (int j = 0; j < width; j++) {
                    //encode.get() ,get方法的返回值为一个boolean类型,true表示该点有数据,false表示该点没有数据
                    if (encode.get(j, i)) {
                        pixels[i * width + j] = 0x00000000;//黑色
                    } else {
                        pixels[i * width + j] = 0xffffffff;//白色
                    }
                }
            }
            /**
             * 第一个参数表示Bitmap中所有像素点的颜色,第二个参数表示像素点的偏移量,
             * 第三个参数表示Bitmap每行有多少个像素点,第四个参数表示生成的Bitmap的宽度,
             * 第五个参数表示生成的Bitmap的高度,第六个参数表示生成的Bitmap的色彩模式
             */
            return Bitmap.createBitmap(pixels, 0, width, width, height, Bitmap.Config.RGB_565);
        } catch (WriterException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 自定义添加二维码中间LOGO 的方法
     *
     * @param qrBitmap   生成的二维码的Bitmap图片
     * @param logoBitmap logo图片
     * @return
     */
    private Bitmap addLogo(Bitmap qrBitmap, Bitmap logoBitmap) {
        //先获取到两张Bitmap各自的宽高
        int qrBitmapWidth = qrBitmap.getWidth();
        int qrBitmapHeight = qrBitmap.getHeight();
        int logoBitmapWidth = logoBitmap.getWidth();
        int logoBitmapHeight = logoBitmap.getHeight();
        //创建一个新的空白的Bitmap,这个新的空白的Bitmap的宽高和二维码的宽高一致
        Bitmap blankBitmap = Bitmap.createBitmap(qrBitmapWidth, qrBitmapHeight, Bitmap.Config.ARGB_8888);
        //创建一个Canvas对象(画布),创建Canvas对象的时候将blankBitmap传入,
        // 这样我一会绘制的东西相当于都是绘制在了blankBitmap上了
        Canvas canvas = new Canvas(blankBitmap);
        /**
         *drawBitmap()先将原本的二维码图片绘制出来
         * 第一个是你要绘制的Bitmap对象,
         * 第二个和第三个是你要绘制的Bitmap的左上角的坐标,
         * 第四个参数是一个画笔,一般情况下我们给一个null就可以了,如果你要设置重复模式等等效果的时候可以不给null。
         */
        canvas.drawBitmap(qrBitmap, 0, 0, null);
        //绘制出后将当前的绘制状态保存下来,然后对画布进行缩放,缩小画布之后我们来绘制Logo
        canvas.save(Canvas.ALL_SAVE_FLAG);

        //一般情况下logo的宽高为二维码原图宽高的1/5(中心logo图片不宜过大,否则会影响到二维码的识别),
        // 所以我们先通过一个while循环获得缩放比例
        float scaleSize = 1.0f;
        while ((logoBitmapWidth / scaleSize) > (qrBitmapWidth / 5) || (logoBitmapHeight / scaleSize) > (qrBitmapHeight / 5)) {
            scaleSize *= 2;
        }
        float sx = 1.0f / scaleSize;

        //然后 scale() 对画布进行缩放,前两个参数表示宽高的缩放比例,大于1表示放大,小于1表示缩小,后两个参数表示缩放的中心点
        canvas.scale(sx, sx, qrBitmapWidth / 2, qrBitmapHeight / 2);
//        canvas.scale(sx, sx, 0, 0);
        //绘制logo
        canvas.drawBitmap(logoBitmap, (qrBitmapWidth - logoBitmapWidth) / 2, (qrBitmapHeight - logoBitmapHeight) / 2, null);
        //restore方法将画布恢复为原来的状态,最后将blankBitmap返回
        canvas.restore();
        return blankBitmap;
    }
}

详细说下方法:

生成二维码不带LOGO

    /**
     * 自定义生成二维码的方法
     * @param content 生成二维码的文本内容(你要把哪一个文本用二维码图片表示出来)
     * @param width   第二个和第三个参数分别表示生成的二维码图片的宽和高
     * @param height
     * @return
     */
    private Bitmap generateBitmap(String content, int width, int height) {
        //获得一个QRCodeWriter实例
        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        Map<EncodeHintType, String> hints = new HashMap<>();
        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
        try {
            //实例中有一个方法叫做encode,通过该方法对文本内容进行编码
            /**
             *第一个参数表示生成二维码的文本内容,第二个参数表示编码格式
             * 第三个参数表示生成的二维码的宽度,第四个参数表示生成的二维码的高度
             *第五个参数可选,可以用来设置文本的编码,encode方法的返回值是一个BitMatrix,
             * 你可以把BitMatrix理解成一个二维数组,这个二维数组的每一个元素都表示一个像素点是否有数据。
             */
            BitMatrix encode = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, width, height, hints);
            //定义一个int数组用来存放Bitmap中所有像素点的颜色
            int[] pixels = new int[width * height];
            //遍历BitMatrix,如果BitMatrix上的点表示 该点有数据,那么对应在Bitmap上的像素点就是黑色,否则就是白色。
            for (int i = 0; i < height; i++) {
                for (int j = 0; j < width; j++) {
                    //encode.get() ,get方法的返回值为一个boolean类型,true表示该点有数据,false表示该点没有数据
                    if (encode.get(j, i)) {
                        pixels[i * width + j] = 0x00000000;//黑色
                    } else {
                        pixels[i * width + j] = 0xffffffff;//白色
                    }
                }
            }
            /**
             * 第一个参数表示Bitmap中所有像素点的颜色,第二个参数表示像素点的偏移量,
             * 第三个参数表示Bitmap每行有多少个像素点,第四个参数表示生成的Bitmap的宽度,
             * 第五个参数表示生成的Bitmap的高度,第六个参数表示生成的Bitmap的色彩模式
             */
            return Bitmap.createBitmap(pixels, 0, width, width, height, Bitmap.Config.RGB_565);
        } catch (WriterException e) {
            e.printStackTrace();
        }
        return null;
    }
点击

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_create_erweima:
                //生成二维码不带LOGO
                Bitmap qrBitmap = generateBitmap("http://www.csdn.net",400, 400);
                iv_erweima.setImageBitmap(qrBitmap);

                break;
        }
    }
生成二维码带LOGO

    /**
     * 自定义添加二维码中间LOGO 的方法
     * @param qrBitmap   生成的二维码的Bitmap图片
     * @param logoBitmap logo图片
     * @return
     */
    private Bitmap addLogo(Bitmap qrBitmap, Bitmap logoBitmap) {
        //先获取到两张Bitmap各自的宽高
        int qrBitmapWidth = qrBitmap.getWidth();
        int qrBitmapHeight = qrBitmap.getHeight();
        int logoBitmapWidth = logoBitmap.getWidth();
        int logoBitmapHeight = logoBitmap.getHeight();
        //创建一个新的空白的Bitmap,这个新的空白的Bitmap的宽高和二维码的宽高一致
        Bitmap blankBitmap = Bitmap.createBitmap(qrBitmapWidth, qrBitmapHeight, Bitmap.Config.ARGB_8888);
        //创建一个Canvas对象(画布),创建Canvas对象的时候将blankBitmap传入,
        // 这样我一会绘制的东西相当于都是绘制在了blankBitmap上了
        Canvas canvas = new Canvas(blankBitmap);
        /**
         *drawBitmap()先将原本的二维码图片绘制出来
         * 第一个是你要绘制的Bitmap对象,
         * 第二个和第三个是你要绘制的Bitmap的左上角的坐标,
         * 第四个参数是一个画笔,一般情况下我们给一个null就可以了,如果你要设置重复模式等等效果的时候可以不给null。
         */
        canvas.drawBitmap(qrBitmap, 0, 0, null);
        //绘制出后将当前的绘制状态保存下来,然后对画布进行缩放,缩小画布之后我们来绘制Logo
        canvas.save(Canvas.ALL_SAVE_FLAG);

        //一般情况下logo的宽高为二维码原图宽高的1/5(中心logo图片不宜过大,否则会影响到二维码的识别),
        // 所以我们先通过一个while循环获得缩放比例
        float scaleSize = 1.0f;
        while ((logoBitmapWidth / scaleSize) > (qrBitmapWidth / 5) || (logoBitmapHeight / scaleSize) > (qrBitmapHeight / 5)) {
            scaleSize *= 2;
        }
        float sx = 1.0f / scaleSize;

        //然后 scale() 对画布进行缩放,前两个参数表示宽高的缩放比例,大于1表示放大,小于1表示缩小,后两个参数表示缩放的中心点
        canvas.scale(sx, sx, qrBitmapWidth / 2, qrBitmapHeight / 2);
//        canvas.scale(sx, sx, 0, 0);
        //绘制logo
        canvas.drawBitmap(logoBitmap, (qrBitmapWidth - logoBitmapWidth) / 2, (qrBitmapHeight - logoBitmapHeight) / 2, null);
        //restore方法将画布恢复为原来的状态,最后将blankBitmap返回
        canvas.restore();
        return blankBitmap;
    }
点击

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_create_erweima:

                //生成二维码并且带有中间LOGO
                Bitmap qrBitmap = generateBitmap("http://www.csdn.net", 400, 400);
                Bitmap logoBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
                Bitmap bitmap = addLogo(qrBitmap, logoBitmap);
                iv_erweima.setImageBitmap(bitmap);

                break;
        }
    }
生成二维码源码: http://download.csdn.net/detail/lijinweii/9899517

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值