ZXing的GitHub地址:
ZXing (“Zebra Crossing”) barcode scanning library for Java, Android
徐宜生修改后的GitHub地址:
ZXing使用全解析
一扫天下——ZXing使用全解析
compile 'com.google.zxing:core:3.3.0'
注意:权限高于23(android6.0)需要动态配置权限
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera.autofocus" />
ZXing暴露的调用Activity。在handleDecode方法中对扫码成功后的动作作处理。
ZXing扫码窗口的绘制,原始的ZXing使用这种方式去绘制,在上面提供的开源库中,作者将扫描框的绘制直接抽取到了XML文件中,这样修改起来更加方便了。
修改横竖屏、处理变形效果的核心类。
在public void setDesiredCameraParameters(Camera camera, boolean safeMode)方法中(读取配置设置相机的对焦模式、闪光灯模式等等),可以将扫描改为竖屏:
即: 在方法最后加上:
/** 设置相机预览为竖屏 */
camera.setDisplayOrientation(90);
即可。
在public void initFromCameraParameters(Camera camera)方法中(计算了屏幕分辨率和当前最适合的相机像素),我们可以对修改为竖屏扫码后,由于像素信息点没有对调造成图像扭曲变形进行修改。
即:
在Log.d(TAG, “Screen resolution: ” + screenResolution);后加上如下的代码:
/** 因为换成了竖屏显示,所以不替换屏幕宽高得出的预览图是变形的 */
Point screenResolutionForCamera = new Point();
screenResolutionForCamera.x = screenResolution.x;
screenResolutionForCamera.y = screenResolution.y;
if (screenResolution.x < screenResolution.y) {
screenResolutionForCamera.x = screenResolution.y;
screenResolutionForCamera.y = screenResolution.x;
}
最后,将screenResolution替换为screenResolutionForCamera:
cameraResolution = findBestPreviewSizeValue(parameters, screenResolutionForCamera);
ZXing解码的核心类
当DecodeHandler.decode完成解码后,系统会向CaptureActivityHandler发消息。如果编码成功则调用CaptureActivity.handleDecode方法对扫描到的结果进行分类处理。
使用Google开源Zxing扫描
1、原始代码是横屏模式,尽管可以改成竖屏,但是扫描界面的自定义和多屏幕适配不好做
2、有效扫描区域不好控制
3、Zxing是Java写的,对二维码的解析效率不是很高
使用iOS开发经常使用的Zbar扫描
1、 Zbar是c实现的二维码解析,效率和Zxing不是一个层面的,但是貌似是日本人写的,中文扫描会乱码
2、 Zbar的扫描界面对相机的控制没有Zxing封装的好
ZXing是纯Java代码实现的,适用于Android平台;
Zbar是C实现的,可以供很多语言和平台使用,比如Java、iOS平台、Android平台,Python等等。
很明显Zbar的识别率和速度都是明显快于ZXing的
用zxing做的扫描需要与二维码差不多完全平行才能扫出来
所以将二者结合起来,用Zxing来控制摄像头,用Zbar来解析扫描到的数据
我集成的demo GitHub地址
参考:Android实现二维码扫描功能(一)-ZXing插件接入
package com.xys.libzxing.zxing.encoding;
import android.graphics.Bitmap;
import android.graphics.Canvas;
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.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import java.util.HashMap;
import java.util.Map;
/**
* 二维码生成工具类
*/
public class EncodingUtils {
/**
* 创建二维码
*
* @param content content
* @param widthPix widthPix
* @param heightPix heightPix
* @param logoBm logoBm
* @return 二维码
*/
public static Bitmap createQRCode(String content, int widthPix, int heightPix, Bitmap logoBm) {
try {
if (content == null || "".equals(content)) {
return null;
}
// 配置参数
Map hints = new HashMap<>();
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
// 容错级别
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
// 图像数据转换,使用了矩阵转换
BitMatrix bitMatrix = new QRCodeWriter().encode(content, BarcodeFormat.QR_CODE, widthPix,
heightPix, hints);
int[] pixels = new int[widthPix * heightPix];
// 下面这里按照二维码的算法,逐个生成二维码的图片,
// 两个for循环是图片横列扫描的结果
for (int y = 0; y < heightPix; y++) {
for (int x = 0; x < widthPix; x++) {
if (bitMatrix.get(x, y)) {
pixels[y * widthPix + x] = 0xff000000;
} else {
pixels[y * widthPix + x] = 0xffffffff;
}
}
}
// 生成二维码图片的格式,使用ARGB_8888
Bitmap bitmap = Bitmap.createBitmap(widthPix, heightPix, Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixels, 0, widthPix, 0, 0, widthPix, heightPix);
if (logoBm != null) {
bitmap = addLogo(bitmap, logoBm);
}
//必须使用compress方法将bitmap保存到文件中再进行读取。直接返回的bitmap是没有任何压缩的,内存消耗巨大!
return bitmap;
} catch (WriterException e) {
e.printStackTrace();
}
return null;
}
/**
* 在二维码中间添加Logo图案
*/
private static Bitmap addLogo(Bitmap src, Bitmap logo) {
if (src == null) {
return null;
}
if (logo == null) {
return src;
}
//获取图片的宽高
int srcWidth = src.getWidth();
int srcHeight = src.getHeight();
int logoWidth = logo.getWidth();
int logoHeight = logo.getHeight();
if (srcWidth == 0 || srcHeight == 0) {
return null;
}
if (logoWidth == 0 || logoHeight == 0) {
return src;
}
//logo大小为二维码整体大小的1/5
float scaleFactor = srcWidth * 1.0f / 5 / logoWidth;
Bitmap bitmap = Bitmap.createBitmap(srcWidth, srcHeight, Bitmap.Config.ARGB_8888);
try {
Canvas canvas = new Canvas(bitmap);
canvas.drawBitmap(src, 0, 0, null);
canvas.scale(scaleFactor, scaleFactor, srcWidth / 2, srcHeight / 2);
canvas.drawBitmap(logo, (srcWidth - logoWidth) / 2, (srcHeight - logoHeight) / 2, null);
canvas.save(Canvas.ALL_SAVE_FLAG);
canvas.restore();
} catch (Exception e) {
bitmap = null;
e.getStackTrace();
}
return bitmap;
}
}
检查是否依赖了多个zxing包,保证一个的情况下,如果还出错,
依然会出现找不到BarcodeFormat.RSS14 这个变量。
直接把BarcodeFormat.RSS14改成BarcodeFormat.RSS_14就可以了