【Android】开发生成和扫描二维码功能

291 阅读3分钟

Android开发 生成和扫描二维码

导入库

implementation ("com.google.zxing:core:3.4.1")  
implementation ("com.journeyapps:zxing-android-embedded:4.3.0")

添加权限

<!--摄像机权限-->  
<uses-permission android:name="android.permission.CAMERA" />  
<uses-feature android:name="android.hardware.camera" android:required="false" />  
<!--手机震动权限-->  
<uses-permission android:name="android.permission.VIBRATE" />  
<uses-permission android:name="android.permission.FLASHLIGHT" />  
<!--读取本地图片权限-->  
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />  
<!-- 自动聚焦权限 -->  
<uses-feature android:name="android.hardware.camera.autofocus" />

需要的导入库

import android.graphics.Canvas;  
import android.graphics.Paint;  
import android.graphics.Rect;  
import android.net.Uri;
import android.provider.MediaStore;
import com.google.zxing.WriterException;  
import com.google.zxing.qrcode.QRCodeWriter;  
import com.google.zxing.BarcodeFormat;  
import com.google.zxing.common.BitMatrix;  
import android.graphics.Bitmap;  
import android.graphics.Color;  
import android.widget.ImageView;
import java.io.UnsupportedEncodingException;  
import java.net.URLDecoder;  
import java.net.URLEncoder;

生成二维码

String encodedInfo = "二维码内容";  
// 二维码宽度  
int width = 320; 
// 二维码高度  
int height = 320; 
QRCodeWriter writer = new QRCodeWriter();  
BitMatrix bitMatrix = writer.encode(encodedInfo, BarcodeFormat.QR_CODE, width, height);  
int matrixWidth = bitMatrix.getWidth();  
int matrixHeight = bitMatrix.getHeight();  
Bitmap bitmap = Bitmap.createBitmap(matrixWidth, matrixHeight, Bitmap.Config.RGB_565);  
  
for (int x = 0; x < matrixWidth; x++) {  
    for (int y = 0; y < matrixHeight; y++) {  
        bitmap.setPixel(x, y, bitMatrix.get(x, y) ? Color.BLACK : Color.WHITE); 
    }  
}

bitmap 就是生成的二维码,这样二维码确实生成了,但是看不到,我们找个图片控件显示出来。

显示二维码图片到界面中

在界面中有一个图片控件。

<ImageView  
    android:id="@+id/btn_main_generate_qr_code_img"  
    android:layout_width="320dp"  
    android:layout_height="320dp"  
    android:layout_gravity="center"  
    android:importantForAccessibility="no"  
    android:layout_marginTop="20dp"  
    android:layout_marginBottom="20dp"  
/>

bitmap 就是上面生成二维码的bitmap

... 生成二维码代码
// 将生成的二维码显示在ImageView中  
ImageView imageView = findViewById(R.id.btn_main_generate_qr_code_img);  
imageView.setImageBitmap(bitmap);

这样图片就会显示出来,我们再开发一个点击按钮后,保存在手机相册功能,不然不能扫描和保存。

二维码添加底部文字

... 生成二维码代码
// 在生成二维码的代码块中添加以下代码来绘制文字  
Canvas canvas = new Canvas(bitmap);  
Paint paint = new Paint();  
paint.setColor(Color.BLACK);  
paint.setTextSize(18); // 设置文字大小  
paint.setTextAlign(Paint.Align.CENTER); // 设置文字居中  
  
// 绘制文字在二维码底部中间位置  
String text = "长城6矿二维码最近遇上了扫描条码的需求,在查找资料过程中不是那么地顺利";  
Rect bounds = new Rect();  
paint.getTextBounds(text, 0, text.length(), bounds);  
int xText = (bitmap.getWidth() - bounds.width())/2;  
int yText = bitmap.getHeight() - 4; // 调整文字距离底部的位置  
canvas.drawText(text, 40, yText, paint);  
// 裁剪Bitmap,去除多余的空白  
int sideCut = 36; // 左右两边裁剪宽度  
Bitmap trimmedBitmap = Bitmap.createBitmap(bitmap, sideCut, sideCut, width - 2 * sideCut, height - sideCut);
... 保存图片代码,保存图片传递最新的trimmedBitmap,而不是bitmap

保存图片到手机相册中

在界面有一个

// 保存在相册  
Button btnMainSaveQrCodeImg = findViewById(R.id.btn_main_save_qr_code_img);  
btnMainSaveQrCodeImg.setOnClickListener(v -> {  
    // 在按钮点击事件中添加以下代码  
    ImageView imageView = findViewById(R.id.btn_main_generate_qr_code_img);  
    imageView.setDrawingCacheEnabled(true);  
    Bitmap qrImage = imageView.getDrawingCache();  

    String savedImagePath = MediaStore.Images.Media.insertImage(getContentResolver(), qrImage, "QRCode", "Generated QR Code");  
    Uri savedImageURI = Uri.parse(savedImagePath);  

    if (savedImageURI != null) {  
        Log.d("IVESTAG", "btnMainSaveQrCodeImg:" + "二维码已保存到相册");  
    } else {  
        Log.d("IVESTAG", "btnMainSaveQrCodeImg:" + "保存失败");  
    }  
});

扫描二维码

// 扫描二维码  
Button btnMainScanQrCode = findViewById(R.id.btn_main_scan_qr_code);  
btnMainScanQrCode.setOnClickListener(v -> {  
    IntentIntegrator integrator = new IntentIntegrator(this);  
    //:设置扫描时的提示信息。  
    integrator.setPrompt("请扫描设备中的二维码");  
    // 设置是否锁定扫描器的方向。  
    integrator.setOrientationLocked(true);  
    // 设置使用的相机ID,0为后置摄像头,1为前置摄像头。  
    integrator.setCameraId(0);  
    // 设置是否开启闪光灯。  
    integrator.setTorchEnabled(true);  
    // 设置是否开启扫描成功时的蜂鸣提示。  
    integrator.setBeepEnabled(true);  
    // 设置是否在扫描时显示扫描的条码图像。  
    integrator.setBarcodeImageEnabled(true);  
    // 设置期望扫描的条码格式,如QR_CODE、CODE_39等  
    integrator.setDesiredBarcodeFormats(IntentIntegrator.QR_CODE);  
    integrator.initiateScan();  
});

如果这样写了会发现扫描时横屏,于是需要创建一个空的ScanPage的页面,只要创建java文件即可,不用创建xml

解决扫描横屏问题

创建ScanPage.java文件,继承CaptureActivity

package com.hxtx.august.Page;  
import android.os.Bundle;  
import com.journeyapps.barcodescanner.CaptureActivity;  
  
public class ScanPage extends CaptureActivity {  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
    }  
}

AndroidManifest.xml文件中添加action

<activity android:name=".Page.ScanPage" android:screenOrientation="fullSensor" />

在扫描二维码代码中添加ScanPage类即可

    // 设置自定义的扫描Activity  
    integrator.setCaptureActivity(ScanPage.class);  

解决二维码中中文乱码问题

import java.net.URLDecoder;

// 加码 生成二维码时使用
combinedInfo = URLEncoder.encode(combinedInfo, "UTF-8");
// 解码,扫描二维码时使用
scannedData = URLDecoder.decode(scannedData, "UTF-8");