蛰伏半月有余,一直在准备期末考试,期间抽空研究了一些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相关的库文件。


                三、建立布局

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

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout  
  3.   xmlns:android="http://schemas.android.com/apk/res/android"  
  4.   android:orientation="vertical"  
  5.   android:layout_width="match_parent"  
  6.   android:layout_height="match_parent">  
  7.   <RelativeLayout  
  8.         android:layout_width="match_parent"  
  9.         android:layout_height="40dp"  
  10.         android:background="@drawable/title_bg" >  
  11.         <TextView  
  12.             android:layout_width="wrap_content"  
  13.             android:layout_height="wrap_content"  
  14.             android:layout_centerHorizontal="true"  
  15.             android:layout_centerVertical="true"  
  16.             android:text="@string/Scan"  
  17.             android:textColor="#ffffff"  
  18.             android:textSize="18sp" />  
  19.         <Button  
  20.             android:id="@+id/BtnAbout"  
  21.             android:layout_width="wrap_content"  
  22.             android:layout_height="wrap_content"  
  23.             android:layout_alignParentRight="true"  
  24.             android:layout_alignParentTop="true"  
  25.             android:text="@string/BtnAbout" />  
  26.     </RelativeLayout>  
  27.   <FrameLayout  
  28.     android:id="@+id/cameraPreview"  
  29.     android:layout_width="match_parent"  
  30.     android:layout_height="0dip"  
  31.     android:layout_weight="1"/>  
  32. </LinearLayout>  

                 

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

                


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

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:background="#ffffff"  
  6.     android:orientation="vertical" >  
  7.     <RelativeLayout  
  8.         android:layout_width="match_parent"  
  9.         android:layout_height="40dp"  
  10.         android:background="@drawable/title_bg" >  
  11.         <TextView  
  12.             android:layout_width="wrap_content"  
  13.             android:layout_height="wrap_content"  
  14.             android:layout_centerHorizontal="true"  
  15.             android:layout_centerVertical="true"  
  16.             android:textSize="18sp"  
  17.             android:textColor="#ffffff"  
  18.             android:text="@string/Result" />  
  19.         <Button  
  20.             android:id="@+id/BtnBack"  
  21.             android:layout_width="wrap_content"  
  22.             android:layout_height="wrap_content"  
  23.             android:layout_alignParentLeft="true"  
  24.             android:layout_alignParentTop="true"  
  25.             android:text="@string/BtnBack" />  
  26.     </RelativeLayout>  
  27.     <TextView  
  28.         android:id="@+id/TextResult"  
  29.         android:layout_width="match_parent"  
  30.         android:layout_height="wrap_content"  
  31.         android:textColor="#000000"  
  32.         android:layout_margin="8dp"  
  33.         android:textIsSelectable="true"/>  
  34. </LinearLayout>  

                

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

               


              四、编写代码

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

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package com.Android.ZBar4Android;  
  2.   
  3. import java.io.IOException;  
  4. import android.util.Log;  
  5.   
  6. import android.view.SurfaceView;  
  7. import android.view.SurfaceHolder;  
  8.   
  9. import android.annotation.SuppressLint;  
  10. import android.content.Context;  
  11. import android.graphics.Canvas;  
  12. import android.hardware.Camera;  
  13. import android.hardware.Camera.Parameters;  
  14. import android.hardware.Camera.PreviewCallback;  
  15. import android.hardware.Camera.AutoFocusCallback;  
  16.   
  17. //此类由ZBar项目的SDK提供,我做了下修改  
  18. @SuppressLint("ViewConstructor")  
  19. public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback   
  20. {  
  21.       
  22.     private SurfaceHolder mHolder;  
  23.     private Camera mCamera;  
  24.     private PreviewCallback mPreviewCallBack;  
  25.     private AutoFocusCallback mAutoFocusCallBack;  
  26.   
  27.     public CameraPreview(Context context, Camera camera,  
  28.                          PreviewCallback previewCb,  
  29.                          AutoFocusCallback autoFocusCb) {  
  30.         super(context);  
  31.         mCamera = camera;  
  32.         mPreviewCallBack = previewCb;  
  33.         mAutoFocusCallBack = autoFocusCb;  
  34.   
  35.         /*  
  36.          * 自动聚焦 
  37.          * 要求API版本>9 
  38.          */  
  39.         Camera.Parameters parameters = camera.getParameters();  
  40.         for (String f : parameters.getSupportedFocusModes()) {  
  41.             if (f == Parameters.FOCUS_MODE_CONTINUOUS_PICTURE) {  
  42.                 parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);  
  43.                 mAutoFocusCallBack = null;  
  44.                 break;  
  45.             }  
  46.         }  
  47.   
  48.   
  49.         // Install a SurfaceHolder.Callback so we get notified when the  
  50.         // underlying surface is created and destroyed.  
  51.         mHolder = getHolder();  
  52.         mHolder.addCallback(this);  
  53.   
  54.         // deprecated setting, but required on Android versions prior to 3.0  
  55.         mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);  
  56.     }  
  57.   
  58.   
  59.     public void surfaceCreated(SurfaceHolder holder) {  
  60.         // The Surface has been created, now tell the camera where to draw the preview.  
  61.         try {  
  62.             mCamera.setPreviewDisplay(holder);  
  63.         } catch (IOException e) {  
  64.             Log.d("DBG""Error setting camera preview: " + e.getMessage());  
  65.         }  
  66.     }  
  67.   
  68.     public void surfaceDestroyed(SurfaceHolder holder) {  
  69.         // Camera preview released in activity  
  70.     }  
  71.   
  72.     public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {  
  73.         /* 
  74.          * If your preview can change or rotate, take care of those events here. 
  75.          * Make sure to stop the preview before resizing or reformatting it. 
  76.          */  
  77.         if (mHolder.getSurface() == null){  
  78.           // preview surface does not exist  
  79.           return;  
  80.         }  
  81.   
  82.         // stop preview before making changes  
  83.         try {  
  84.             mCamera.stopPreview();  
  85.         } catch (Exception e){  
  86.           // ignore: tried to stop a non-existent preview  
  87.         }  
  88.   
  89.         try {  
  90.             // Hard code camera surface rotation 90 degs to match Activity view in portrait  
  91.             mCamera.setDisplayOrientation(90);  
  92.   
  93.             mCamera.setPreviewDisplay(mHolder);  
  94.             mCamera.setPreviewCallback(mPreviewCallBack);  
  95.             mCamera.startPreview();  
  96.             mCamera.autoFocus(mAutoFocusCallBack);  
  97.         } catch (Exception e){  
  98.             Log.d("DBG""Error starting camera preview: " + e.getMessage());  
  99.         }  
  100.     }  
  101.       
  102.     /* 
  103.      * 绘制校准框 
  104.      * 修改:秦元培 
  105.      * 时间:2013年11月22日 
  106.      *  
  107.      */  
  108.     @Override  
  109.     protected void onDraw(Canvas mCanvas)   
  110.     {  
  111.        //这里不会写了?  
  112.     }  
  113. }  

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

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

               2、二维码图片的获取

               3、二维码图片的解析

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

                获取相机的代码如下:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. //获取照相机的方法  
  2.     public static Camera getCameraInstance()  
  3.     {  
  4.         Camera mCamera = null;  
  5.         try  
  6.         {  
  7.             mCamera = Camera.open();  
  8.             //没有后置摄像头,尝试打开前置摄像头*******************  
  9.             if (mCamera == null)  
  10.             {  
  11.                 Camera.CameraInfo mCameraInfo = new Camera.CameraInfo();  
  12.                 int cameraCount = Camera.getNumberOfCameras();   
  13.                 for (int camIdx = 0; camIdx < cameraCount; camIdx++)  
  14.                 {  
  15.                     Camera.getCameraInfo(camIdx, mCameraInfo);   
  16.                     if (mCameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT)  
  17.                     {  
  18.                         mCamera = Camera.open(camIdx);                          
  19.                     }  
  20.             }  
  21.         }  
  22.     }  
  23.         catch (Exception e)  
  24.         {  
  25.             e.printStackTrace();  
  26.         }  
  27.         return mCamera;  
  28.     }  
               

               释放照相机的方法

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. //释放照相机  
  2.     private void releaseCamera()  
  3.     {  
  4.         if (mCamera != null)  
  5.         {  
  6.             IsPreview = false;  
  7.             mCamera.setPreviewCallback(null);  
  8.             mCamera.release();  
  9.             mCamera = null;  
  10.         }  
  11.     }  


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

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. PreviewCallback previewCb = new PreviewCallback()  
  2.     {  
  3.         public void onPreviewFrame(byte[] data, Camera camera)  
  4.         {  
  5.             Camera.Parameters parameters = camera.getParameters();  
  6.             //获取扫描图片的大小  
  7.             Size mSize = parameters.getPreviewSize();  
  8.             //构造存储图片的Image  
  9.             Image mResult = new Image(mSize.width, mSize.height, "Y800");//第三个参数不知道是干嘛的  
  10.             //设置Image的数据资源  
  11.             mResult.setData(data);  
  12.             //获取扫描结果的代码  
  13.             int mResultCode = mScanner.scanImage(mResult);  
  14.             //如果代码不为0,表示扫描成功  
  15.             if (mResultCode != 0)  
  16.             {  
  17.                 //停止扫描  
  18.                 IsPreview = false;  
  19.                 mCamera.setPreviewCallback(null);  
  20.                 mCamera.stopPreview();  
  21.                 //开始解析扫描图片  
  22.                 SymbolSet Syms = mScanner.getResults();  
  23.                 for (Symbol mSym : Syms)  
  24.                 {  
  25.                     //mSym.getType()方法可以获取扫描的类型,ZBar支持多种扫描类型,这里实现了条形码、二维码、ISBN码的识别  
  26.                     if (mSym.getType() == Symbol.CODE128 || mSym.getType() == Symbol.QRCODE ||   
  27.                         mSym.getType() == Symbol.CODABAR || mSym.getType() == Symbol.ISBN10 ||  
  28.                         mSym.getType() == Symbol.ISBN13|| mSym.getType()==Symbol.DATABAR ||  
  29.                         mSym.getType()==Symbol.DATABAR_EXP || mSym.getType()==Symbol.I25)  
  30.                                
  31.                     {  
  32.                         //添加震动效果,提示用户扫描完成  
  33.                         Vibrator mVibrator=(Vibrator)getSystemService(VIBRATOR_SERVICE);  
  34.                         mVibrator.vibrate(400);  
  35.                         Intent intent=new Intent(MainActivity.this,ResultActivity.class);  
  36.                         intent.putExtra("ScanResult""扫描类型:"+GetResultByCode(mSym.getType())+"\n"+ mSym.getData());  
  37.                         //这里需要注意的是,getData方法才是最终返回识别结果的方法  
  38.                         //但是这个方法是返回一个标识型的字符串,换言之,返回的值中包含每个字符串的含义  
  39.                         //例如N代表姓名,URL代表一个Web地址等等,其它的暂时不清楚,如果可以对这个进行一个较好的分割  
  40.                         //效果会更好,如果需要返回扫描的图片,可以对Image做一个合适的处理  
  41.                         startActivity(intent);  
  42.                         IsScanned = true;  
  43.                     }  
  44.                     else  
  45.                     {  
  46.                         //否则继续扫描  
  47.                         IsScanned = false;  
  48.                         mCamera.setPreviewCallback(previewCb);  
  49.                         mCamera.startPreview();  
  50.                         IsPreview = true;  
  51.                         mCamera.autoFocus(autoFocusCB);  
  52.                     }  
  53.                 }  
  54.             }  
  55.         }  
  56.     };  

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

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

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /* 
  2.  * ZBar4Android 
  3.  * 作者:秦元培 
  4.  * 时间:2013年12月21日 
  5.  * 需要解决的问题有: 
  6.  * 1、返回内容的正则解析 
  7.  * 2、如果锁屏后打开程序会报错 
  8.  * 3、没有校正框,画不出来啊,郁闷 
  9.  * 4、可能会与其它相机应用冲突,如微信 
  10.  * 5、条形码还是读不出来 
  11.  */  
  12. package com.Android.ZBar4Android;  
  13.   
  14. import com.Android.ZBar4Android.CameraPreview;  
  15. import com.Android.ZBar4Android.R;  
  16.   
  17. import android.app.Activity;  
  18. import android.app.AlertDialog;  
  19. import android.content.DialogInterface;  
  20. import android.content.Intent;  
  21. import android.content.pm.ActivityInfo;  
  22. import android.os.Bundle;  
  23. import android.os.Handler;  
  24. import android.os.Vibrator;  
  25. import android.view.LayoutInflater;  
  26. import android.view.View;  
  27. import android.view.ViewGroup.LayoutParams;  
  28. import android.view.Window;  
  29. import android.view.View.OnClickListener;  
  30. import android.widget.FrameLayout;  
  31. import android.widget.Button;  
  32. import android.widget.PopupWindow;  
  33. import android.hardware.Camera;  
  34. import android.hardware.Camera.PreviewCallback;  
  35. import android.hardware.Camera.AutoFocusCallback;  
  36. import android.hardware.Camera.Size;  
  37.    
  38. import net.sourceforge.zbar.ImageScanner;  
  39. import net.sourceforge.zbar.Image;  
  40. import net.sourceforge.zbar.Symbol;  
  41. import net.sourceforge.zbar.SymbolSet;  
  42. import net.sourceforge.zbar.Config;  
  43.   
  44. public class MainActivity extends Activity  
  45. {  
  46.     //关于按钮  
  47.     private Button BtnAbout;  
  48.     //相机  
  49.     private Camera mCamera;  
  50.     //预览视图  
  51.     private CameraPreview mPreview;  
  52.     //自动聚焦  
  53.     private Handler mAutoFocusHandler;  
  54.     //图片扫描器  
  55.     private ImageScanner mScanner;  
  56.     //弹出窗口  
  57.     private PopupWindow mPopupWindow;  
  58.     //是否扫描完毕  
  59.     private boolean IsScanned = false;  
  60.     //是否处于预览状态  
  61.     private boolean IsPreview = true;  
  62.     //是否显示弹出层  
  63.     private boolean IsShowPopup=false;  
  64.   
  65.     //加载iconvlib  
  66.     static  
  67.     {  
  68.         System.loadLibrary("iconv");  
  69.     }  
  70.     public void onCreate(Bundle savedInstanceState)  
  71.     {  
  72.         super.onCreate(savedInstanceState);  
  73.         //去除标题栏  
  74.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  75.         setContentView(R.layout.layout_main);  
  76.         //设置屏幕方向为竖屏  
  77.         setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);  
  78.         //自动聚焦线程  
  79.         mAutoFocusHandler = new Handler();  
  80.         //获取相机实例  
  81.         mCamera = getCameraInstance();  
  82.         if(mCamera == null)  
  83.         {  
  84.             //在这里写下获取相机失败的代码  
  85.             AlertDialog.Builder mBuilder=new AlertDialog.Builder(this);  
  86.             mBuilder.setTitle("ZBar4Android");  
  87.             mBuilder.setMessage("ZBar4Android获取相机失败,请重试!");  
  88.             mBuilder.setPositiveButton("确定"new DialogInterface.OnClickListener()  
  89.             {  
  90.   
  91.                 @Override  
  92.                 public void onClick(DialogInterface mDialogInterface, int mIndex)   
  93.                 {  
  94.                     MainActivity.this.finish();  
  95.                 }  
  96.             });  
  97.             AlertDialog mDialog=mBuilder.create();  
  98.             mDialog.show();  
  99.         }  
  100.         //实例化Scanner  
  101.         mScanner = new ImageScanner();  
  102.         mScanner.setConfig(0, Config.X_DENSITY, 3);  
  103.         mScanner.setConfig(0, Config.Y_DENSITY, 3);  
  104.        //设置相机预览视图  
  105.         mPreview = new CameraPreview(this, mCamera, previewCb, autoFocusCB);  
  106.         FrameLayout preview = (FrameLayout)findViewById(R.id.cameraPreview);  
  107.         preview.addView(mPreview);  
  108.         if (IsScanned)  
  109.           {  
  110.              IsScanned = false;  
  111.              mCamera.setPreviewCallback(previewCb);  
  112.              mCamera.startPreview();  
  113.              IsPreview = true;  
  114.              mCamera.autoFocus(autoFocusCB);  
  115.           }  
  116.         //获取BtnAbout,显示程序信息  
  117.         BtnAbout=(Button)findViewById(R.id.BtnAbout);  
  118.         BtnAbout.setOnClickListener(new OnClickListener()  
  119.         {  
  120.             @Override  
  121.             public void onClick(View v)  
  122.             {  
  123.                 //如果弹出层已打开,销毁弹出层  
  124.                 if(IsShowPopup)  
  125.                 {  
  126.                     mPopupWindow.dismiss();  
  127.                     IsShowPopup=false;  
  128.                 }  
  129.                 else  
  130.                 {  
  131.                     //否则显示弹出层  
  132.                     mPopupWindow=new PopupWindow();  
  133.                     LayoutInflater mInflater=LayoutInflater.from(getApplicationContext());  
  134.                     View view=mInflater.inflate(R.layout.layout_about, null);  
  135.                     mPopupWindow.setContentView(view);  
  136.                     mPopupWindow.setWidth(LayoutParams.WRAP_CONTENT);  
  137.                     mPopupWindow.setHeight(LayoutParams.WRAP_CONTENT);  
  138.                     mPopupWindow.showAtLocation(mPreview, 0100100);  
  139.                     IsShowPopup=true;  
  140.                 }  
  141.             }   
  142.         });  
  143.     }  
  144.     //实现Pause方法  
  145.     public void onPause()  
  146.     {  
  147.         super.onPause();  
  148.         releaseCamera();  
  149.     }  
  150.     //获取照相机的方法  
  151.     public static Camera getCameraInstance()  
  152.     {  
  153.         Camera mCamera = null;  
  154.         try  
  155.         {  
  156.             mCamera = Camera.open();  
  157.             //没有后置摄像头,尝试打开前置摄像头*******************  
  158.             if (mCamera == null)  
  159.             {  
  160.                 Camera.CameraInfo mCameraInfo = new Camera.CameraInfo();  
  161.                 int cameraCount = Camera.getNumberOfCameras();   
  162.                 for (int camIdx = 0; camIdx < cameraCount; camIdx++)  
  163.                 {  
  164.                     Camera.getCameraInfo(camIdx, mCameraInfo);   
  165.                     if (mCameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT)  
  166.                     {  
  167.                         mCamera = Camera.open(camIdx);                          
  168.                     }  
  169.             }  
  170.         }  
  171.     }  
  172.         catch (Exception e)  
  173.         {  
  174.             e.printStackTrace();  
  175.         }  
  176.         return mCamera;  
  177.     }  
  178.   
  179.     //释放照相机  
  180.     private void releaseCamera()  
  181.     {  
  182.         if (mCamera != null)  
  183.         {  
  184.             IsPreview = false;  
  185.             mCamera.setPreviewCallback(null);  
  186.             mCamera.release();  
  187.             mCamera = null;  
  188.         }  
  189.     }  
  190.   
  191.     private Runnable doAutoFocus = new Runnable()  
  192.     {  
  193.         public void run()  
  194.         {  
  195.             if (IsPreview)  
  196.                 mCamera.autoFocus(autoFocusCB);  
  197.         }  
  198.     };  
  199.   
  200.     PreviewCallback previewCb = new PreviewCallback()  
  201.     {  
  202.         public void onPreviewFrame(byte[] data, Camera camera)  
  203.         {  
  204.             Camera.Parameters parameters = camera.getParameters();  
  205.             //获取扫描图片的大小  
  206.             Size mSize = parameters.getPreviewSize();  
  207.             //构造存储图片的Image  
  208.             Image mResult = new Image(mSize.width, mSize.height, "Y800");//第三个参数不知道是干嘛的  
  209.             //设置Image的数据资源  
  210.             mResult.setData(data);  
  211.             //获取扫描结果的代码  
  212.             int mResultCode = mScanner.scanImage(mResult);  
  213.             //如果代码不为0,表示扫描成功  
  214.             if (mResultCode != 0)  
  215.             {  
  216.                 //停止扫描  
  217.                 IsPreview = false;  
  218.                 mCamera.setPreviewCallback(null);  
  219.                 mCamera.stopPreview();  
  220.                 //开始解析扫描图片  
  221.                 SymbolSet Syms = mScanner.getResults();  
  222.                 for (Symbol mSym : Syms)  
  223.                 {  
  224.                     //mSym.getType()方法可以获取扫描的类型,ZBar支持多种扫描类型,这里实现了条形码、二维码、ISBN码的识别  
  225.                     if (mSym.getType() == Symbol.CODE128 || mSym.getType() == Symbol.QRCODE ||   
  226.                         mSym.getType() == Symbol.CODABAR || mSym.getType() == Symbol.ISBN10 ||  
  227.                         mSym.getType() == Symbol.ISBN13|| mSym.getType()==Symbol.DATABAR ||  
  228.                         mSym.getType()==Symbol.DATABAR_EXP || mSym.getType()==Symbol.I25)  
  229.                                
  230.                     {  
  231.                         //添加震动效果,提示用户扫描完成  
  232.                         Vibrator mVibrator=(Vibrator)getSystemService(VIBRATOR_SERVICE);  
  233.                         mVibrator.vibrate(400);  
  234.                         Intent intent=new Intent(MainActivity.this,ResultActivity.class);  
  235.                         intent.putExtra("ScanResult""扫描类型:"+GetResultByCode(mSym.getType())+"\n"+ mSym.getData());  
  236.                         //这里需要注意的是,getData方法才是最终返回识别结果的方法  
  237.                         //但是这个方法是返回一个标识型的字符串,换言之,返回的值中包含每个字符串的含义  
  238.                         //例如N代表姓名,URL代表一个Web地址等等,其它的暂时不清楚,如果可以对这个进行一个较好的分割  
  239.                         //效果会更好,如果需要返回扫描的图片,可以对Image做一个合适的处理  
  240.                         startActivity(intent);  
  241.                         IsScanned = true;  
  242.                     }  
  243.                     else  
  244.                     {  
  245.                         //否则继续扫描  
  246.                         IsScanned = false;  
  247.                         mCamera.setPreviewCallback(previewCb);  
  248.                         mCamera.startPreview();  
  249.                         IsPreview = true;  
  250.                         mCamera.autoFocus(autoFocusCB);  
  251.                     }  
  252.                 }  
  253.             }  
  254.         }  
  255.     };  
  256.   
  257.     //用于刷新自动聚焦的方法  
  258.     AutoFocusCallback autoFocusCB = new AutoFocusCallback()  
  259.     {  
  260.         public void onAutoFocus(boolean success, Camera camera)  
  261.         {  
  262.             mAutoFocusHandler.postDelayed(doAutoFocus, 1000);  
  263.         }  
  264.     };  
  265.       
  266.     //根据返回的代码值来返回相应的格式化数据  
  267.     public String GetResultByCode(int CodeType)  
  268.     {  
  269.         String mResult="";  
  270.         switch(CodeType)  
  271.         {  
  272.           //条形码  
  273.           case Symbol.CODABAR:  
  274.               mResult="条形码";  
  275.               break;  
  276.           //128编码格式二维码)  
  277.           case Symbol.CODE128:  
  278.               mResult="二维码";  
  279.               break;  
  280.           //QR码二维码  
  281.           case Symbol.QRCODE:  
  282.               mResult="二维码";  
  283.               break;  
  284.           //ISBN10图书查询  
  285.           case Symbol.ISBN10:  
  286.               mResult="图书ISBN号";  
  287.               break;  
  288.           //ISBN13图书查询  
  289.           case Symbol.ISBN13:  
  290.               mResult="图书ISBN号";  
  291.               break;  
  292.         }  
  293.         return mResult;  
  294.     }  
  295.    
  296.       
  297. }  
             对于显示扫描结果的界面,代码比较简单

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /* 
  2.  * 返回扫描结果 
  3.  * 作者:秦元培 
  4.  * 时间:2013年12月21日 
  5.  * 总结:这里有一个问题,就是在这个界面上按下返回键的时候程序会立即报错,试着重写过相关的方法都解决不了问题 
  6.  * 谁要是知道这个问题怎么解决,记得给我说一声啊 
  7.  */  
  8. package com.Android.ZBar4Android;  
  9.   
  10. import android.app.Activity;  
  11. import android.content.Intent;  
  12. import android.os.Bundle;  
  13. import android.view.View;  
  14. import android.view.View.OnClickListener;  
  15. import android.view.Window;  
  16. import android.widget.Button;  
  17. import android.widget.TextView;  
  18.   
  19. public class ResultActivity extends Activity   
  20. {  
  21.   
  22.     private TextView tv;  
  23.     private Button BtnBack;  
  24.     @Override  
  25.     protected void onCreate(Bundle savedInstanceState)   
  26.     {  
  27.         super.onCreate(savedInstanceState);  
  28.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  29.         setContentView(R.layout.layout_result);  
  30.         //获取扫描结果  
  31.         Intent intent=getIntent();  
  32.         Bundle mData=intent.getExtras();  
  33.         CharSequence mResult=mData.getCharSequence("ScanResult");  
  34.         StringHelper mHelper=new StringHelper(mResult.toString());  
  35.         mResult=mHelper.SplitFormDict();  
  36.         tv=(TextView)findViewById(R.id.TextResult);  
  37.         tv.setText(mResult);  
  38.         //返回扫描界面  
  39.         BtnBack=(Button)findViewById(R.id.BtnBack);  
  40.         BtnBack.setOnClickListener(new OnClickListener()  
  41.         {  
  42.             @Override  
  43.             public void onClick(View arg0)   
  44.             {  
  45.                 Intent intent=new Intent(ResultActivity.this,MainActivity.class);  
  46.                 startActivity(intent);  
  47.             }  
  48.               
  49.         });  
  50.     }  
  51.       
  52.     @Override  
  53.     protected void onPause()   
  54.     {  
  55.         super.onPause();  
  56.     }  
  57.       
  58. }  

                        五、总结

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

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

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

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

                  4、校准框死活画不出来

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

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

                  源代码下载


 

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐