为了在APP中添加扫码功能,需要用到相关的开源库,最常见的是zxing库和zbar库,zbar很多年前就已经不再维护了,xing还在维护,但是使用起来比较复杂。为了使用起来更方便,于是选择基于zxing集成的第三方库zxing-android-embedded。主要参考了第三方ZXing库zxing-android-embedded使用及自定义与安卓Zxing的简单使用-(生成二维码与扫一扫)这两篇博客,以及android和该库的官方文档。
配置依赖
- 在app/build.gradle中添加如下
dependencies {
......
implementation 'com.journeyapps:zxing-android-embedded:3.6.0'
......
}
- 点击如下图所示的
Sync Now
,完成配置依赖。
生成二维码
步骤
生成二维码步骤如下:
- 申明一个QRCodeWriter对象QRCodeWriter类文档
- QRCodeWriter的encode方法(提供长、宽等参数,其余参数不太理解),返回一个BitMatrix对象。
- 循环遍历BitMatrix对象,将其存储到矩阵中。(在上面的文档中可以看到Bitmatrix的get(i,j)方法中,i: 列,j:行)。
- 为了将图像能够显示出来,需要转换成Bitmap对象, 调用Bitmap的createBitmap方法,将其转化成Bitmap对象。Bitmap类文档
- 通过ImageView控件的setImageBitmap方法,显示二维码。
简单实践
- 在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>
效果如下:
- 在活动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;
}
}
- 运行一下,看看效果
扫描二维码
- 在zxing-android-embedded中,已经为我们默认写了一些界面,我们可以直接调用写好的类快速实现扫码功能。
- 在Activity中直接添加下列代码可以直接实现扫码功能。
new IntentIntegrator(this)
.setDesiredBarcodeFormats(IntentIntegrator.ONE_D_CODE_TYPES)// 扫码的类型,一维码,二维码,一/二维码,默认为一/二维码
.setPrompt("请对准二维码")// 设置提示语
.setCameraId(0)// 选择摄像头,可使用前置或者后置
.setBeepEnabled(false)// 是否开启声音,扫完码之后会"哔"的一声
.initiateScan();// 初始化扫码
- 在上述代码中,我们为了得到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类,来改变横屏与竖屏。扫描框的大小则需要我们给出一个布局文件。下面给出代码。
自定义部分:横屏与竖屏(扫码)设置
- 修改
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();// 初始化扫码
-
要得到库里的
Activity
文件,有很多种方法,比如github源码中,或者在编辑器内敲出来Activity
,然后ctrl +鼠标左键
直接进入该文件。 -
获取Activity文件,复制其内容到如下路径中。注意导入的包要自己调一下。(自己创建一个Activity文件再复制其内容,否则需要自己手动进入
AndroidManifest.xml
中注册活动)
-
运行一下,如图,可以发现已经变为竖屏了。
自定义部分:扫码框大小的设置
- 我们 添加一个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>
- 注意,上述代码中的下面两行,是扫码框的大小,如下图箭头所指。
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整个界面又没了。。。。所以不好说具体的对应关系。晕。。。。。。。
源码看的还有很多想法,但是理解太浅了,还要多学习,废话有点多,就写到这里结束吧。