Android 二维码扫描(仿微信界面),根据Google zxing
Android项目开发中经常会用到二维码扫描,例如登陆、支付等谷歌方面已经有了一个开源库(地址: https://github.com/zxing/zxing),里面的内容还是比较多的,如果想深入学习这方面的内容,还是不错的。当然了还是要根据实际需求去选择,所以我们就选择类库中的核心Jar包就行了(地址:https://github.com/ASCN-BJ/ZhaoYun/blob/master/qrcodelibrary/libs/core-3.3.1.jar)。
GoogleZxing中的原装的类库有一个问题就是竖屏的时候会导致无法识别,原因是竖屏的时候没有对相机的预览效果进行处理,所以在项目中,进行了处理,使得竖屏的时候的识别能够成功。所以正好看了一下,就当学习了。
效果图
- 二维码的扫描
zxing中的二维码识别界面主要是在CaptureActivity中,基本原理通过获取相机的预览界面然后对获取到的数据进行处理,预览效果是在PreviewCallback中获取数据,然后通过DecodeHandler发送数据,具体识别是在DecodeHandler类中处理。
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
Point cameraResolution = configManager.getCameraResolution();
Handler thePreviewHandler = previewHandler;
// if (cameraResolution != null && thePreviewHandler != null) {
// Message message = thePreviewHandler.obtainMessage(previewMessage, cameraResolution.x,
// cameraResolution.y, data);
// message.sendToTarget();
// previewHandler = null;
// } else {
// Log.d(TAG, "Got preview callback, but no handler or resolution available");
// }
// Log.d(TAG, "onPreviewFrame: " + "onRunning");
if (cameraResolution != null && thePreviewHandler != null) {
//add by tancolo
Point screenResolution = configManager.getScreenResolution();
Message message;
if (screenResolution.x < screenResolution.y) {
// portrait
message = thePreviewHandler.obtainMessage(previewMessage, cameraResolution.y,
cameraResolution.x, data);
} else {
// landscape
message = thePreviewHandler.obtainMessage(previewMessage, cameraResolution.x,
cameraResolution.y, data);
}
message.sendToTarget();
previewHandler = null;
}
}
可以看到在onPreviewFrame中将具体byte[] data数据发送出去,同时将预览效果的宽高发送出去,用于后续的处理。
接下来看具体二维码识别的代码
@Override
public void handleMessage(Message message) {
if (message == null || !running) {
return;
}
if (message.what == R.id.decode) {
decode((byte[]) message.obj, message.arg1, message.arg2);
} else if (message.what == R.id.quit) {
running = false;
Looper.myLooper().quit();
}
}
private void decode(byte[] data, int width, int height) {
long start = System.currentTimeMillis();
//add by tancolo
if (width < height) {
// portrait
byte[] rotatedData = new byte[data.length];
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++)
rotatedData[y * width + width - x - 1] = data[y + x * height];
}
data = rotatedData;
}
//end add
Result rawResult = null;
PlanarYUVLuminanceSource source = activity.getCameraManager().buildLuminanceSource(data, width, height);
if (source != null) {
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
try {
rawResult = multiFormatReader.decodeWithState(bitmap);//具体识别方法,获取到数据
} catch (ReaderException re) {
// continue
} finally {
multiFormatReader.reset();
}
}
Handler handler = activity.getHandler();
if (rawResult != null) {
// Don't log the barcode contents for security.
long end = System.currentTimeMillis();
Log.d(TAG, "Found barcode in " + (end - start) + " ms");
if (handler != null) {
Message message = Message.obtain(handler, R.id.decode_succeeded, rawResult);
Bundle bundle = new Bundle();
bundleThumbnail(source, bundle);
message.setData(bundle);
message.sendToTarget();
}
} else {
if (handler != null) {
Message message = Message.obtain(handler, R.id.decode_failed);
message.sendToTarget();
}
}
}
- 二维码的生成
这里写代码片
try {
mQRCodeEncoder2 = new QRCodeEncoder2(smallerDimension);
//生成二维码
Bitmap bitmap = mQRCodeEncoder2.encodeAsBitmap(text, BarcodeFormat.QR_CODE);
if (bitmap == null) {
qrCodeEncoder = nul