Android Studio基于zxing的第三方库zxing-android-embedded实现生成二维码与扫描二维码

为了在APP中添加扫码功能,需要用到相关的开源库,最常见的是zxing库和zbar库,zbar很多年前就已经不再维护了,xing还在维护,但是使用起来比较复杂。为了使用起来更方便,于是选择基于zxing集成的第三方库zxing-android-embedded。主要参考了第三方ZXing库zxing-android-embedded使用及自定义安卓Zxing的简单使用-(生成二维码与扫一扫)这两篇博客,以及android和该库的官方文档。

配置依赖

  1. 在app/build.gradle中添加如下
dependencies {
	......
	implementation 'com.journeyapps:zxing-android-embedded:3.6.0'
	......
}
  1. 点击如下图所示的 Sync Now,完成配置依赖。
    在这里插入图片描述

生成二维码

步骤

生成二维码步骤如下:

  1. 申明一个QRCodeWriter对象QRCodeWriter类文档
  2. QRCodeWriter的encode方法(提供长、宽等参数,其余参数不太理解),返回一个BitMatrix对象。
  3. 循环遍历BitMatrix对象,将其存储到矩阵中。(在上面的文档中可以看到Bitmatrix的get(i,j)方法中,i: 列,j:行)。
  4. 为了将图像能够显示出来,需要转换成Bitmap对象, 调用Bitmap的createBitmap方法,将其转化成Bitmap对象。Bitmap类文档
  5. 通过ImageView控件的setImageBitmap方法,显示二维码。

简单实践

  1. 在activity_main.xml添加布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <EditText
        android:id="@+id/edit_input_string"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="输入需要转换的字符串"/>

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

    <ImageView
        android:id="@+id/imageview_QRcode"
        android:layout_width="match_parent"
        android:layout_height="250dp" />
</LinearLayout>

效果如下:在这里插入图片描述

  1. 在活动MainActivity.java中添加逻辑,其中generate_QRCode_Bitmap方法对应上述的步骤。
package com.example.myqrtest;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.graphics.Bitmap;
import android.media.Image;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
import com.google.zxing.qrcode.QRCodeWriter;

import java.util.HashMap;
import java.util.Map;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private TextView textView;

    private ImageView imageView;

    private Button button_gerate_QRCode;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        textView = (TextView) findViewById(R.id.edit_input_string);
        button_gerate_QRCode = (Button) findViewById(R.id.button_generate_QRcode);
        imageView = (ImageView) findViewById(R.id.imageview_QRcode);

        button_gerate_QRCode.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.button_generate_QRcode:
                String input_string = textView.getText().toString().trim();
                if(!TextUtils.isEmpty(input_string)){
                    imageView.setImageBitmap(generate_QRCode_Bitmap(input_string,600,600));
                }
            default:
        }
    }

    private Bitmap generate_QRCode_Bitmap(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] = 0x000000;
                    } else {
                        pixels[i * width + j] = 0xffffff;
                    }
                }
            }
            return Bitmap.createBitmap(pixels, 0, width, width, height, Bitmap.Config.RGB_565);
            //根据官方文档显示stride:Number of colors in the array between rows (must be >= width or <= -width).
            // 即Bitmap.createBitmap方法中第三个参数需要大于width。
        } catch (WriterException e) {
            e.printStackTrace();
        }
        return null;
    }
}
  1. 运行一下,看看效果
    在这里插入图片描述

扫描二维码

  1. 在zxing-android-embedded中,已经为我们默认写了一些界面,我们可以直接调用写好的类快速实现扫码功能。
  2. 在Activity中直接添加下列代码可以直接实现扫码功能。
new IntentIntegrator(this)
        .setDesiredBarcodeFormats(IntentIntegrator.ONE_D_CODE_TYPES)// 扫码的类型,一维码,二维码,一/二维码,默认为一/二维码
        .setPrompt("请对准二维码")// 设置提示语
        .setCameraId(0)// 选择摄像头,可使用前置或者后置
        .setBeepEnabled(false)// 是否开启声音,扫完码之后会"哔"的一声
        .initiateScan();// 初始化扫码
  1. 在上述代码中,我们为了得到intent的回调结果,需要重载onActivityResultfang方法,代码如下。
 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
        if(result != null) {
            if(result.getContents() == null) {
                Toast.makeText(this, "Cancelled", Toast.LENGTH_LONG).show();
            } else {
                Toast.makeText(this, "Scanned: " + result.getContents(), Toast.LENGTH_LONG).show();
            }
        }
    }

运行一下,可以看到
在这里插入图片描述
注意:

  • 该部分代码在生成二维码代码之后添加进行直接测试(最后再添加其他控件点击扫码),可以看到,直接打开应用就是一个扫码界面。
  • 对于使用相机,需要动态申请权限,这里我们什么都没有写,说明该第三方库已经帮我们封装好了。

自定义扫描二维码

先给出结果

对于IntentIntegrator对象,参考可以配置其属性,其中有一项为:setCaptureActivity方法,参数为我们给出的一个Activity类。默认为Activity.java。我们需要给出一个Activity类,来改变横屏与竖屏。扫描框的大小则需要我们给出一个布局文件。下面给出代码。

自定义部分:横屏与竖屏(扫码)设置

  1. 修改MainActivity.java中的如下内容,注意`setCaptureActivity(CaptureActivity.class)``这一行
new IntentIntegrator(this)
	//.setDesiredBarcodeFormats(IntentIntegrator.ONE_D_CODE_TYPES)// 扫码的类型,可选:一维码,二维码,一/二维码
	.setPrompt("请对准二维码")// 设置提示语
	.setCameraId(0)// 选择摄像头,可使用前置或者后置
	.setBeepEnabled(false)// 是否开启声音,扫完码之后会"哔"的一声
	//.setBarcodeImageEnabled(true)// 扫完码之后生成二维码的图片
	.setCaptureActivity(CaptureActivity.class)
	.initiateScan();// 初始化扫码
  1. 要得到库里的Activity文件,有很多种方法,比如github源码中,或者在编辑器内敲出来Activity,然后ctrl +鼠标左键 直接进入该文件。

  2. 获取Activity文件,复制其内容到如下路径中。注意导入的包要自己调一下。(自己创建一个Activity文件再复制其内容,否则需要自己手动进入AndroidManifest.xml中注册活动)
    在这里插入图片描述

  3. 运行一下,如图,可以发现已经变为竖屏了。
    在这里插入图片描述

自定义部分:扫码框大小的设置

  1. 我们 添加一个layout布局文件去覆盖掉原来自动导入的布局文件,和源码中的命名一样。
    在这里插入图片描述
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <com.journeyapps.barcodescanner.BarcodeView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/zxing_barcode_surface"
        app:zxing_framing_rect_width="250dp"
        app:zxing_framing_rect_height="50dp"/>

    <com.journeyapps.barcodescanner.ViewfinderView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/zxing_viewfinder_view"/>

    <TextView android:id="@+id/zxing_status_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|center_horizontal"
        android:background="@color/zxing_transparent"
        android:text="@string/zxing_msg_default_status"
        android:textColor="@color/zxing_status_text"/>
</merge>
  1. 注意,上述代码中的下面两行,是扫码框的大小,如下图箭头所指。
app:zxing_framing_rect_width="250dp"
app:zxing_framing_rect_height="50dp"

在这里插入图片描述

自定义部分:其他(未实践)

在运行源码Demo的时候看到一些自定义样例,自己没进行调试了,以后再说。。。。(官网demo不知道为啥一运行就特别卡,最重要的是还占了好大的空间= =)
在这里插入图片描述

分析与总结(很啰嗦)

在自定义的过程中,可以看到源码中的setCaptureActivity默认了参数captureActivity。完全可以自己写一个Activity作为参数。(取其他名字更安全些)。
在这里插入图片描述
之所以自己写一个Activity作为参数就可以改为竖屏是因为源码中(见下图),因此我们自己创建的Activity可以根据需要自己添加属性!
在这里插入图片描述
打开源码CaptureActivity文件
在这里插入图片描述
对于上述文件,参考这篇博客第三方ZXing库zxing-android-embedded使用及自定义写的。如下截图。对于BarcodeView与ViewfinderView的说法我觉得不对,其一是在调试的过程中尝试改变布局的长宽属性可以否定,其二在查看源码时发现扫描框的配置实际上是在BarcodeView中配置的,而背景颜色是在BarcodeView中,正好相反。但是当把BarcodeView长款调为0整个界面又没了。。。。所以不好说具体的对应关系。晕。。。。。。。
在这里插入图片描述
源码看的还有很多想法,但是理解太浅了,还要多学习,废话有点多,就写到这里结束吧。

  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值