枕上从妨一夜睡,灯前读尽十年诗。这篇文章主要讲述Android 二维码扫描怎样实现第二次(重复)扫描相关的知识,希望能为你提供帮助。
【Android 二维码扫描怎样实现第二次(重复)扫描】相关文章:
Android 基于google Zxing实现二维码、条形码扫描,仿微信二维码扫描效果
http://blog.csdn.net/xiaanming/article/details/10163203
下载地址:http://download.csdn.net/detail/xiaanming/5990219
首先看一下扫描界面
CaptureCodeActivity.java代码:
package com.haier.qr.code;
import java.io.IOException;
import java.io.Serializable;
import java.util.Map;
import java.util.Vector;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.DecodeHintType;
import com.google.zxing.Result;
import com.haier.cabinet.customer.R;
import com.haier.cabinet.customer.activity.DeliveryBoxListActivity;
import com.haier.common.util.AppToast;
import com.haier.qr.code.zxing.camera.CameraManager;
import com.haier.qr.code.zxing.decoding.CaptureActivityHandler;
import com.haier.qr.code.zxing.decoding.FinishListener;
import com.haier.qr.code.zxing.decoding.InactivityTimer;
import com.haier.qr.code.zxing.view.ViewfinderView;
/**
* Initial the camera
*
* @author jdsjlzx
*/
public class CaptureCodeActivity extends Activity implements Callback,View.OnClickListener { private static final String TAG = CaptureCodeActivity.class
.getSimpleName();
private CameraManager cameraManager;
private CaptureActivityHandler handler;
private ViewfinderView viewfinderView;
private boolean hasSurface;
private Map<
DecodeHintType, ?>
decodeHints;
private Vector<
BarcodeFormat>
decodeFormats;
private String characterSet;
private InactivityTimer inactivityTimer;
private boolean isFlashlightOpen;
/**
* 声音震动管理器。如果扫描成功后可以播放一段音频,也可以震动提醒,可以通过配置来决定扫描成功后的行为。
*/
private BeepManager beepManager;
/**
* 闪光灯调节器。自动检测环境光线强弱并决定是否开启闪光灯
*/
private AmbientLightManager ambientLightManager;
public CameraManager getCameraManager() {
return cameraManager;
} /** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.activity_capture);
hasSurface = false;
inactivityTimer = new InactivityTimer(this);
beepManager = new BeepManager(this);
ambientLightManager = new AmbientLightManager(this);
//按钮监听事件
findViewById(R.id.capture_flashlight).setOnClickListener(this);
} @Override
protected void onResume() {
super.onResume();
Log.d(TAG, "onResume");
cameraManager = new CameraManager(getApplication());
viewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view);
viewfinderView.setCameraManager(cameraManager);
viewfinderView.setVisibility(View.VISIBLE);
SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view);
SurfaceHolder surfaceHolder = surfaceView.getHolder();
if (hasSurface) {
initCamera(surfaceHolder);
} else {
// 防止sdk8的设备初始化预览异常
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
// Install the callback and wait for surfaceCreated() to init the
// camera.
surfaceHolder.addCallback(this);
}
decodeFormats = null;
characterSet = null;
// 加载声音配置,其实在BeemManager的构造器中也会调用该方法,即在onCreate的时候会调用一次
beepManager.updatePrefs();
// 启动闪光灯调节器
ambientLightManager.start(cameraManager);
// 恢复活动监控器
inactivityTimer.onResume();
}
@Override
protected void onPause() {
Log.d(TAG, "onPause");
if (handler != null) {
handler.quitSynchronously();
handler = null;
}
inactivityTimer.onPause();
ambientLightManager.stop();
beepManager.close();
// 关闭摄像头
cameraManager.closeDriver();
if (!hasSurface) {
SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view);
SurfaceHolder surfaceHolder = surfaceView.getHolder();
surfaceHolder.removeCallback(this);
}
super.onPause();
} @Override
protected void onDestroy() {
inactivityTimer.shutdown();
super.onDestroy();
} /**
* A valid barcode has been found, so give an indication of success and show
* the results.
*
* @param rawResult
*The contents of the barcode.
* @param scaleFactor
*amount by which thumbnail was scaled
* @param barcode
*A greyscale bitmap of the camera data which was decoded.
*/
public void handleDecode(Result rawResult, Bitmap barcode, float scaleFactor) {
Log.d(TAG, "handleDecode");
inactivityTimer.onActivity();
beepManager.playBeepSoundAndVibrate();
String resultString = rawResult.getText();
if (TextUtils.isEmpty(resultString)) {
Toast.makeText(CaptureCodeActivity.this, "Scan failed!",
Toast.LENGTH_SHORT).show();
} else {
//扫码完成,处理结果(跳转到箱子列表)
/*Intent resultIntent = new Intent();
Bundle bundle = new Bundle();
bundle.putString("result", resultString);
bundle.putParcelable("bitmap", barcode);
resultIntent.putExtras(bundle);
this.setResult(RESULT_OK, resultIntent);
*/
String terminalNo = getIntent().getStringExtra("terminal_no");
if (resultString.equals(terminalNo)) {
AppToast.makeToast(this, "确认成功!");
Intent intent = new Intent(this, DeliveryBoxListActivity.class);
intent.putExtra("terminal_no", terminalNo);
intent.putExtra("box_list", (Serializable) getIntent().getSerializableExtra("box_list"));
startActivity(intent);
CaptureCodeActivity.this.finish();
} else {
/*AppToast.makeToast(this, "确认失败,请重新扫描确认");
*/
showErrorDialog();
}} } private void initCamera(SurfaceHolder surfaceHolder) {
if (surfaceHolder == null) {
throw new IllegalStateException("No SurfaceHolder provided");
}
if (cameraManager.isOpen()) {
Log.w(TAG,
"initCamera() while already open -- late SurfaceView callback?");
return;
}
try {
cameraManager.openDriver(surfaceHolder);
// Creating the handler starts the preview, which can also throw a
// RuntimeException.
if (handler == null) {
handler = new CaptureActivityHandler(this, decodeFormats,
decodeHints, characterSet, cameraManager);
}} catch (IOException ioe) {
Log.w(TAG, ioe);
displayFrameworkBugMessageAndExit();
} catch (RuntimeException e) {
// Barcode Scanner has seen crashes in the wild of this variety:
// java.?lang.?RuntimeException: Fail to connect to camera service
Log.w(TAG, "Unexpected error initializing camera", e);
displayFrameworkBugMessageAndExit();
}
} private void displayFrameworkBugMessageAndExit() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(getString(R.string.app_name));
builder.setMessage(getString(R.string.msg_camera_framework_bug));
builder.setPositiveButton(android.R.string.yes, new FinishListener(this));
builder.setOnCancelListener(new FinishListener(this));
builder.show();
} @Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) { } @Override
public void surfaceCreated(SurfaceHolder holder) {
if (holder == null) {
Log.e(TAG,
"*** WARNING *** surfaceCreated() gave us a null surface!");
}
if (!hasSurface) {
hasSurface = true;
initCamera(holder);
} } @Override
public void surfaceDestroyed(SurfaceHolder holder) {
hasSurface = false;
} public ViewfinderView getViewfinderView() {
return viewfinderView;
} public Handler getHandler() {
return handler;
} public void drawViewfinder() {
viewfinderView.drawViewfinder();
} @Override
public void onClick(View v) {
switch (v.getId()) {case R.id.capture_flashlight:
if (isFlashlightOpen) {
cameraManager.setTorch(false);
// 关闭闪光灯
isFlashlightOpen = false;
}
else {
cameraManager.setTorch(true);
// 打开闪光灯
isFlashlightOpen = true;
}
break;
default:
break;
}
} private void showErrorDialog() {
closeCamera();
viewfinderView.setVisibility(View.GONE);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(getString(R.string.app_name));
builder.setMessage("扫描确认出错,请重新扫描二维码!");
builder.setPositiveButton(android.R.string.ok, new OnClickListener() {@Override
public void onClick(DialogInterface dialog, int which) {
restartCamera();
}
});
builder.setOnCancelListener(new OnCancelListener() {@Override
public void onCancel(DialogInterface dialog) {
CaptureCodeActivity.this.finish();
}
});
builder.show();
}
void restartCamera(){
Log.d(TAG, "hasSurface " + hasSurface);
viewfinderView.setVisibility(View.VISIBLE);
SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view);
SurfaceHolder surfaceHolder = surfaceView.getHolder();
initCamera(surfaceHolder);
// 恢复活动监控器
inactivityTimer.onResume();
}
void closeCamera(){
if (handler != null) {
handler.quitSynchronously();
handler = null;
}
inactivityTimer.onPause();
// 关闭摄像头
cameraManager.closeDriver();
}}
在扫描出现问题事弹出dialog,当用户点击确定按钮后重新开始扫描。
private void showErrorDialog() {
closeCamera();
viewfinderView.setVisibility(View.GONE);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(getString(R.string.app_name));
builder.setMessage("扫描确认出错,请重新扫描柜子上的二维码!");
builder.setPositiveButton(android.R.string.ok, new OnClickListener() {@Override
public void onClick(DialogInterface dialog, int which) {
restartCamera();
}
});
builder.setOnCancelListener(new OnCancelListener() {@Override
public void onCancel(DialogInterface dialog) {
CaptureCodeActivity.this.finish();
}
});
builder.show();
}
closeCamera(相当于onPause)和restartCamera(onResume)方法就不贴代码了。
Demo还有个问题,就是在低分辨率上面扫描区域出现了变形,我已经修改了,改天把代码打包发出来!可以加我QQ通知我!
先把代码贴出来:
ViewfinderView.java
/*
* Copyright (C) 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/package com.haier.qr.code.zxing.view;
import java.util.Collection;
import java.util.HashSet;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
import com.google.zxing.ResultPoint;
import com.haier.cabinet.postman.R;
import com.haier.qr.code.zxing.camera.CameraManager;
/**
* This view is overlaid on top of the camera preview. It adds the viewfinder
* rectangle and partial transparency outside it, as well as the laser scanner
* animation and result points.
*
*/
public final class ViewfinderView extends View {
private static final String TAG = "ViewfinderView";
/**
* 刷新界面的时间
*/
private static final long ANIMATION_DELAY = 10L;
private static final int OPAQUE = 0xFF;
/**
* 四个绿色边角对应的长度
*/
private int ScreenRate;
/**
* 四个绿色边角对应的宽度
*/
private static final int CORNER_WIDTH = 10;
/**
* 扫描框中的中间线的宽度
*/
private static final int MIDDLE_LINE_WIDTH = 6;
/**
* 扫描框中的中间线的与扫描框左右的间隙
*/
private static final int MIDDLE_LINE_PADDING = 5;
/**
* 中间那条线每次刷新移动的距离
*/
private static final int SPEEN_DISTANCE = 5;
/**
* 手机的屏幕密度
*/
private static float density;
/**
* 字体大小
*/
private static final int TEXT_SIZE = 16;
/**
* 字体距离扫描框下面的距离
*/
private static final int TEXT_PADDING_TOP = 30;
/**
* 画笔对象的引用
*/
private Paint paint;
/**
* 中间滑动线的最顶端位置
*/
private int slideTop;
/**
* 中间滑动线的最底端位置
*/
private int slideBottom;
/**
* 将扫描的二维码拍下来,这里没有这个功能,暂时不考虑
*/
private Bitmap resultBitmap;
private final int maskColor;
private final int resultColor;
private final int resultPointColor;
private Collection<
ResultPoint>
possibleResultPoints;
private Collection<
ResultPoint>
lastPossibleResultPoints;
boolean isFirst;
private CameraManager cameraManager;
public ViewfinderView(Context context, AttributeSet attrs) {
super(context, attrs);
density = context.getResources().getDisplayMetrics().density;
//将像素转换成dp
ScreenRate = (int)(20 * density);
paint = new Paint();
Resources resources = getResources();
maskColor = resources.getColor(R.color.viewfinder_mask);
resultColor = resources.getColor(R.color.result_view);
resultPointColor = resources.getColor(R.color.possible_result_points);
possibleResultPoints = new HashSet<
ResultPoint>
(5);
} public void setCameraManager(CameraManager cameraManager) {
this.cameraManager = cameraManager;
}
@Override
public void onDraw(Canvas canvas) {
if (cameraManager == null) {
return;
// not ready yet, early draw before done configuring
}
//中间的扫描框,你要修改扫描框的大小,去CameraManager里面修改
Rect frame = cameraManager.getFramingRect();
if (frame == null) {
return;
}//初始化中间线滑动的最上边和最下边
if(!isFirst){
isFirst = true;
slideTop = frame.top;
slideBottom = frame.bottom;
}//获取屏幕的宽和高
int width = canvas.getWidth();
int height = canvas.getHeight();
paint.setColor(resultBitmap != null ? resultColor : maskColor);
//画出扫描框外面的阴影部分,共四个部分,扫描框的上面到屏幕上面,扫描框的下面到屏幕下面
//扫描框的左边面到屏幕左边,扫描框的右边到屏幕右边
canvas.drawRect(0, 0, width, frame.top, paint);
canvas.drawRect(0, frame.top, frame.left, frame.bottom + 1, paint);
canvas.drawRect(frame.right + 1, frame.top, width, frame.bottom + 1,
paint);
canvas.drawRect(0, frame.bottom + 1, width, height, paint);
if (resultBitmap != null) {
// Draw the opaque result bitmap over the scanning rectangle
paint.setAlpha(OPAQUE);
canvas.drawBitmap(resultBitmap, frame.left, frame.top, paint);
} else {//画扫描框边上的角,总共8个部分
paint.setColor(Color.GREEN);
canvas.drawRect(frame.left, frame.top, frame.left + ScreenRate,
frame.top + CORNER_WIDTH, paint);
canvas.drawRect(frame.left, frame.top, frame.left + CORNER_WIDTH, frame.top
+ ScreenRate, paint);
canvas.drawRect(frame.right - ScreenRate, frame.top, frame.right,
frame.top + CORNER_WIDTH, paint);
canvas.drawRect(frame.right - CORNER_WIDTH, frame.top, frame.right, frame.top
+ ScreenRate, paint);
canvas.drawRect(frame.left, frame.bottom - CORNER_WIDTH, frame.left
+ ScreenRate, frame.bottom, paint);
canvas.drawRect(frame.left, frame.bottom - ScreenRate,
frame.left + CORNER_WIDTH, frame.bottom, paint);
canvas.drawRect(frame.right - ScreenRate, frame.bottom - CORNER_WIDTH,
frame.right, frame.bottom, paint);
canvas.drawRect(frame.right - CORNER_WIDTH, frame.bottom - ScreenRate,
frame.right, frame.bottom, paint);
//绘制中间的线,每次刷新界面,中间的线往下移动SPEEN_DISTANCE
slideTop += SPEEN_DISTANCE;
if(slideTop >
= frame.bottom){
slideTop = frame.top;
}
canvas.drawRect(frame.left + MIDDLE_LINE_PADDING, slideTop - MIDDLE_LINE_WIDTH/2, frame.right - MIDDLE_LINE_PADDING,slideTop + MIDDLE_LINE_WIDTH/2, paint);
//画扫描框下面的字
/*paint.setColor(Color.WHITE);
paint.setTextSize(TEXT_SIZE * density);
paint.setAlpha(0x40);
paint.setTypeface(Typeface.create("System", Typeface.BOLD));
canvas.drawText(getResources().getString(R.string.scan_text), frame.left, (float) (frame.bottom + (float)TEXT_PADDING_TOP *density), paint);
*/<
span style="white-space:pre">
<
/span>
Collection<
ResultPoint>
currentPossible = possibleResultPoints;
Collection<
ResultPoint>
currentLast = lastPossibleResultPoints;
if (currentPossible.isEmpty()) {
lastPossibleResultPoints = null;
} else {
possibleResultPoints = new HashSet<
ResultPoint>
(5);
lastPossibleResultPoints = currentPossible;
paint.setAlpha(OPAQUE);
paint.setColor(resultPointColor);
for (ResultPoint point : currentPossible) {
canvas.drawCircle(frame.left + point.getX(), frame.top
+ point.getY(), 6.0f, paint);
}
}
if (currentLast != null) {
paint.setAlpha(OPAQUE / 2);
paint.setColor(resultPointColor);
for (ResultPoint point : currentLast) {
canvas.drawCircle(frame.left + point.getX(), frame.top
+ point.getY(), 3.0f, paint);
}
}//只刷新扫描框的内容,其他地方不刷新
postInvalidateDelayed(ANIMATION_DELAY, frame.left, frame.top,
frame.right, frame.bottom);
}
} public void drawViewfinder() {
resultBitmap = null;
invalidate();
} /**
* Draw a bitmap with the result points highlighted instead of the live
* scanning display.
*
* @param barcode
*An image of the decoded barcode.
*/
public void drawResultBitmap(Bitmap barcode) {
resultBitmap = barcode;
invalidate();
} public void addPossibleResultPoint(ResultPoint point) {
possibleResultPoints.add(point);
}}
有网友反馈代码不全,可以下载:http://download.csdn.net/detail/jdsjlzx/9433140
更多详见:https://github.com/jdsjlzx/Customer/tree/master/android_app/src/main/java/com/haier/qr/code
再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!http://www.captainbed.net
推荐阅读
- Android??????????????????????????????
- Android使用Retrofit技术仿微信图片上传,可以选择多张图片拍照上传
- Android 抓取LOG的几种命令
- Android-finished with non-zero exit value 2
- Android开发--WIFI实现
- Python中的运算符用法全解
- 防止过度拟合(正则化)
- R中的马尔可夫链分析
- 机器学习基础-规范