首页 > 代码库 > Android开发学习之基于相机扫描二维码、条形码等

Android开发学习之基于相机扫描二维码、条形码等

蛰伏半月有余,一直在准备期末考试,期间抽空研究了一些Android的源代码,现在我就把在这其中的一些收获分享给大家。

今天想分享给大家的是二维码扫描。说起二维码,大家一定不会陌生,尤其是微信火了以后,在我们的生活中几乎随处都可以看到二维码的影

子。相关科技媒体甚至把二维码当成是未来移动互联网的入口,因此研究二维码的相关技术就显得意义非凡。目前在移动开发领域,使用最为广泛的二

维码库有两个,分别是ZXing和ZBar,其中ZXing在Android开发中较为常见,而ZBar则在IOS开发中较为常见,更重要的一点是,这两个库都是开源

的,因此我们可以从源代码中获得很多有用的东西。关于ZXing,网上有很多相关的博文,我今天不想多说,我今天想说的是ZBar,你可能会说,ZBar

不是用在IOS中,怎么今天要说ZBar呢?其实我是从这两个库使用的难易程度来选择的,ZXing功能强大,但是使用起来比较繁琐,网上有很多简化的

教程,大家可以自行前去研究。相比较而言,ZBar则比较简单,使用起来容易上手,因此我们今天选择了ZBar作为我们的库来使用。

一、准备工作

下载ZBar的SDK:由于ZBar的项目托管在sourceforge,所以在这里给出下载地址:http://download.csdn.net/detail/qinyuanpei/6794713

二、导入项目

下载完成后,我们直接解压,可以看到下面的目录结构

\

打开android文件夹,我们可以找到一个Example的文件夹,这是官方给出的示例代码,我们下面的所有工作都是基于这个示例程序而来。我们

自行创建一个Android项目,并将这两个文件拷贝到我们的项目中,同时引入ZBar相关的库文件。

三、建立布局

首先建立主界面,即扫描二维码的界面,界面布局代码如下:

<!--?xml version="1.0" encoding="utf-8"?--><linearlayout android:layout_height="match_parent" android:layout_width="match_parent" android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android">  <relativelayout android:layout_height="40dp" android:layout_width="match_parent" android:background="@drawable/title_bg">        <textview android:layout_height="wrap_content" android:layout_width="wrap_content" android:textsize="18sp" android:textcolor="#ffffff" android:text="@string/Scan" android:layout_centervertical="true" android:layout_centerhorizontal="true">        <button android:id="@+id/BtnAbout" android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="@string/BtnAbout" android:layout_alignparenttop="true" android:layout_alignparentright="true">       <frameLayout    android:id="@+id/cameraPreview"    android:layout_width="match_parent"    android:layout_height="0dip"    android:layout_weight="1"/> </button></textview></relativelayout></linearlayout>
View Code

实现的布局效果如下图所示:

\

接下里,我们在来设计一个用于显示结果的界面,界面布局代码如下:

<!--?xml version="1.0" encoding="utf-8"?--><linearlayout android:layout_height="match_parent" android:layout_width="match_parent" android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android" android:background="#ffffff">    <relativelayout android:layout_height="40dp" android:layout_width="match_parent" android:background="@drawable/title_bg">        <textview android:layout_height="wrap_content" android:layout_width="wrap_content" android:textsize="18sp" android:textcolor="#ffffff" android:text="@string/Result" android:layout_centervertical="true" android:layout_centerhorizontal="true">        <button android:id="@+id/BtnBack" android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="@string/BtnBack" android:layout_alignparenttop="true" android:layout_alignparentleft="true">         <textview android:id="@+id/TextResult" android:layout_height="wrap_content" android:layout_width="match_parent" android:textcolor="#000000" android:textisselectable="true" android:layout_margin="8dp"></textview></button></textview></relativelayout></linearlayout>
View Code

实现的界面效果如图所示:

\

四、编写代码

首先我们来写一个用于扫描的相机预览视图CameraPreview,此文件由ZBar的SDK提供,这里我做了下简单的修改

package com.Android.ZBar4Android; import java.io.IOException;import android.util.Log; import android.view.SurfaceView;import android.view.SurfaceHolder; import android.annotation.SuppressLint;import android.content.Context;import android.graphics.Canvas;import android.hardware.Camera;import android.hardware.Camera.Parameters;import android.hardware.Camera.PreviewCallback;import android.hardware.Camera.AutoFocusCallback; //此类由ZBar项目的SDK提供,我做了下修改@SuppressLint("ViewConstructor")public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {         private SurfaceHolder mHolder;    private Camera mCamera;    private PreviewCallback mPreviewCallBack;    private AutoFocusCallback mAutoFocusCallBack;     public CameraPreview(Context context, Camera camera,                         PreviewCallback previewCb,                         AutoFocusCallback autoFocusCb) {        super(context);        mCamera = camera;        mPreviewCallBack = previewCb;        mAutoFocusCallBack = autoFocusCb;         /*          * 自动聚焦         * 要求API版本>9         */        Camera.Parameters parameters = camera.getParameters();        for (String f : parameters.getSupportedFocusModes()) {            if (f == Parameters.FOCUS_MODE_CONTINUOUS_PICTURE) {                parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);                mAutoFocusCallBack = null;                break;            }        }          // Install a SurfaceHolder.Callback so we get notified when the        // underlying surface is created and destroyed.        mHolder = getHolder();        mHolder.addCallback(this);         // deprecated setting, but required on Android versions prior to 3.0        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);    }      public void surfaceCreated(SurfaceHolder holder) {        // The Surface has been created, now tell the camera where to draw the preview.        try {            mCamera.setPreviewDisplay(holder);        } catch (IOException e) {            Log.d("DBG", "Error setting camera preview: " + e.getMessage());        }    }     public void surfaceDestroyed(SurfaceHolder holder) {        // Camera preview released in activity    }     public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {        /*         * If your preview can change or rotate, take care of those events here.         * Make sure to stop the preview before resizing or reformatting it.         */        if (mHolder.getSurface() == null){          // preview surface does not exist          return;        }         // stop preview before making changes        try {            mCamera.stopPreview();        } catch (Exception e){          // ignore: tried to stop a non-existent preview        }         try {            // Hard code camera surface rotation 90 degs to match Activity view in portrait            mCamera.setDisplayOrientation(90);             mCamera.setPreviewDisplay(mHolder);            mCamera.setPreviewCallback(mPreviewCallBack);            mCamera.startPreview();            mCamera.autoFocus(mAutoFocusCallBack);        } catch (Exception e){            Log.d("DBG", "Error starting camera preview: " + e.getMessage());        }    }         /*     * 绘制校准框     * 修改:秦元培     * 时间:2013年11月22日     *      */    @Override    protected void onDraw(Canvas mCanvas)     {       //这里不会写了?    }}
View Code

接下来,我们来编写主界面的逻辑代码,在这里我们需要搞清楚的几个问题有:

1、相机的获取及相机的交互处理

2、二维码图片的获取

3、二维码图片的解析

对于第一个问题,需要我们深入地了解相机的工作原理,即我们需要了解Camera类。

获取相机的代码如下:

//获取照相机的方法    public static Camera getCameraInstance()    {        Camera mCamera = null;        try        {            mCamera = Camera.open();            //没有后置摄像头,尝试打开前置摄像头*******************            if (mCamera == null)            {                Camera.CameraInfo mCameraInfo = new Camera.CameraInfo();                int cameraCount = Camera.getNumberOfCameras();                 for (int camIdx = 0; camIdx < cameraCount; camIdx++)                {                    Camera.getCameraInfo(camIdx, mCameraInfo);                     if (mCameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT)                    {                        mCamera = Camera.open(camIdx);                                            }            }        }    }        catch (Exception e)        {            e.printStackTrace();        }        return mCamera;    }
View Code

释放照相机的方法

//释放照相机    private void releaseCamera()    {        if (mCamera != null)        {            IsPreview = false;            mCamera.setPreviewCallback(null);            mCamera.release();            mCamera = null;        }    }
View Code

相机反馈的方法,即扫描到二维码后的处理

PreviewCallback previewCb = new PreviewCallback()    {        public void onPreviewFrame(byte[] data, Camera camera)        {            Camera.Parameters parameters = camera.getParameters();            //获取扫描图片的大小            Size mSize = parameters.getPreviewSize();            //构造存储图片的Image            Image mResult = new Image(mSize.width, mSize.height, "Y800");//第三个参数不知道是干嘛的            //设置Image的数据资源            mResult.setData(data);            //获取扫描结果的代码            int mResultCode = mScanner.scanImage(mResult);            //如果代码不为0,表示扫描成功            if (mResultCode != 0)            {                //停止扫描                IsPreview = false;                mCamera.setPreviewCallback(null);                mCamera.stopPreview();                //开始解析扫描图片                SymbolSet Syms = mScanner.getResults();                for (Symbol mSym : Syms)                {                    //mSym.getType()方法可以获取扫描的类型,ZBar支持多种扫描类型,这里实现了条形码、二维码、ISBN码的识别                    if (mSym.getType() == Symbol.CODE128 || mSym.getType() == Symbol.QRCODE ||                         mSym.getType() == Symbol.CODABAR || mSym.getType() == Symbol.ISBN10 ||                        mSym.getType() == Symbol.ISBN13|| mSym.getType()==Symbol.DATABAR ||                        mSym.getType()==Symbol.DATABAR_EXP || mSym.getType()==Symbol.I25)                                                  {                        //添加震动效果,提示用户扫描完成                        Vibrator mVibrator=(Vibrator)getSystemService(VIBRATOR_SERVICE);                        mVibrator.vibrate(400);                        Intent intent=new Intent(MainActivity.this,ResultActivity.class);                        intent.putExtra("ScanResult", "扫描类型:"+GetResultByCode(mSym.getType())+"\n"+ mSym.getData());                        //这里需要注意的是,getData方法才是最终返回识别结果的方法                        //但是这个方法是返回一个标识型的字符串,换言之,返回的值中包含每个字符串的含义                        //例如N代表姓名,URL代表一个Web地址等等,其它的暂时不清楚,如果可以对这个进行一个较好的分割                        //效果会更好,如果需要返回扫描的图片,可以对Image做一个合适的处理                        startActivity(intent);                        IsScanned = true;                    }                    else                    {                        //否则继续扫描                        IsScanned = false;                        mCamera.setPreviewCallback(previewCb);                        mCamera.startPreview();                        IsPreview = true;                        mCamera.autoFocus(autoFocusCB);                    }                }            }        }    };
View Code

对于第二个问题,从上面的代码中我们可以看出,Image类用于获取二维码图片,ImageScanner类用于对图片的初步解析,而图片的最终解析是在SymbolSet类和

Symbol中去实现的,由此,第三个问题得以解答。下面给出完整代码:

/* * ZBar4Android * 作者:秦元培 * 时间:2013年12月21日 * 需要解决的问题有: * 1、返回内容的正则解析 * 2、如果锁屏后打开程序会报错 * 3、没有校正框,画不出来啊,郁闷 * 4、可能会与其它相机应用冲突,如微信 * 5、条形码还是读不出来 */package com.Android.ZBar4Android; import com.Android.ZBar4Android.CameraPreview;import com.Android.ZBar4Android.R; import android.app.Activity;import android.app.AlertDialog;import android.content.DialogInterface;import android.content.Intent;import android.content.pm.ActivityInfo;import android.os.Bundle;import android.os.Handler;import android.os.Vibrator;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup.LayoutParams;import android.view.Window;import android.view.View.OnClickListener;import android.widget.FrameLayout;import android.widget.Button;import android.widget.PopupWindow;import android.hardware.Camera;import android.hardware.Camera.PreviewCallback;import android.hardware.Camera.AutoFocusCallback;import android.hardware.Camera.Size;  import net.sourceforge.zbar.ImageScanner;import net.sourceforge.zbar.Image;import net.sourceforge.zbar.Symbol;import net.sourceforge.zbar.SymbolSet;import net.sourceforge.zbar.Config; public class MainActivity extends Activity{    //关于按钮    private Button BtnAbout;    //相机    private Camera mCamera;    //预览视图    private CameraPreview mPreview;    //自动聚焦    private Handler mAutoFocusHandler;    //图片扫描器    private ImageScanner mScanner;    //弹出窗口    private PopupWindow mPopupWindow;    //是否扫描完毕    private boolean IsScanned = false;    //是否处于预览状态    private boolean IsPreview = true;    //是否显示弹出层    private boolean IsShowPopup=false;     //加载iconvlib    static    {        System.loadLibrary("iconv");    }    public void onCreate(Bundle savedInstanceState)    {        super.onCreate(savedInstanceState);        //去除标题栏        requestWindowFeature(Window.FEATURE_NO_TITLE);        setContentView(R.layout.layout_main);        //设置屏幕方向为竖屏        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);        //自动聚焦线程        mAutoFocusHandler = new Handler();        //获取相机实例        mCamera = getCameraInstance();        if(mCamera == null)        {            //在这里写下获取相机失败的代码            AlertDialog.Builder mBuilder=new AlertDialog.Builder(this);            mBuilder.setTitle("ZBar4Android");            mBuilder.setMessage("ZBar4Android获取相机失败,请重试!");            mBuilder.setPositiveButton("确定", new DialogInterface.OnClickListener()            {                 @Override                public void onClick(DialogInterface mDialogInterface, int mIndex)                 {                    MainActivity.this.finish();                }            });            AlertDialog mDialog=mBuilder.create();            mDialog.show();        }        //实例化Scanner        mScanner = new ImageScanner();        mScanner.setConfig(0, Config.X_DENSITY, 3);        mScanner.setConfig(0, Config.Y_DENSITY, 3);       //设置相机预览视图        mPreview = new CameraPreview(this, mCamera, previewCb, autoFocusCB);        FrameLayout preview = (FrameLayout)findViewById(R.id.cameraPreview);        preview.addView(mPreview);        if (IsScanned)          {             IsScanned = false;             mCamera.setPreviewCallback(previewCb);             mCamera.startPreview();             IsPreview = true;             mCamera.autoFocus(autoFocusCB);          }        //获取BtnAbout,显示程序信息        BtnAbout=(Button)findViewById(R.id.BtnAbout);        BtnAbout.setOnClickListener(new OnClickListener()        {            @Override            public void onClick(View v)            {                //如果弹出层已打开,销毁弹出层                if(IsShowPopup)                {                    mPopupWindow.dismiss();                    IsShowPopup=false;                }                else                {                    //否则显示弹出层                    mPopupWindow=new PopupWindow();                    LayoutInflater mInflater=LayoutInflater.from(getApplicationContext());                    View view=mInflater.inflate(R.layout.layout_about, null);                    mPopupWindow.setContentView(view);                    mPopupWindow.setWidth(LayoutParams.WRAP_CONTENT);                    mPopupWindow.setHeight(LayoutParams.WRAP_CONTENT);                    mPopupWindow.showAtLocation(mPreview, 0, 100, 100);                    IsShowPopup=true;                }            }         });    }    //实现Pause方法    public void onPause()    {        super.onPause();        releaseCamera();    }    //获取照相机的方法    public static Camera getCameraInstance()    {        Camera mCamera = null;        try        {            mCamera = Camera.open();            //没有后置摄像头,尝试打开前置摄像头*******************            if (mCamera == null)            {                Camera.CameraInfo mCameraInfo = new Camera.CameraInfo();                int cameraCount = Camera.getNumberOfCameras();                 for (int camIdx = 0; camIdx < cameraCount; camIdx++)                {                    Camera.getCameraInfo(camIdx, mCameraInfo);                     if (mCameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT)                    {                        mCamera = Camera.open(camIdx);                                            }            }        }    }        catch (Exception e)        {            e.printStackTrace();        }        return mCamera;    }     //释放照相机    private void releaseCamera()    {        if (mCamera != null)        {            IsPreview = false;            mCamera.setPreviewCallback(null);            mCamera.release();            mCamera = null;        }    }     private Runnable doAutoFocus = new Runnable()    {        public void run()        {            if (IsPreview)                mCamera.autoFocus(autoFocusCB);        }    };     PreviewCallback previewCb = new PreviewCallback()    {        public void onPreviewFrame(byte[] data, Camera camera)        {            Camera.Parameters parameters = camera.getParameters();            //获取扫描图片的大小            Size mSize = parameters.getPreviewSize();            //构造存储图片的Image            Image mResult = new Image(mSize.width, mSize.height, "Y800");//第三个参数不知道是干嘛的            //设置Image的数据资源            mResult.setData(data);            //获取扫描结果的代码            int mResultCode = mScanner.scanImage(mResult);            //如果代码不为0,表示扫描成功            if (mResultCode != 0)            {                //停止扫描                IsPreview = false;                mCamera.setPreviewCallback(null);                mCamera.stopPreview();                //开始解析扫描图片                SymbolSet Syms = mScanner.getResults();                for (Symbol mSym : Syms)                {                    //mSym.getType()方法可以获取扫描的类型,ZBar支持多种扫描类型,这里实现了条形码、二维码、ISBN码的识别                    if (mSym.getType() == Symbol.CODE128 || mSym.getType() == Symbol.QRCODE ||                         mSym.getType() == Symbol.CODABAR || mSym.getType() == Symbol.ISBN10 ||                        mSym.getType() == Symbol.ISBN13|| mSym.getType()==Symbol.DATABAR ||                        mSym.getType()==Symbol.DATABAR_EXP || mSym.getType()==Symbol.I25)                                                  {                        //添加震动效果,提示用户扫描完成                        Vibrator mVibrator=(Vibrator)getSystemService(VIBRATOR_SERVICE);                        mVibrator.vibrate(400);                        Intent intent=new Intent(MainActivity.this,ResultActivity.class);                        intent.putExtra("ScanResult", "扫描类型:"+GetResultByCode(mSym.getType())+"\n"+ mSym.getData());                        //这里需要注意的是,getData方法才是最终返回识别结果的方法                        //但是这个方法是返回一个标识型的字符串,换言之,返回的值中包含每个字符串的含义                        //例如N代表姓名,URL代表一个Web地址等等,其它的暂时不清楚,如果可以对这个进行一个较好的分割                        //效果会更好,如果需要返回扫描的图片,可以对Image做一个合适的处理                        startActivity(intent);                        IsScanned = true;                    }                    else                    {                        //否则继续扫描                        IsScanned = false;                        mCamera.setPreviewCallback(previewCb);                        mCamera.startPreview();                        IsPreview = true;                        mCamera.autoFocus(autoFocusCB);                    }                }            }        }    };     //用于刷新自动聚焦的方法    AutoFocusCallback autoFocusCB = new AutoFocusCallback()    {        public void onAutoFocus(boolean success, Camera camera)        {            mAutoFocusHandler.postDelayed(doAutoFocus, 1000);        }    };         //根据返回的代码值来返回相应的格式化数据    public String GetResultByCode(int CodeType)    {        String mResult="";        switch(CodeType)        {          //条形码          case Symbol.CODABAR:              mResult="条形码";              break;          //128编码格式二维码)          case Symbol.CODE128:              mResult="二维码";              break;          //QR码二维码          case Symbol.QRCODE:              mResult="二维码";              break;          //ISBN10图书查询          case Symbol.ISBN10:              mResult="图书ISBN号";              break;          //ISBN13图书查询          case Symbol.ISBN13:              mResult="图书ISBN号";              break;        }        return mResult;    }       }/* * ZBar4Android * 作者:秦元培 * 时间:2013年12月21日 * 需要解决的问题有: * 1、返回内容的正则解析 * 2、如果锁屏后打开程序会报错 * 3、没有校正框,画不出来啊,郁闷 * 4、可能会与其它相机应用冲突,如微信 * 5、条形码还是读不出来 */package com.Android.ZBar4Android; import com.Android.ZBar4Android.CameraPreview;import com.Android.ZBar4Android.R; import android.app.Activity;import android.app.AlertDialog;import android.content.DialogInterface;import android.content.Intent;import android.content.pm.ActivityInfo;import android.os.Bundle;import android.os.Handler;import android.os.Vibrator;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup.LayoutParams;import android.view.Window;import android.view.View.OnClickListener;import android.widget.FrameLayout;import android.widget.Button;import android.widget.PopupWindow;import android.hardware.Camera;import android.hardware.Camera.PreviewCallback;import android.hardware.Camera.AutoFocusCallback;import android.hardware.Camera.Size;  import net.sourceforge.zbar.ImageScanner;import net.sourceforge.zbar.Image;import net.sourceforge.zbar.Symbol;import net.sourceforge.zbar.SymbolSet;import net.sourceforge.zbar.Config; public class MainActivity extends Activity{    //关于按钮    private Button BtnAbout;    //相机    private Camera mCamera;    //预览视图    private CameraPreview mPreview;    //自动聚焦    private Handler mAutoFocusHandler;    //图片扫描器    private ImageScanner mScanner;    //弹出窗口    private PopupWindow mPopupWindow;    //是否扫描完毕    private boolean IsScanned = false;    //是否处于预览状态    private boolean IsPreview = true;    //是否显示弹出层    private boolean IsShowPopup=false;     //加载iconvlib    static    {        System.loadLibrary("iconv");    }    public void onCreate(Bundle savedInstanceState)    {        super.onCreate(savedInstanceState);        //去除标题栏        requestWindowFeature(Window.FEATURE_NO_TITLE);        setContentView(R.layout.layout_main);        //设置屏幕方向为竖屏        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);        //自动聚焦线程        mAutoFocusHandler = new Handler();        //获取相机实例        mCamera = getCameraInstance();        if(mCamera == null)        {            //在这里写下获取相机失败的代码            AlertDialog.Builder mBuilder=new AlertDialog.Builder(this);            mBuilder.setTitle("ZBar4Android");            mBuilder.setMessage("ZBar4Android获取相机失败,请重试!");            mBuilder.setPositiveButton("确定", new DialogInterface.OnClickListener()            {                 @Override                public void onClick(DialogInterface mDialogInterface, int mIndex)                 {                    MainActivity.this.finish();                }            });            AlertDialog mDialog=mBuilder.create();            mDialog.show();        }        //实例化Scanner        mScanner = new ImageScanner();        mScanner.setConfig(0, Config.X_DENSITY, 3);        mScanner.setConfig(0, Config.Y_DENSITY, 3);       //设置相机预览视图        mPreview = new CameraPreview(this, mCamera, previewCb, autoFocusCB);        FrameLayout preview = (FrameLayout)findViewById(R.id.cameraPreview);        preview.addView(mPreview);        if (IsScanned)          {             IsScanned = false;             mCamera.setPreviewCallback(previewCb);             mCamera.startPreview();             IsPreview = true;             mCamera.autoFocus(autoFocusCB);          }        //获取BtnAbout,显示程序信息        BtnAbout=(Button)findViewById(R.id.BtnAbout);        BtnAbout.setOnClickListener(new OnClickListener()        {            @Override            public void onClick(View v)            {                //如果弹出层已打开,销毁弹出层                if(IsShowPopup)                {                    mPopupWindow.dismiss();                    IsShowPopup=false;                }                else                {                    //否则显示弹出层                    mPopupWindow=new PopupWindow();                    LayoutInflater mInflater=LayoutInflater.from(getApplicationContext());                    View view=mInflater.inflate(R.layout.layout_about, null);                    mPopupWindow.setContentView(view);                    mPopupWindow.setWidth(LayoutParams.WRAP_CONTENT);                    mPopupWindow.setHeight(LayoutParams.WRAP_CONTENT);                    mPopupWindow.showAtLocation(mPreview, 0, 100, 100);                    IsShowPopup=true;                }            }         });    }    //实现Pause方法    public void onPause()    {        super.onPause();        releaseCamera();    }    //获取照相机的方法    public static Camera getCameraInstance()    {        Camera mCamera = null;        try        {            mCamera = Camera.open();            //没有后置摄像头,尝试打开前置摄像头*******************            if (mCamera == null)            {                Camera.CameraInfo mCameraInfo = new Camera.CameraInfo();                int cameraCount = Camera.getNumberOfCameras();                 for (int camIdx = 0; camIdx < cameraCount; camIdx++)                {                    Camera.getCameraInfo(camIdx, mCameraInfo);                     if (mCameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT)                    {                        mCamera = Camera.open(camIdx);                                            }            }        }    }        catch (Exception e)        {            e.printStackTrace();        }        return mCamera;    }     //释放照相机    private void releaseCamera()    {        if (mCamera != null)        {            IsPreview = false;            mCamera.setPreviewCallback(null);            mCamera.release();            mCamera = null;        }    }     private Runnable doAutoFocus = new Runnable()    {        public void run()        {            if (IsPreview)                mCamera.autoFocus(autoFocusCB);        }    };     PreviewCallback previewCb = new PreviewCallback()    {        public void onPreviewFrame(byte[] data, Camera camera)        {            Camera.Parameters parameters = camera.getParameters();            //获取扫描图片的大小            Size mSize = parameters.getPreviewSize();            //构造存储图片的Image            Image mResult = new Image(mSize.width, mSize.height, "Y800");//第三个参数不知道是干嘛的            //设置Image的数据资源            mResult.setData(data);            //获取扫描结果的代码            int mResultCode = mScanner.scanImage(mResult);            //如果代码不为0,表示扫描成功            if (mResultCode != 0)            {                //停止扫描                IsPreview = false;                mCamera.setPreviewCallback(null);                mCamera.stopPreview();                //开始解析扫描图片                SymbolSet Syms = mScanner.getResults();                for (Symbol mSym : Syms)                {                    //mSym.getType()方法可以获取扫描的类型,ZBar支持多种扫描类型,这里实现了条形码、二维码、ISBN码的识别                    if (mSym.getType() == Symbol.CODE128 || mSym.getType() == Symbol.QRCODE ||                         mSym.getType() == Symbol.CODABAR || mSym.getType() == Symbol.ISBN10 ||                        mSym.getType() == Symbol.ISBN13|| mSym.getType()==Symbol.DATABAR ||                        mSym.getType()==Symbol.DATABAR_EXP || mSym.getType()==Symbol.I25)                                                  {                        //添加震动效果,提示用户扫描完成                        Vibrator mVibrator=(Vibrator)getSystemService(VIBRATOR_SERVICE);                        mVibrator.vibrate(400);                        Intent intent=new Intent(MainActivity.this,ResultActivity.class);                        intent.putExtra("ScanResult", "扫描类型:"+GetResultByCode(mSym.getType())+"\n"+ mSym.getData());                        //这里需要注意的是,getData方法才是最终返回识别结果的方法                        //但是这个方法是返回一个标识型的字符串,换言之,返回的值中包含每个字符串的含义                        //例如N代表姓名,URL代表一个Web地址等等,其它的暂时不清楚,如果可以对这个进行一个较好的分割                        //效果会更好,如果需要返回扫描的图片,可以对Image做一个合适的处理                        startActivity(intent);                        IsScanned = true;                    }                    else                    {                        //否则继续扫描                        IsScanned = false;                        mCamera.setPreviewCallback(previewCb);                        mCamera.startPreview();                        IsPreview = true;                        mCamera.autoFocus(autoFocusCB);                    }                }            }        }    };     //用于刷新自动聚焦的方法    AutoFocusCallback autoFocusCB = new AutoFocusCallback()    {        public void onAutoFocus(boolean success, Camera camera)        {            mAutoFocusHandler.postDelayed(doAutoFocus, 1000);        }    };         //根据返回的代码值来返回相应的格式化数据    public String GetResultByCode(int CodeType)    {        String mResult="";        switch(CodeType)        {          //条形码          case Symbol.CODABAR:              mResult="条形码";              break;          //128编码格式二维码)          case Symbol.CODE128:              mResult="二维码";              break;          //QR码二维码          case Symbol.QRCODE:              mResult="二维码";              break;          //ISBN10图书查询          case Symbol.ISBN10:              mResult="图书ISBN号";              break;          //ISBN13图书查询          case Symbol.ISBN13:              mResult="图书ISBN号";              break;        }        return mResult;    }       }
View Code

对于显示扫描结果的界面,代码比较简单

/* * 返回扫描结果 * 作者:秦元培 * 时间:2013年12月21日 * 总结:这里有一个问题,就是在这个界面上按下返回键的时候程序会立即报错,试着重写过相关的方法都解决不了问题 * 谁要是知道这个问题怎么解决,记得给我说一声啊 */package com.Android.ZBar4Android; import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.view.Window;import android.widget.Button;import android.widget.TextView; public class ResultActivity extends Activity {     private TextView tv;    private Button BtnBack;    @Override    protected void onCreate(Bundle savedInstanceState)     {        super.onCreate(savedInstanceState);        requestWindowFeature(Window.FEATURE_NO_TITLE);        setContentView(R.layout.layout_result);        //获取扫描结果        Intent intent=getIntent();        Bundle mData=intent.getExtras();        CharSequence mResult=mData.getCharSequence("ScanResult");        StringHelper mHelper=new StringHelper(mResult.toString());        mResult=mHelper.SplitFormDict();        tv=(TextView)findViewById(R.id.TextResult);        tv.setText(mResult);        //返回扫描界面        BtnBack=(Button)findViewById(R.id.BtnBack);        BtnBack.setOnClickListener(new OnClickListener()        {            @Override            public void onClick(View arg0)             {                Intent intent=new Intent(ResultActivity.this,MainActivity.class);                startActivity(intent);            }                     });    }         @Override    protected void onPause()     {        super.onPause();    }     }
View Code

五、总结

经过测试,可以快速地对二维码进行识别,并显示扫描结果。目前尚存在的问题有:

1、官方的文档说它是支持条形码、ISBN、二维码等多种形式的编码的,并且在程序代码中亦有所体现,但是实际测试中,发现二维码可以扫,其余的无法扫描

2、锁屏后再次打开程序会报错

3、与微信等类似的需要相机功能的软件冲突

4、校准框死活画不出来

5、在扫描结果界面下按下返回键,程序报错,无法拦截

欢迎大家积极寻找解决问题的方法,再次谢谢大家!

源代码下载

\

Android开发学习之基于相机扫描二维码、条形码等