`
ljl_xyf
  • 浏览: 636539 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

android利用ZXing进行条码扫描二维码扫描源码简化

阅读更多

导入项目

@Override
      public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.main);
          //初始化 CameraManager
           CameraManager.init(getApplication());
  
          viewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view);
          txtResult = (TextView) findViewById(R.id.txtResult);
         hasSurface = false;
         inactivityTimer = new InactivityTimer(this);
     }
 

  打开Eclipse 导入 源码中的 Android 项目,然后右击项目 选择“Build path”——》"Add External Archives" 把核心库 core.jar文件加入到项目中。

此时编译一下项目,会发现报错,“ Multiple substitutions specified in non-positional format; did you mean to add the formatted="false" attribute? ”之类的。打开raw 下的Values 发现错误是在一个<String>上。这里把 “preferences_custom_product_search_summary ” 里的  %s  %f  全部都改成  %1$s  %1$f(因为我们用不到多国语言,建议只保留默认的Value ,其他全部删除)。

  原因:由于新的SDK采用了新版本的aapt(Android项目编译器),这个版本的aapt编译起来会比老版本更加的严格,然后在Android最新的开发文档的描述String的部分,已经说明如何去设置 %s 等符号

  “If you need to format your strings using String.format(String, Object...) , then you can do so by putting your format arguments in the string resource. For example, with the following resource:

  <string name="welcome_messages">Hello, %1$s! You have %2$d new messages.</string>

  In this example, the format string has two arguments: %1$s is a string and %2$d is a decimal number. You can format the string with arguements from your application...“

  经过以上步骤后项目应该就可以运行了。

  但是ZXing的android项目东西太多了,有很多是我们不需要的,得新建另一个项目简化它。

简化

  在开始前大致介绍一下简化ZXing需要用到各个包 、类的职责。

  • CaptureActivity。这个是启动Activity 也就是扫描器(如果是第一安装,它还会跳转到帮助界面)。
  • CaptureActivityHandler 解码处理类,负责调用另外的线程进行解码。
  • DecodeThread 解码的线程。
  • com.google.zxing.client.android.camera 包,摄像头控制包。
  • ViewfinderView 自定义的View,就是我们看见的拍摄时中间的框框了。

新建另一个项目

  新建另一个项目将启动的Activity命名为CaptureActivity,并导入核心库。项目新建完成后我们打开 CaptureActivity 的布局文件,我这里为main。把里面的XML修改为:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     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_centerInParent="true" />
         
     <com.Zxing.Demo.view.ViewfinderView
         android:id="@+id/viewfinder_view" android:layout_width="fill_parent"
         android:layout_height="fill_parent" android:background="@android:color/transparent" />
     <TextView android:layout_width="wrap_content"
         android:id="@+id/txtResult"
         android:layout_height="wrap_content" android:text="@string/hello" />
     
  </FrameLayout>
 

  可以看到在XML里面用到了 ViewfinderView 自定义view 。所以新建一个View 的包,然后把:ViewfinderView 和 ViewfinderResultPointCallback 靠到里面(记得对应修改XML里面的包)。

打开 CaptureActivity 覆盖 onCreate 方法:

 

  这里调用到的 CameraManager 类是控制摄像头的包里的类。新建一个camera包把:com.google.zxing.client.android.camera 里面的类全部拷入,另外我把PlanarYUVLuminanceSource也拷入到这个包里面。根据错误的提示来修正代码,主要是修改正包结构。(整 个简化的流程都是如此:“根据错误提示,修改代码 ”)。


  在修改的过程中,有很多是关于R 资源的问题,在此我们需要将Values  里面的两个xml资源文件拷入项目中:colos.xml 和ids.xml 。 ctrl+b 一下看看error 是不是少了很多。在CameraManager中有些地方需要用到项目的配置,这里需要把配置直接写入代码中:

/     SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
      //是否使用前灯
//      if (prefs.getBoolean(PreferencesActivity.KEY_FRONT_LIGHT, false)) {
//        FlashlightManager.enableFlashlight();
//      }
      FlashlightManager.enableFlashlight();
 

   使用摄像头需要加入相应的权限:

<uses-permission android:name="android.permission.CAMERA"></uses-permission>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
    <uses-feature android:name="android.hardware.camera" />
    <uses-feature android:name="android.hardware.camera.autofocus" />
      <uses-permission android:name="android.permission.VIBRATE"/>
  <uses-permission android:name="android.permission.FLASHLIGHT"/>

 

当View 和 camera 包里的错误修正完成后,我们继续来看CaptureActivity。

覆盖onResume方法初始化摄像头:

 

@Override
    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 = null;
        characterSet = null;

        playBeep = true;
        AudioManager audioService = (AudioManager) getSystemService(AUDIO_SERVICE);
        if (audioService.getRingerMode() != AudioManager.RINGER_MODE_NORMAL) {
            playBeep = false;
        }
        initBeepSound();
        vibrate = true;
    }
 





initCamera

private void initCamera(SurfaceHolder surfaceHolder) {
        try {
            CameraManager.get().openDriver(surfaceHolder);
        } catch (IOException ioe) {
            return;
        } catch (RuntimeException e) {
            return;
        }
        if (handler == null) {
            handler = new CaptureActivityHandler(this, decodeFormats,
                    characterSet);
        }
    }
 

 

 

SurfaceHolder接口实现
@Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {

    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        if (!hasSurface) {
            hasSurface = true;
            initCamera(holder);
        }

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        hasSurface = false;

    }
 

initCamera () 方法用于初始化摄像头,如果排除了所有的error ,运行项目时就可以看到大致扫描界面了。 surfaceHolder.addCallback( this );表示让CaptureActivity实现其callback接口。

handler = new CaptureActivityHandler(this, decodeFormats, characterSet) 用于进行扫描解码处理。

解码

  上面的步骤主要都是用于对摄像头的控制,而解码的真正工作入口是在CaptureActivityHandler 里面的。新建一个Decoding包把以下文件拷入包中:

  • CaptureActivityHandler
  • DecodeFormatManager
  • DecodeHandler
  • DecodeThread
  • FinishListener
  • InactivityTimer
  • Intents  http://www.my400800.cn

由于我们的包结构和Zxing 项目的有所不同所以需要注意一下类的可访问性

同样开始ctrl+B 编译一下,然后开始修正错误。

  在CaptureActivityHandler 里 把 handleMessage 里的部分方法先注释掉如:“decode_succeeded ”分支,这是解码成功时调用 CaptureActivity 展示解码的结果。

在DecodeThread 类里,修改部分涉及Preference配置的代码:

DecodeThread(CaptureActivity activity,
               Vector<BarcodeFormat> decodeFormats,
               String characterSet,
               ResultPointCallback resultPointCallback) {

    this.activity = activity;
    handlerInitLatch = new CountDownLatch(1);

    hints = new Hashtable<DecodeHintType, Object>(3);

//    // The prefs can't change while the thread is running, so pick them up once here.
//    if (decodeFormats == null || decodeFormats.isEmpty()) {
//      SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
//      decodeFormats = new Vector<BarcodeFormat>();
//      if (prefs.getBoolean(PreferencesActivity.KEY_DECODE_1D, true)) {
//        decodeFormats.addAll(DecodeFormatManager.ONE_D_FORMATS);
//      }
//      if (prefs.getBoolean(PreferencesActivity.KEY_DECODE_QR, true)) {
//        decodeFormats.addAll(DecodeFormatManager.QR_CODE_FORMATS);
//      }
//      if (prefs.getBoolean(PreferencesActivity.KEY_DECODE_DATA_MATRIX, true)) {
//        decodeFormats.addAll(DecodeFormatManager.DATA_MATRIX_FORMATS);
//      }
//    }
    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);
  }
 

这里是设置 解码的类型,我们现在默认将所有类型都加入。

错误类型基本上都是:包结构、PreferencesActivity 的配置 、类可访问性的问题。根据错误提示耐心把错误解决。

返回解码结果

   还记得在 CaptureActivityHandler 的 messagehandler 里注销掉的Case分支吗?现在CaptureActivity 里实现它。

 public void handleDecode(Result obj, Bitmap barcode) {
        inactivityTimer.onActivity();
        viewfinderView.drawResultBitmap(barcode);
         playBeepSoundAndVibrate();
        txtResult.setText(obj.getBarcodeFormat().toString() + ":"
                + obj.getText());
    }
 

最后

  ZXing的简化已基本完成,有几位是可以运行成功的?呵呵。

下面是CaptureActivity的源码:

CaputreActivity
public class CaptureActivity extends Activity implements Callback {

    private CaptureActivityHandler handler;
    private ViewfinderView viewfinderView;
    private boolean hasSurface;
    private Vector<BarcodeFormat> decodeFormats;
    private String characterSet;
    private TextView txtResult;
    private InactivityTimer inactivityTimer;
    private MediaPlayer mediaPlayer;
    private boolean playBeep;
    private static final float BEEP_VOLUME = 0.10f;
    private boolean vibrate;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        //初始化 CameraManager
        CameraManager.init(getApplication());

        viewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view);
        txtResult = (TextView) findViewById(R.id.txtResult);
        hasSurface = false;
        inactivityTimer = new InactivityTimer(this);
    }

    @Override
    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 = null;
        characterSet = null;

        playBeep = true;
        AudioManager audioService = (AudioManager) getSystemService(AUDIO_SERVICE);
        if (audioService.getRingerMode() != AudioManager.RINGER_MODE_NORMAL) {
            playBeep = false;
        }
        initBeepSound();
        vibrate = true;
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (handler != null) {
            handler.quitSynchronously();
            handler = null;
        }
        CameraManager.get().closeDriver();
    }

    @Override
    protected void onDestroy() {
        inactivityTimer.shutdown();
        super.onDestroy();
    }

    private void initCamera(SurfaceHolder surfaceHolder) {
        try {
            CameraManager.get().openDriver(surfaceHolder);
        } catch (IOException ioe) {
            return;
        } catch (RuntimeException e) {
            return;
        }
        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 = true;
            initCamera(holder);
        }

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        hasSurface = false;

    }

    public ViewfinderView getViewfinderView() {
        return viewfinderView;
    }

    public Handler getHandler() {
        return handler;
    }

    public void drawViewfinder() {
        viewfinderView.drawViewfinder();

    }

    public void handleDecode(Result obj, Bitmap barcode) {
        inactivityTimer.onActivity();
        viewfinderView.drawResultBitmap(barcode);
         playBeepSoundAndVibrate();
        txtResult.setText(obj.getBarcodeFormat().toString() + ":"
                + obj.getText());
    }

    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 = null;
            }
        }
    }

    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);
        }
    };
 

简化过的包结构图:

 

 简化后的ZXing 更加方便我们了解ZXing项目 是如何解码的。只要仔细查看源码,进行单点跟踪调试,相信大家很容易能理解。

  • 大小: 3.6 KB
分享到:
评论

相关推荐

    Android zxing生成 扫描二维码(依赖形式)

    在Android开发中,ZXing(Zebra Crossing)库是一个广泛使用的开源项目,它提供了二维码和条形码的生成与扫描功能。ZXing库为开发者提供了一个便捷的方式,将二维码扫描集成到自己的应用中,无需从零开始实现这些...

    Autojs调用zxing实现条形码与二维码

    本篇文章将详细探讨如何利用AutoJS调用ZXing库来实现条形码和二维码的扫描功能。 首先,ZXing(Zebra Crossing)是一个开源的、跨平台的条形码和二维码读取库。它支持多种编码格式,如QR码、Data Matrix、UPC、EAN...

    android 二维码扫描Zxing

    在Android开发中,二维码扫描是一项常见的功能,用于读取和生成包含信息的二维条形码。ZXing(Zebra Crossing)是Google开发的一个开源项目,它提供了跨平台的二维码和条形码处理库。本文将详细介绍如何在Android...

    Zxing条形码和二维码扫描

    《Zxing:打造高效能的条形码与二维码扫描应用》 Zxing,全称“ZXing,意为“zebra crossing”(斑马线),是一个开源的、跨平台的条形码和二维码读取库。它允许开发者轻松地集成条码和二维码扫描功能到他们的应用...

    android zxing条码扫描源码

    《Android Zxing条码扫描源码解析》 在Android应用开发中,Zxing(又称为ZXing,意为“快速可扩展的二进制解码”)是一个强大的开源项目,专注于各种类型的条码扫描和生成。它提供了跨平台的库,使得开发者能够轻松...

    条形码、二维码扫描、生成Demo 完整源码

    下面将详细阐述ZXing的工作原理以及如何利用其开发一个完整的条形码、二维码生成与扫描的Demo。 首先,让我们了解一下条形码和二维码。条形码是一种用黑白相间的条纹表示数字和字母的信息编码方式,通常包括UPC...

    zxing条形码/二维码开发包源码

    总之,ZXing是一个强大的条形码和二维码处理工具,通过这个修改后的源码,开发者可以更灵活地在Android项目中应用条形码和二维码功能,而无需担心原生包名带来的问题。只需遵循正确的集成步骤,并结合项目需求进行...

    XE10 Android Zxing 实现竖屏扫二维码.docx

    1. **ZXing (Zebra Crossing)**: ZXing是一个开源的、多平台的一维和二维条码图像处理库,支持多种格式的编码和解码,如QR码、条形码等。在Android平台上,ZXing常用于实现二维码扫描功能。 2. **在Delphi XE10中...

    Google ZXing制作的条形码、二维码的生成、扫描Demo 源码.zip

    总之,Google ZXing提供的源码Demo是一个宝贵的教育资源,可以帮助开发者深入了解条形码和二维码的生成与扫描原理,以及如何在实际项目中高效地利用ZXing库。通过深入研究这个源码,你不仅可以掌握ZXing的基本用法,...

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

    总之,基于Google Zxing在Android上实现二维码和条形码扫描涉及了Android的摄像头操作、图像处理、UI设计等多个方面。通过合理的代码结构和用户体验设计,我们可以构建出一个高效且易用的扫描应用,类似微信的扫描...

    Android 二维码扫描 ZXing源码

    ZXing,全称为“Zebra Crossing”,是一款开源的、跨平台的条形码和二维码读取库。在Android平台上,ZXing(又称“二维码扫一扫”)被广泛用于实现二维码扫描功能。本文将深入探讨ZXing源码,解析其在Android应用中...

    Android 基于google Zxing实现二维码、条形码扫描

    本项目"Android 基于google Zxing实现二维码、条形码扫描"就是这样一个示例,它旨在模仿微信的二维码扫描体验,让用户能够快速、方便地读取和识别二维码或条形码信息。 Zxing,又称为“二维码解码器”,是由Google...

    使用zxing识别一幅包含多个二维码的图片

    ZXing(Zebra Crossing),又称“条形码解码库”,是一个开源项目,提供了多种格式的一维和二维条码读取功能,包括二维码。本篇文章将深入探讨如何使用ZXing来识别一幅包含多个二维码的图片。 首先,我们需要理解...

    android 扫描二维码源码及实例

    本篇将深入解析"android 扫描二维码源码及实例"中的关键知识点,包括二维码的基本原理、Android二维码库的使用、相机权限处理以及用户界面设计。 首先,我们需要了解二维码的基本概念。二维码(Quick Response Code...

    Zxing二维码条形码跨平台源码

    【Zxing二维码条形码跨平台源码】是一款基于C++语言开发的开源项目,它允许开发者在不同的操作系统上,包括手机(Android、iOS)、Windows系统等,实现二维码和条形码的扫描与生成功能。这个项目的核心是Zxing...

    扫描二维码(zxing)

    二维码(Quick Response Code,简称QR码)是一种二维条形码,可以存储丰富的信息,如网址、文本、联系人信息等。ZXing(Zebra Crossing)是Google开发的一个开源的、跨平台的条码读取库,支持多种类型的条码和二维码...

    android Zxing扫描二维码条形码功能仿微信扫码框扫描线为图片样式Eclipse版本

    在Android开发中,集成二维码和条形码扫描是一项常见的需求,而Zxing(又名ZXing,意为“zebra crossing”,斑马线)是一个开源的、跨平台的条码图像处理库,提供了多种格式的一维和二维条码的生成与扫描功能。...

    Android zxing生成 扫描二维码(含有源码lib)

    在Android开发中,ZXing(Zebra Crossing)库是一个广泛使用的开源项目,它提供了二维码和条形码的生成与扫描功能。ZXing库为开发者提供了便捷的API接口,使得在Android应用中集成二维码扫描和生成变得简单易行。...

    ZXing(可以编译的二维码、条形码扫描源码)

    对于标题中提到的"可以编译的二维码、条形码扫描源码",这意味着你可以直接获取到ZXing的源代码,并根据自己的需求进行定制和编译。这对于开发者来说是非常有价值的,因为可以深入理解其内部工作原理,同时也能够...

    Android应用源码使用ZXing识别条码二维码(简单的实现).zip

    在Android开发中,ZXing(Zebra Crossing)库是一个广泛使用的开源项目,它提供了解析和生成条形码和二维码的能力。本项目是关于如何在Android应用中简单地集成ZXing来实现条码和二维码的识别功能。下面将详细介绍这...

Global site tag (gtag.js) - Google Analytics