安卓怎样将安卓二维码扫描demo框canvas的内容截图

手机百度如何扫描二维码
手机百度的扫码二维码功能十分强大,不仅可以简单的扫码,还可以识别美食、服装、人脸等,当然大家用得最多的还是扫描二维码功能,那么手机百度怎么扫描二维码呢?1.进入手机百度,点击搜索框旁的【相机】图标2.点击【我知道了】3.出现扫描框,将二维码放入扫描框内4.如果二维码是网页,扫描后则打开网页5.如果二维码是APP下载,扫描后则弹出下载提示1829人阅读
相关文章:
http://blog.csdn.net/xiaanming/article/details/
下载地址:http://download.csdn.net/detail/xiaanming/5990219
首先看一下扫描界面
CaptureCodeActivity.java代码:
package com.haier.qr.
import java.io.IOE
import java.io.S
import java.util.M
import java.util.V
import android.app.A
import android.app.AlertD
import android.content.DialogI
import android.content.DialogInterface.OnCancelL
import android.content.DialogInterface.OnClickL
import android.content.I
import android.graphics.B
import android.os.B
import android.os.H
import android.text.TextU
import android.util.L
import android.view.SurfaceH
import android.view.SurfaceHolder.C
import android.view.SurfaceV
import android.view.V
import android.view.W
import android.view.WindowM
import android.widget.T
import com.google.zxing.BarcodeF
import com.google.zxing.DecodeHintT
import com.google.zxing.R
import com.haier.cabinet.customer.R;
import com.haier.cabinet.customer.activity.DeliveryBoxListA
import mon.util.AppT
import com.haier.qr.code.zxing.camera.CameraM
import com.haier.qr.code.zxing.decoding.CaptureActivityH
import com.haier.qr.code.zxing.decoding.FinishL
import com.haier.qr.code.zxing.decoding.InactivityT
import com.haier.qr.code.zxing.view.ViewfinderV
* Initial the camera
* @author jdsjlzx
public class CaptureCodeActivity extends Activity implements Callback,View.OnClickListener {
private static final String TAG = CaptureCodeActivity.class
.getSimpleName();
private CameraManager cameraM
private CaptureActivityH
private ViewfinderView viewfinderV
private boolean hasS
private Map&DecodeHintType, ?& decodeH
private Vector&BarcodeFormat& decodeF
private String characterS
private InactivityTimer inactivityT
private boolean isFlashlightO
* 声音震动管理器。如果扫描成功后可以播放一段音频,也可以震动提醒,可以通过配置来决定扫描成功后的行为。
private BeepManager beepM
* 闪光灯调节器。自动检测环境光线强弱并决定是否开启闪光灯
private AmbientLightManager ambientLightM
public CameraManager getCameraManager() {
return cameraM
/** Called when the activity is first created. */
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 =
inactivityTimer = new InactivityTimer(this);
beepManager = new BeepManager(this);
ambientLightManager = new AmbientLightManager(this);
//按钮监听事件
findViewById(R.id.capture_flashlight).setOnClickListener(this);
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);
// 防止sdk8的设备初始化预览异常
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
// Install the callback and wait for surfaceCreated() to init the
// camera.
surfaceHolder.addCallback(this);
decodeFormats =
characterSet =
// 加载声音配置,其实在BeemManager的构造器中也会调用该方法,即在onCreate的时候会调用一次
beepManager.updatePrefs();
// 启动闪光灯调节器
ambientLightManager.start(cameraManager);
// 恢复活动监控器
inactivityTimer.onResume();
protected void onPause() {
Log.d(TAG, &onPause&);
if (handler != null) {
handler.quitSynchronously();
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();
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();
//扫码完成,处理结果(跳转到箱子列表)
/*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();
/*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?&);
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();
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
public void surfaceCreated(SurfaceHolder holder) {
if (holder == null) {
Log.e(TAG,
&*** WARNING *** surfaceCreated() gave us a null surface!&);
if (!hasSurface) {
hasSurface =
initCamera(holder);
public void surfaceDestroyed(SurfaceHolder holder) {
hasSurface =
public ViewfinderView getViewfinderView() {
return viewfinderV
public Handler getHandler() {
public void drawViewfinder() {
viewfinderView.drawViewfinder();
public void onClick(View v) {
switch (v.getId()) {
case R.id.capture_flashlight:
if (isFlashlightOpen) {
cameraManager.setTorch(false); // 关闭闪光灯
isFlashlightOpen =
cameraManager.setTorch(true); // 打开闪光灯
isFlashlightOpen =
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() {
public void onClick(DialogInterface dialog, int which) {
restartCamera();
builder.setOnCancelListener(new OnCancelListener() {
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();
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() {
public void onClick(DialogInterface dialog, int which) {
restartCamera();
builder.setOnCancelListener(new OnCancelListener() {
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.
import java.util.C
import java.util.HashS
import android.content.C
import android.content.res.R
import android.graphics.B
import android.graphics.C
import android.graphics.C
import android.graphics.P
import android.graphics.R
import android.util.AttributeS
import android.view.V
import com.google.zxing.ResultP
import com.haier.cabinet.postman.R;
import com.haier.qr.code.zxing.camera.CameraM
* 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 ScreenR
* 四个绿色边角对应的宽度
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 final int TEXT_SIZE = 16;
* 字体距离扫描框下面的距离
private static final int TEXT_PADDING_TOP = 30;
* 画笔对象的引用
* 中间滑动线的最顶端位置
private int slideT
* 中间滑动线的最底端位置
private int slideB
* 将扫描的二维码拍下来,这里没有这个功能,暂时不考虑
private Bitmap resultB
private final int maskC
private final int resultC
private final int resultPointC
private Collection&ResultPoint& possibleResultP
private Collection&ResultPoint& lastPossibleResultP
boolean isF
private CameraManager cameraM
public ViewfinderView(Context context, AttributeSet attrs) {
super(context, attrs);
density = context.getResources().getDisplayMetrics().
//将像素转换成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 = cameraM
public void onDraw(Canvas canvas) {
if (cameraManager == null) {
// not ready yet, early draw before done configuring
//中间的扫描框,你要修改扫描框的大小,去CameraManager里面修改
Rect frame = cameraManager.getFramingRect();
if (frame == null) {
//初始化中间线滑动的最上边和最下边
if(!isFirst){
slideTop = frame.
slideBottom = frame.
//获取屏幕的宽和高
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,
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);
//画扫描框边上的角,总共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.
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&&
Collection&ResultPoint& currentPossible = possibleResultP
Collection&ResultPoint& currentLast = lastPossibleResultP
if (currentPossible.isEmpty()) {
lastPossibleResultPoints =
possibleResultPoints = new HashSet&ResultPoint&(5);
lastPossibleResultPoints = currentP
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 =
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 =
invalidate();
public void addPossibleResultPoint(ResultPoint point) {
possibleResultPoints.add(point);
版权声明:本文为博主原创文章,未经博主允许不得转载。
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:2295175次
积分:30161
积分:30161
排名:第79名
原创:563篇
转载:1331篇
评论:613条
(3)(12)(16)(14)(33)(27)(34)(32)(64)(51)(93)(15)(15)(18)(14)(4)(10)(9)(71)(18)(15)(26)(21)(42)(15)(13)(31)(30)(37)(24)(52)(49)(38)(55)(40)(35)(11)(20)(40)(96)(163)(48)(70)(62)(28)(34)(52)(21)(29)(52)(77)(2)(1)(3)(1)(3)(6)(1)(3)当前访客身份:游客 [
程序员看世界
目前还没有任何评论
今日访问:0
昨日访问:5
本周访问:6
本月访问:5
所有访问:3995
利用ZXING扫描二维码的分析
发表于1年前( 23:35)&&
阅读(116)&|&评论()
0人收藏此文章,
之前给公司做了一个摄影相关的应用,现在要添加二维码扫描的功能,网上找资料后,虽然已经成功集成到app里面,但是总感觉心里没底儿。所以趁这段时间不是很忙,总结一下。
之前给公司做了一个摄影相关的应用,现在要添加二维码扫描的功能,网上找资料后,虽然已经成功集成到app里面,但是总感觉心里没底儿。所以趁这段时间不是很忙,总结一下。
首先是启动扫描的UI类:
1,Activity启动,当然是onCreate方法
private&CaptureActivityHandler&
private&ViewfinderView&viewfinderV
private&boolean&hasS
private&Vector&BarcodeFormat&&decodeF
private&String&characterS
private&InactivityTimer&inactivityT
private&MediaPlayer&mediaP
private&boolean&playB
private&static&final&float&BEEP_VOLUME&=&0.10f;
private&boolean&
/**&Called&when&the&activity&is&first&created.&*/
public&void&onCreate(Bundle&savedInstanceState)&{
&&&&super.onCreate(savedInstanceState);
&&&&setContentView(R.layout.activity_capture);
&&&&//&ViewUtil.addTopView(getApplicationContext(),&this,
&&&&//&R.string.scan_card);
&&&&CameraManager.init(getApplication());
&&&&viewfinderView&=&(ViewfinderView)&findViewById(R.id.viewfinder_view);
&&&&Button&mButtonBack&=&(Button)&findViewById(R.id.button_back);
&&&&mButtonBack.setOnClickListener(new&OnClickListener()&{
&&&&&&&&@Override
&&&&&&&&public&void&onClick(View&v)&{
&&&&&&&&&&&&Scaner.this.finish();
&&&&hasSurface&=&
&&&&inactivityTimer&=&new&InactivityTimer(this);
protected&void&onResume()&{
&&&&super.onResume();
&&&&SurfaceView&surfaceView&=&(SurfaceView)&findViewById(R.id.preview_view);
&&&&SurfaceHolder&surfaceHolder&=&surfaceView.getHolder();
&&&&if&(hasSurface)&{
&&&&&&&&initCamera(surfaceHolder);
&&&&}&else&{
&&&&&&&&surfaceHolder.addCallback(this);
&&&&&&&&surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
&&&&decodeFormats&=&
&&&&characterSet&=&
&&&&playBeep&=&
&&&&AudioManager&audioService&=&(AudioManager)&getSystemService(AUDIO_SERVICE);
&&&&if&(audioService.getRingerMode()&!=&AudioManager.RINGER_MODE_NORMAL)&{
&&&&&&&&playBeep&=&
&&&&initBeepSound();
&&&&vibrate&=&
protected&void&onPause()&{
&&&&super.onPause();
&&&&if&(handler&!=&null)&{
&&&&&&&&handler.quitSynchronously();
&&&&&&&&handler&=&
&&&&CameraManager.get().closeDriver();
protected&void&onDestroy()&{
&&&&inactivityTimer.shutdown();
&&&&super.onDestroy();
*&@param&@param&result
*&@param&@param&barcode
*&@author&&Administrator
*&@return&void
public&void&handleDecode(Result&result,&Bitmap&barcode)&{
&&&&inactivityTimer.onActivity();
&&&&playBeepSoundAndVibrate();
&&&&String&resultString&=&result.getText();
&&&&if&(resultString.equals(""))&{
&&&&&&&&Toast.makeText(Scaner.this,&"Scan&failed!",3000).show();
&&&&}&else&{
&&&&&&&&//查询keycode&本地数据库&1,优先查询本地库,2,没有本地库,直接跳到知道链接
&&&&&&&&//分析出keyCode
&&&&&&&&Log.i("testMain","scan_result=====&"+resultString);
&&&&&&&&String&keyCode="";
&&&&&&&&String[]&split1;
&&&&&&&&if(resultString.lastIndexOf("?")&0){
&&&&&&&&&&&&Intent&intent&=&new&Intent(this,&InnerBrowser.class);
&&&&&&&&&&&&Bundle&bundle&=&new&Bundle();
&&&&&&&&&&&&bundle.putString("result",&resultString);
&&&&&&&&&&&&//bundle.putParcelable("bitmap",&barcode);
&&&&&&&&&&&&intent.putExtras(bundle);
&&&&&&&&&&&&startActivity(intent);Scaner.this.finish();
&&&&&&&&String[]&attr&=&resultString.substring(resultString.lastIndexOf("?")-1,&resultString.length()).split("&");
&&&&&&&&for&(String&string&:&attr)&{
&&&&&&&&&&&&&split1&=&string.split("=");
&&&&&&&&&&&&if(split1[0].equalsIgnoreCase("keycode")){
&&&&&&&&&&&&&&&&//找到
&&&&&&&&&&&&&&&&if(split1.length==2){
&&&&&&&&&&&&&&&&&&&&keyCode=split1[1];
&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&}
&&&&&&&&Log.i("testMain","keyCode=====&"+keyCode);
&&&&&&&&if(!StringUtils.isBlank(keyCode)){
&&&&&&&&&&&&AttractionDAO&dao=new&AttractionDAO(Scaner.this);
&&&&&&&&&&&&Attraction&a=dao.findAttrByKeyCode(keyCode);
&&&&&&&&&&&&Log.i("testMain","a=====&"+a);
&&&&&&&&&&&&if(a!=null){
&&&&&&&&&&&&&&&&Intent&it=new&Intent();
&&&&&&&&&&&&&&&&it.setClass(Scaner.this,&UIAttractionDetail.class);
&&&&&&&&&&&&&&&&it.putExtra("a",&a);
&&&&&&&&&&&&&&&&startActivity(it);
&&&&&&&&&&&&}else{
&&&&&&&&&&&&&&&&Intent&intent&=&new&Intent(this,&InnerBrowser.class);
&&&&&&&&&&&&&&&&Bundle&bundle&=&new&Bundle();
&&&&&&&&&&&&&&&&bundle.putString("result",&resultString);
&&&&&&&&&&&&&&&&//bundle.putParcelable("bitmap",&barcode);
&&&&&&&&&&&&&&&&intent.putExtras(bundle);
&&&&&&&&&&&&&&&&startActivity(intent);
&&&&&&&&&&&&&&&&//this.setResult(RESULT_OK,&resultIntent);
&&&&&&&&&&&&&&&&//使用内置浏览器打开网站内容
&&&&&&&&&&&&}
&&&&&&&&}else{
&&&&&&&&&&&&Intent&intent&=&new&Intent(this,&InnerBrowser.class);
&&&&&&&&&&&&Bundle&bundle&=&new&Bundle();
&&&&&&&&&&&&bundle.putString("result",&resultString);
&&&&&&&&&&&&//bundle.putParcelable("bitmap",&barcode);
&&&&&&&&&&&&intent.putExtras(bundle);
&&&&&&&&&&&&startActivity(intent);
&&&&&&&&&&&&//this.setResult(RESULT_OK,&resultIntent);
&&&&&&&&&&&&//使用内置浏览器打开网站内容
&&&&Scaner.this.finish();
private&void&initCamera(SurfaceHolder&surfaceHolder)&{
&&&&&&&&CameraManager.get().openDriver(surfaceHolder);
&&&&}&catch&(IOException&ioe)&{
&&&&}&catch&(RuntimeException&e)&{
&&&&if&(handler&==&null)&{
&&&&&&&&handler&=&new&CaptureActivityHandler(this,&decodeFormats,
&&&&&&&&&&&&&&&&characterSet);
public&void&surfaceChanged(SurfaceHolder&holder,&int&format,&int&width,
&&&&&&&&int&height)&{
public&void&surfaceCreated(SurfaceHolder&holder)&{
&&&&if&(!hasSurface)&{
&&&&&&&&hasSurface&=&
&&&&&&&&initCamera(holder);
public&void&surfaceDestroyed(SurfaceHolder&holder)&{
&&&&hasSurface&=&
public&ViewfinderView&getViewfinderView()&{
&&&&return&viewfinderV
public&Handler&getHandler()&{
&&&&return&
public&void&drawViewfinder()&{
&&&&viewfinderView.drawViewfinder();
private&void&initBeepSound()&{
&&&&if&(playBeep&&&&mediaPlayer&==&null)&{
&&&&&&&&//&The&volume&on&STREAM_SYSTEM&is&not&adjustable,&and&users&found&it
&&&&&&&&//&too&loud,
&&&&&&&&//&so&we&now&play&on&the&music&stream.
&&&&&&&&setVolumeControlStream(AudioManager.STREAM_MUSIC);
&&&&&&&&mediaPlayer&=&new&MediaPlayer();
&&&&&&&&mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
&&&&&&&&mediaPlayer.setOnCompletionListener(beepListener);
&&&&&&&&AssetFileDescriptor&file&=&getResources().openRawResourceFd(
&&&&&&&&&&&&&&&&R.raw.beep);
&&&&&&&&try&{
&&&&&&&&&&&&mediaPlayer.setDataSource(file.getFileDescriptor(),
&&&&&&&&&&&&&&&&&&&&file.getStartOffset(),&file.getLength());
&&&&&&&&&&&&file.close();
&&&&&&&&&&&&mediaPlayer.setVolume(BEEP_VOLUME,&BEEP_VOLUME);
&&&&&&&&&&&&mediaPlayer.prepare();
&&&&&&&&}&catch&(IOException&e)&{
&&&&&&&&&&&&mediaPlayer&=&
private&static&final&long&VIBRATE_DURATION&=&200L;
private&void&playBeepSoundAndVibrate()&{
&&&&if&(playBeep&&&&mediaPlayer&!=&null)&{
&&&&&&&&mediaPlayer.start();
&&&&if&(vibrate)&{
&&&&&&&&Vibrator&vibrator&=&(Vibrator)&getSystemService(VIBRATOR_SERVICE);
&&&&&&&&vibrator.vibrate(VIBRATE_DURATION);
&*&When&the&beep&has&finished&playing,&rewind&to&queue&up&another&one.
private&final&OnCompletionListener&beepListener&=&new&OnCompletionListener()&{
&&&&public&void&onCompletion(MediaPlayer&mediaPlayer)&{
&&&&&&&&mediaPlayer.seekTo(0);
从上面代码可以看出,做了三件事儿:加载布局文件;初始化了一个相机管理器;设置按钮监听,初始化了一个InactivityTimer实例;
然后,最重要的是他实现了一个CallBack函数:具体参见:&
surfaceCreated
这个方法会调用然后就初始化相机的一些参数:
前两个我们好理解,第三个是干嘛的?
我们先看布局文件:
&?xml&version="1.0"&encoding="utf-8"?&
&FrameLayout&xmlns:android="/apk/res/android"
&&&&android:layout_width="fill_parent"
&&&&&&&&android:layout_height="fill_parent"&&
&&&&&RelativeLayout
&&&&&&&&android:layout_width="fill_parent"
&&&&&&&&android:layout_height="fill_parent"&&
&&&&&&&&&SurfaceView
&&&&&&&&&&&&android:id="@+id/preview_view"
&&&&&&&&&&&&android:layout_width="fill_parent"
&&&&&&&&&&&&android:layout_height="fill_parent"
&&&&&&&&&&&&android:layout_gravity="center"&/&
&&&&&&&&&com.euc.app.scan.view.ViewfinderView
&&&&&&&&&&&&android:id="@+id/viewfinder_view"
&&&&&&&&&&&&android:layout_width="wrap_content"
&&&&&&&&&&&&android:layout_height="wrap_content"&/&
&&&&&&&&&include
&&&&&&&&&&&&android:id="@+id/include1"
&&&&&&&&&&&&android:layout_width="fill_parent"
&&&&&&&&&&&&android:layout_height="wrap_content"
&&&&&&&&&&&&android:layout_alignParentTop="true"
&&&&&&&&&&&&layout="@layout/activity_title"&/&
&&&&&/RelativeLayout&
&/FrameLayout&
可以看到里面有一个自定义的View及surfaceView,
对于我这样的初学者来说,surfaceView 是什么东西?
csdn上看到这个文章
虽然不是很明白,但是大致明白这是个什么东西了。
了解了生命周期之后,我们来看他执行的方法:
private&void&initCamera(SurfaceHolder&surfaceHolder)&{
&&&&&&&&try&{
&&&&&&&&&&&&CameraManager.get().openDriver(surfaceHolder);//配置摄像头
&&&&&&&&}&catch&(IOException&ioe)&{
&&&&&&&&&&&&
&&&&&&&&}&catch&(RuntimeException&e)&{
&&&&&&&&&&&&
&&&&&&&&if&(handler&==&null)&{
&&&&&&&&&&&&handler&=&new&CaptureActivityHandler(this,&decodeFormats,
&&&&&&&&&&&&&&&&&&&&characterSet);//初始化方法里面开启摄像头预览界面。
&&&&@Override
&&&&public&void&surfaceChanged(SurfaceHolder&holder,&int&format,&int&width,
&&&&&&&&&&&&int&height)&{
&&&&@Override
&&&&public&void&surfaceCreated(SurfaceHolder&holder)&{
&&&&&&&&if&(!hasSurface)&{
&&&&&&&&&&&&hasSurface&=&
&&&&&&&&&&&&initCamera(holder);
&&&&@Override
&&&&public&void&surfaceDestroyed(SurfaceHolder&holder)&{
&&&&&&&&hasSurface&=&
这个surfaceView 创建出来之后,其实也把摄像头的配置信息以及硬件信息初始化好了。
OK,经过上面一个oncreate以及布局文件的加载,我们已经知道,摄像头预览成功,
这个自定义的View又是干嘛的?我们继续看源码: & &
private&final&int&maskC
private&final&int&resultC
private&final&int&resultPointC
private&Collection&ResultPoint&&possibleResultP
private&Collection&ResultPoint&&lastPossibleResultP
boolean&isF
public&ViewfinderView(Context&context,&AttributeSet&attrs)&{
&&&&super(context,&attrs);
&&&&density&=&context.getResources().getDisplayMetrics().
&&&&//将像素转换成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&onDraw(Canvas&canvas)&{
&&&&//中间的扫描框,你要修改扫描框的大小,去CameraManager里面修改
&&&&Rect&frame&=&CameraManager.get().getFramingRect();
&&&&if&(frame&==&null)&{
&&&&//初始化中间线滑动的最上边和最下边
&&&&if(!isFirst){
&&&&&&&&isFirst&=&
&&&&&&&&slideTop&=&frame.
&&&&&&&&slideBottom&=&frame.
&&&&//获取屏幕的宽和高
&&&&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.
&&&&&&&&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);
&&&&&&&&Collection&ResultPoint&&currentPossible&=&possibleResultP
&&&&&&&&Collection&ResultPoint&&currentLast&=&lastPossibleResultP
&&&&&&&&if&(currentPossible.isEmpty())&{
&&&&&&&&&&&&lastPossibleResultPoints&=&
&&&&&&&&}&else&{
&&&&&&&&&&&&possibleResultPoints&=&new&HashSet&ResultPoint&(5);
&&&&&&&&&&&&lastPossibleResultPoints&=&currentP
&&&&&&&&&&&&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&=&
&&&&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&=&
&&&&invalidate();
public&void&addPossibleResultPoint(ResultPoint&point)&{
&&&&possibleResultPoints.add(point);
哦,这个就是定义了一个有动态效果的扫描界面 & &
上面的虽然代码不多,当时我们现在回忆一下步骤:
1,启动activity,加载布局文件,初始化surfaceView,初始化自定义的View(动态界面),
2,在初始化surfaceView的时候,同时初始化了摄像头的参数,初始化的handler处理器,启动了摄像头预览。
问题:那什么时候开始监听扫描二维码的呢?
初始化handler 的时候就开始监听了,看一下其构造函数: & &
public&CaptureActivityHandler(Scaner&activity,&Vector&BarcodeFormat&&decodeFormats,
&&&&&&String&characterSet)&{
&&&&this.activity&=&
&&&&decodeThread&=&new&DecodeThread(activity,&decodeFormats,&characterSet,
&&&&&&&&new&ViewfinderResultPointCallback(activity.getViewfinderView()));
&&&&decodeThread.start();
&&&&state&=&State.SUCCESS;
&&&&//&Start&ourselves&capturing&previews&and&decoding.
&&&&CameraManager.get().startPreview();
&&&&restartPreviewAndDecode();
再来一个:上面构造函数new了一个对象,这个对象就是用来监听获取扫描的图像的。
直到获取了二维码图像,调用回调函数就结束。
final&class&DecodeThread&extends&Thread&{
&&public&static&final&String&BARCODE_BITMAP&=&"barcode_bitmap";
&&private&final&Scaner&
&&private&final&Hashtable&DecodeHintType,&Object&&
&&private&Handler&
&&private&final&CountDownLatch&handlerInitL
&&DecodeThread(Scaner&activity,
&&&&&&&&&&&&&&&Vector&BarcodeFormat&&decodeFormats,
&&&&&&&&&&&&&&&String&characterSet,
&&&&&&&&&&&&&&&ResultPointCallback&resultPointCallback)&{
&&&&this.activity&=&
&&&&handlerInitLatch&=&new&CountDownLatch(1);
&&&&hints&=&new&Hashtable&DecodeHintType,&Object&(3);
&&&&if&(decodeFormats&==&null&||&decodeFormats.isEmpty())&{
&&&&&&&&&decodeFormats&=&new&Vector&BarcodeFormat&();
&&&&&&&&&decodeFormats.addAll(DecodeFormatManager.ONE_D_FORMATS);
&&&&&&&&&decodeFormats.addAll(DecodeFormatManager.QR_CODE_FORMATS);
&&&&&&&&&decodeFormats.addAll(DecodeFormatManager.DATA_MATRIX_FORMATS);
&&&&hints.put(DecodeHintType.POSSIBLE_FORMATS,&decodeFormats);
&&&&if&(characterSet&!=&null)&{
&&&&&&hints.put(DecodeHintType.CHARACTER_SET,&characterSet);
&&&&hints.put(DecodeHintType.NEED_RESULT_POINT_CALLBACK,&resultPointCallback);
&&Handler&getHandler()&{
&&&&&&handlerInitLatch.await();
&&&&}&catch&(InterruptedException&ie)&{
&&&&&&//&continue?
&&&&return&
&&@Override
&&public&void&run()&{
&&&&Looper.prepare();
&&&&handler&=&new&DecodeHandler(activity,&hints);
&&&&handlerInitLatch.countDown();
&&&&Looper.loop();
回调函数: & &
public&void&handleDecode(Result&result,&Bitmap&barcode)&{
&&&&inactivityTimer.onActivity();
&&&&playBeepSoundAndVibrate();
&&&&String&resultString&=&result.getText();
&&&&if&(resultString.equals(""))&{
&&&&&&&&Toast.makeText(Scaner.this,&"Scan&failed!",3000).show();
&&&&}&else&{&&
&&&&&&&&//扫描结果的处理。
&&&&Scaner.this.finish();
更多开发者职位上
1)">1)">1" ng-class="{current:{{currentPage==page}}}" ng-repeat="page in pages"><li class='page' ng-if="(endIndex<li class='page next' ng-if="(currentPage
相关文章阅读

我要回帖

更多关于 安卓二维码扫描demo 的文章

 

随机推荐