现在很多App都集成了扫一扫功能,最常用的微信、QQ、手机助手等。二维码也使得生活变得更加简洁,扫一扫订餐、扫一扫下载等等。那么,说到二维码,我们不得不提Google一个开源的扫码框架:zxing。

开源下载:http://code.google.com/p/zxing/

zxing是基于多种1D/2D条码处理的开源库,是一个完整的项目。它可以通过手机摄像头实现条码的扫描以及解码,功能及其强大。那么如果要实现二维码的扫描以及解码,我们需要在该开源项目的基础上进行简化,并修改。让我们来看一下

      

上图是仿照QQ的扫一扫进行修改的zxing项目,以zxing项目为基础,结合实际应用,这里作了三点改变:

(1)竖屏扫描

(2)自定义取景框

(3)重新定义扫描结果处理

一、第一步:下载zxing项目,并简化出扫描框架

1、首先,下载最新zxing开源项目。 下载地址:http://code.google.com/p/zxing/

2、分析项目结构,明确扫描框架需求。在zxing中,有很多其他的功能,项目结构比较复杂;针对二维码QRCode扫描,我们需要几个包:

(1)com.google.zxing.client.android.Camera  基于Camera调用以及参数配置,核心包

(2)DecodeFormatManager、DecodeThread、DecodeHandler 基于解码格式、解码线程、解码结果处理的解码类

(3)ViewfinderView、ViewfinderResultPointCallBack 基于取景框视图定义的View类

(4)CaptureActivity、CaptureActivityHandler 基于扫描Activity以及扫描结果处理的Capture类

(5)InactivityTimer、BeepManager、FinishListener 基于休眠、声音、退出的辅助管理类

(6)Intents、IntentSource、PrefrencesActivity 基于常量存储的常量类

3、新建工程,添加如下权限:

  <uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.FLASHLIGHT" />

permission

添加core.jar文件,并BuildPath;将上述类或包加入工程后,会报一系列错误,原因有几点:

(1)资源文件缺乏,将zxing下需要的资源文件copy到新工程下

(2)版本兼容问题,zxing下很多技术都是使用4.0版本及以上,集成到低版本之后,须做相应改动,详情参照项目源码

(3)包结构引用问题,需要重新导入包引用

4、简化CapyureActivity, camera包以及decode各类异常解决以后,即可对CaptureActivity进行代码简化 ,首先看一下capture.xml布局

 1 <merge xmlns:android="http://schemas.android.com/apk/res/android"
2 xmlns:tools="http://schemas.android.com/tools" >
3
4 <!-- 整体透明画布 -->
5 <SurfaceView
6 android:id="@+id/preview_view"
7 android:layout_width="fill_parent"
8 android:layout_height="fill_parent" />
9
10 <!-- 扫描取景框 -->
11 <com.karics.library.zxing.view.ViewfinderView
12 android:id="@+id/viewfinder_view"
13 android:layout_width="fill_parent"
14 android:layout_height="fill_parent" />
15
16 <!-- 标题栏 -->
17 <RelativeLayout
18 android:layout_width="fill_parent"
19 android:layout_height="50dp"
20 android:layout_gravity="top"
21 android:background="#99000000">
22
23 <ImageButton
24 android:id="@+id/capture_imageview_back"
25 android:layout_width="42dp"
26 android:layout_height="42dp"
27 android:layout_centerVertical="true"
28 android:background="@drawable/selector_capture_back"/>
29
30 <TextView
31 android:layout_width="wrap_content"
32 android:layout_height="wrap_content"
33 android:layout_centerInParent="true"
34 android:textColor="#ffffffff"
35 android:textSize="20sp"
36 android:text="扫一扫"/>
37
38 </RelativeLayout>
39
40 </merge>

capture.xml

capture.xml布局去掉结果显示,添加标题栏。那么captureActivity中,onCreate(),onPause(),onResume(),onDestroy涉及到Camera的初始化或销毁

 1 @Override
2 public void onCreate(Bundle icicle) {
3 super.onCreate(icicle);
4 // 保持Activity处于唤醒状态
5 Window window = getWindow();
6 window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
7 setContentView(R.layout.capture);
8
9 hasSurface = false;
10
11 inactivityTimer = new InactivityTimer(this);
12 beepManager = new BeepManager(this);
13
14 imageButton_back = (ImageButton) findViewById(R.id.capture_imageview_back);
15 imageButton_back.setOnClickListener(new View.OnClickListener() {
16
17 @Override
18 public void onClick(View v) {
19 finish();
20 }
21 });
22 }
23
24 @Override
25 protected void onResume() {
26 super.onResume();
27
28 // CameraManager必须在这里初始化,而不是在onCreate()中。
29 // 这是必须的,因为当我们第一次进入时需要显示帮助页,我们并不想打开Camera,测量屏幕大小
30 // 当扫描框的尺寸不正确时会出现bug
31 cameraManager = new CameraManager(getApplication());
32
33 viewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view);
34 viewfinderView.setCameraManager(cameraManager);
35
36 handler = null;
37
38 SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view);
39 SurfaceHolder surfaceHolder = surfaceView.getHolder();
40 if (hasSurface) {
41 // activity在paused时但不会stopped,因此surface仍旧存在;
42 // surfaceCreated()不会调用,因此在这里初始化camera
43 initCamera(surfaceHolder);
44 } else {
45 // 重置callback,等待surfaceCreated()来初始化camera
46 surfaceHolder.addCallback(this);
47 }
48
49 beepManager.updatePrefs();
50 inactivityTimer.onResume();
51
52 source = IntentSource.NONE;
53 decodeFormats = null;
54 characterSet = null;
55 }
56
57 @Override
58 protected void onPause() {
59 if (handler != null) {
60 handler.quitSynchronously();
61 handler = null;
62 }
63 inactivityTimer.onPause();
64 beepManager.close();
65 cameraManager.closeDriver();
66 if (!hasSurface) {
67 SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view);
68 SurfaceHolder surfaceHolder = surfaceView.getHolder();
69 surfaceHolder.removeCallback(this);
70 }
71 super.onPause();
72 }
73
74 @Override
75 protected void onDestroy() {
76 inactivityTimer.shutdown();
77 super.onDestroy();
78 }

surfaceview是基于Camera而实现,surfaceview的使用需要实现SurfaceHolder.Callback接口,在开启屏幕surfaceview的时候初始化camera

 1 @Override
2 public void surfaceCreated(SurfaceHolder holder) {
3 if (!hasSurface) {
4 hasSurface = true;
5 initCamera(holder);
6 }
7 }
8
9 @Override
10 public void surfaceDestroyed(SurfaceHolder holder) {
11 hasSurface = false;
12 }
13
14 @Override
15 public void surfaceChanged(SurfaceHolder holder, int format, int width,
16 int height) {
17
18 }

接下来看如何初始化Camera,代码简化之后如下

 1 private void initCamera(SurfaceHolder surfaceHolder) {
2 if (surfaceHolder == null) {
3 throw new IllegalStateException("No SurfaceHolder provided");
4 }
5 if (cameraManager.isOpen()) {
6 return;
7 }
8 try {
9 // 打开Camera硬件设备
10 cameraManager.openDriver(surfaceHolder);
11 // 创建一个handler来打开预览,并抛出一个运行时异常
12 if (handler == null) {
13 handler = new CaptureActivityHandler(this, decodeFormats,
14 decodeHints, characterSet, cameraManager);
15 }
16 } catch (IOException ioe) {
17 Log.w(TAG, ioe);
18 displayFrameworkBugMessageAndExit();
19 } catch (RuntimeException e) {
20 Log.w(TAG, "Unexpected error initializing camera", e);
21 displayFrameworkBugMessageAndExit();
22 }
23 }

在CaptureActivity中,有一个核心方法,用来返回并处理解码结果,也即扫描结果。handleDecode(),如果需要对解码后的内容进行自己的处理,需要对该方法进行改动,这里修改        为将解码的bitmap以及内容回传到开启扫描的Activiity进行处理。

 1 public void handleDecode(Result rawResult, Bitmap barcode, float scaleFactor) {
2 inactivityTimer.onActivity();
3
4 boolean fromLiveScan = barcode != null;
5 //这里处理解码完成后的结果,此处将参数回传到Activity处理
6 if (fromLiveScan) {
7 beepManager.playBeepSoundAndVibrate();
8
9 Toast.makeText(this, "扫描成功", Toast.LENGTH_SHORT).show();
10
11 Intent intent = getIntent();
12 intent.putExtra("codedContent", rawResult.getText());
13 intent.putExtra("codedBitmap", barcode);
14 setResult(RESULT_OK, intent);
15 finish();
16 }
17
18 }

5、将指定Url生成二维码

 1 /**
2 * 生成QRCode(二维码)
3 *
4 * @param str
5 * @return
6 * @throws WriterException
7 */
8 public static Bitmap createQRCode(String url) throws WriterException {
9
10 if (url == null || url.equals("")) {
11 return null;
12 }
13
14 // 生成二维矩阵,编码时指定大小,不要生成了图片以后再进行缩放,这样会模糊导致识别失败
15 BitMatrix matrix = new MultiFormatWriter().encode(url,
16 BarcodeFormat.QR_CODE, 300, 300);
17
18 int width = matrix.getWidth();
19 int height = matrix.getHeight();
20
21 // 二维矩阵转为一维像素数组,也就是一直横着排了
22 int[] pixels = new int[width * height];
23
24 for (int y = 0; y < height; y++) {
25 for (int x = 0; x < width; x++) {
26 if (matrix.get(x, y)) {
27 pixels[y * width + x] = 0xff000000;
28 }
29
30 }
31 }
32
33 Bitmap bitmap = Bitmap.createBitmap(width, height,
34 Bitmap.Config.ARGB_8888);
35 bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
36 return bitmap;
37 }

通过以上四步,zxing项目的简化工作基本完成。至于一些类需要进行小修小改,希望可以对着源码进行,这里不再赘述。二维码扫描的整体构架主要包含三部分:

1、定义取景框,也即扫描的View,通过surfaceview进行绘制

2、Camera, 扫描的核心在于camera的配置使用,包括预览,自动聚焦,打开设备等处理

3、Decode解码,扫描完成后整个工程的核心

除去以上三个模块,需要明确的就是CaptureActivitiy中handleDeCode()方法做自己的处理。

点击下面链接,即可下载源码

http://pan.baidu.com/s/1c0yADUS

Android自由行之走进zxing,轻松实现二维码扫描的更多相关文章

  1. 【Android-Zxing框架】二维码扫描框区域大小与不同手机分辨率适配问题

    Zxing框架进行二维码扫描时候会发现,随着分辨率的增加,扫描框会越来越小,SurfaceView扫描窗口就看不见了,我们可以自己定义扫描窗口的大小,以及适配屏幕问题. Zxing包中有个类Camer ...

  2. Android—ZXing二维码扫描遇到的问题

    最近工作中需要开发带有二维码扫描功能的软件(基于开源项目ZXing),遇到的问题记录一下,也希望给大家带来帮助. 1.首先因为扫描要开摄像机所以加权限是一定的,不然后面什么都不能进行 <uses ...

  3. Android 基于google Zxing实现二维码、条形码扫描,仿微信二维码扫描效果

      Android 高手进阶(21)  版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请注明出处:http://blog.csdn.net/xiaanming/article/detail ...

  4. 【转】Android 基于google Zxing实现二维码、条形码扫描,仿微信二维码扫描效果--不错

    原文网址:http://blog.csdn.net/xiaanming/article/details/10163203 转载请注明出处:http://blog.csdn.net/xiaanming/ ...

  5. Android快速实现二维码扫描--Zxing

    Android中二维码扫描的最常用库是zxing和zbar,zxing项目地址为https://github.com/zxing/zxing,目前还有多个人在维护.zbar主要用C来写的,对速度有要求 ...

  6. Zxing图片拉伸解决 Android 二维码扫描

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/aaawqqq/article/details/24852915  二维码扫描  Android Zx ...

  7. Android之Zxing二维码扫描图片拉伸

    还是这个接手项目,二维码扫描集成的是zxing,扫描界面的图像有明显的拉伸变形. 这种问题,根据以往的经验,一般是x,y轴错位引起的,处理好x,y轴的问题,一般可以解决问题. 由于这个问题,之前有很多 ...

  8. XAMARIN ANDROID 二维码扫描示例

    现在二维码的应用越来越普及,二维码扫描也成为手机应用程序的必备功能了.本文将基于 Xamarin.Android 平台使用 ZXing.Net.Mobile  做一个简单的 Android 条码扫描示 ...

  9. Android仿微信二维码扫描

    转载:http://blog.csdn.net/xiaanming/article/details/10163203 了解二维码这个东西还是从微信中,当时微信推出二维码扫描功能,自己感觉挺新颖的,从一 ...

随机推荐

  1. asp.net推送

    http://tech.it168.com/a2012/0210/1310/000001310252_all.shtml http://www.infoq.com/cn/news/2012/09/rc ...

  2. Android自定义属性时format选项可以取用的值

    1. reference:参考某一资源ID. (1)属性定义: <declare-styleable name="名称"> <attr format=" ...

  3. IPSEC实现

    IPSEC介绍与实现 一.介绍 IPSec 协议不是一个单独的协议,它给出了应用于IP层上网络数据安全的一整套体系结构,包括网络认证协议 Authentication Header(AH).封装安全载 ...

  4. mac 修改密码后 频繁输入钥匙串问题修复方法

    就一句话就是 清空钥匙串缓存 下面是具体方法 进入硬盘目录-->资源库-->Keychains 删除里面的文件夹(这个文件夹里面有 keychain-2.db keychain-2.db- ...

  5. MapReduce——计算温度最大值 (基于全新2.2.0API)

    MapReduce——计算温度最大值 (基于全新2.2.0API) deprecated: Job类的所有Constructors, 新的API用静态方法getInstance(conf)来去的Job ...

  6. bzoj1007

    其实吧,就是一个半平面交,而且不用考虑转回来的情况,所以只要极角排序然后用栈即可给的是点斜式,比极角很方便至于完整版的半平面交还没写过,看到再说吧 ..] of longint; v:..] of b ...

  7. NOI2010超级钢琴 2

    2006: [NOI2010]超级钢琴 Time Limit: 20 Sec  Memory Limit: 552 MBSubmit: 1296  Solved: 606[Submit][Status ...

  8. MS-DOS 7.10完整安装版(含图文安装程序)

    大家知道,要想学习或使用DOS,安装一个DOS并进行实际操作是非常必要的.MS-DOS 7.10是一个非常好且强大实用的操作系统,而且兼容性和性能都十分强.要在系统中安装MS-DOS 7.10,可以使 ...

  9. MVVM中轻松实现Command绑定(三)任意事件的Command

    WPF中不是所有的控件都有Command属性的,如果窗体我需要在ViewModel中处理Loaded事件命令,或者其他事件的命令时,很难都过绑定Command完成,必须要注册依赖属性或事件等,太麻烦了 ...

  10. 如何在小方框上打对号 小方框内打对勾 word 方框打对勾

      在word中做选择时,很多人遇到需要在小方框上打对勾而不知如何做,现将可行的各种方法总结如下: 1:直接找到一个做好的,保存为图片,在需要的时候插入它: 2:插入文本框,然后边框选择为实线,在文本 ...