zoukankan      html  css  js  c++  java
  • Zxing库

    一.介绍

      Zxing是一个开放的源码,用java实现的多种样式的1D/2D条码处理库,它包含了联系到其他语言的端口。Zxing可以实现手机的内置摄像头完成条码的扫描及解码。目前支持:UPC-A ,UPC-E ,EAN-8 ,EAN-13 ,39 码,93码。

    二.Zxing库的主要类

      1.CaptureActivity :启动Activity,也就是扫描器

      2.CaptureActivityHandler :解码处理器,负责调用另外的线程进行解码

      3.DecodeThread :解码线程

      4.com.google.zxing.client.android.camera包:摄像头调用包

      5.ViewfinderView :自定义的View,就是我们看到的拍摄中间的框框

    三. 使用Zxing生成二维码

    //Edited by mythou
    //http://www.cnblogs.com/mythou/
      //要转换的地址或字符串,可以是中文
        public void createQRImage(String url)
        {
            try
            {
                //判断URL合法性
                if (url == null || "".equals(url) || url.length() < 1)
                {
                    return;
                }
                Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>();
                hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
                //图像数据转换,使用了矩阵转换
                BitMatrix bitMatrix = new QRCodeWriter().encode(url, BarcodeFormat.QR_CODE, QR_WIDTH, QR_HEIGHT, hints);
                int[] pixels = new int[QR_WIDTH * QR_HEIGHT];
                //下面这里按照二维码的算法,逐个生成二维码的图片,
                //两个for循环是图片横列扫描的结果
                for (int y = 0; y < QR_HEIGHT; y++)
                {
                    for (int x = 0; x < QR_WIDTH; x++)
                    {
                        if (bitMatrix.get(x, y))
                        {
                            pixels[y * QR_WIDTH + x] = 0xff000000;
                        }
                        else
                        {
                            pixels[y * QR_WIDTH + x] = 0xffffffff;
                        }
                    }
                }
                //生成二维码图片的格式,使用ARGB_8888
                Bitmap bitmap = Bitmap.createBitmap(QR_WIDTH, QR_HEIGHT, Bitmap.Config.ARGB_8888);
                bitmap.setPixels(pixels, 0, QR_WIDTH, 0, 0, QR_WIDTH, QR_HEIGHT);
                //显示到一个ImageView上面
                sweepIV.setImageBitmap(bitmap);
            }
            catch (WriterException e)
            {
                e.printStackTrace();
            }
        }

      上面就是二维码生成的方法接口,如果你只是使用者方法,很简单,只要传一个URL即可。或者像现在一些移动的App推广,把App下载地址转成二维码;
      上面代码做的事情不多,主要是调用Zxing库里面的QRCodeWriter().encode的方法对我们传进去的URL进行编码


    四.扫描二维码获取信息

      扫描获取二维码信息工作稍微复杂一点,主要是需要编写的Camera的使用,这个跟我们一般使用的Camera一样,需要使用Sufaceview作为预览;
      获取二维码数据的关键在于处理说在Camera的自动对焦回函数那里,调用ZXing的解码接口:
    //Edited by mythou
    //http://www.cnblogs.com/mythou/
      private void restartPreviewAndDecode() {
        if (state == State.SUCCESS) {
          state = State.PREVIEW;
          CameraManager.get().requestPreviewFrame(decodeThread.getHandler(), R.id.decode);
          CameraManager.get().requestAutoFocus(this, R.id.auto_focus);
          activity.drawViewfinder();
        }
      }
      由于解码需要一点时间,所以ZXing的解码调用,都是使用Handler作为线程通讯机制,解码的工作都是放在独立线程里面使用的,如果你放在主线程解码,恐怕ANR问题是避免不了

    public void handleMessage(Message message) {
        switch (message.what) {
          case R.id.auto_focus:
            //Log.d(TAG, "Got auto-focus message");
            // When one auto focus pass finishes, start another. This is the closest thing to
            // continuous AF. It does seem to hunt a bit, but I'm not sure what else to do.
            if (state == State.PREVIEW) {
              CameraManager.get().requestAutoFocus(this, R.id.auto_focus);
            }
            break;
          case R.id.restart_preview:
            Log.d(TAG, "Got restart preview message");
            restartPreviewAndDecode();
            break;
          case R.id.decode_succeeded:
        //解码成功,获取到界面的结果和原来的二维码数据
            Log.d(TAG, "Got decode succeeded message");
            state = State.SUCCESS;
            Bundle bundle = message.getData();
            Bitmap barcode = bundle == null ? null :
                (Bitmap) bundle.getParcelable(DecodeThread.BARCODE_BITMAP);
            activity.handleDecode((Result) message.obj, barcode);
            break;
          case R.id.decode_failed:
            // We're decoding as fast as possible, so when one decode fails, start another.
            state = State.PREVIEW;
            CameraManager.get().requestPreviewFrame(decodeThread.getHandler(), R.id.decode);
            break;
          case R.id.return_scan_result:
            Log.d(TAG, "Got return scan result message");
            activity.setResult(Activity.RESULT_OK, (Intent) message.obj);
            activity.finish();
            break;
          case R.id.launch_product_query:
            Log.d(TAG, "Got product query message");
            String url = (String) message.obj;
            Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
            activity.startActivity(intent);
            break;
        }
      }
    
    
      上面是解码的线程处理不同状态时候需要注意的地方,我们这里只看获取图像成功的地方,成功获取图片解码的是在DecodeThread里面实现的; DecodeThread里面解码成功后,会把数据序列化,然后保存到Bundle里面,我们可以直接通过Bundle的序列化,获取图片数据; 同时会把解码后的结果保存到MSG里面,然后可以根据实际情况进行处理;例如上面代码,解码成功后,会调用一个处理函数:
     
    public void handleMessage(Message message) {
        switch (message.what) {
          case R.id.auto_focus:
            //Log.d(TAG, "Got auto-focus message");
            // When one auto focus pass finishes, start another. This is the closest thing to
            // continuous AF. It does seem to hunt a bit, but I'm not sure what else to do.
            if (state == State.PREVIEW) {
              CameraManager.get().requestAutoFocus(this, R.id.auto_focus);
            }
            break;
          case R.id.restart_preview:
            Log.d(TAG, "Got restart preview message");
            restartPreviewAndDecode();
            break;
          case R.id.decode_succeeded:
        //解码成功,获取到界面的结果和原来的二维码数据
            Log.d(TAG, "Got decode succeeded message");
            state = State.SUCCESS;
            Bundle bundle = message.getData();
            Bitmap barcode = bundle == null ? null :
                (Bitmap) bundle.getParcelable(DecodeThread.BARCODE_BITMAP);
            activity.handleDecode((Result) message.obj, barcode);
            break;
          case R.id.decode_failed:
            // We're decoding as fast as possible, so when one decode fails, start another.
            state = State.PREVIEW;
            CameraManager.get().requestPreviewFrame(decodeThread.getHandler(), R.id.decode);
            break;
          case R.id.return_scan_result:
            Log.d(TAG, "Got return scan result message");
            activity.setResult(Activity.RESULT_OK, (Intent) message.obj);
            activity.finish();
            break;
          case R.id.launch_product_query:
            Log.d(TAG, "Got product query message");
            String url = (String) message.obj;
            Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
            activity.startActivity(intent);
            break;
        }
      }
     
       上面就是整个二维码的解码流程,里面因为涉及很多Camera的使用,所以你如果需要使用二维码识别,需要注意一下你的程序需要申请以下权限,一般的Camera使用以及Camrea的自动对焦等。
    <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" />


    五.结尾

    ZXing开源项目Google Code地址:https://code.google.com/p/zxing/

    ZXingDemo下载:ZXingDemo2013-8-25.rar

     

     




  • 相关阅读:
    linux 远程同步数据工具rsync (1)
    lamp+nginx代理+discuz+wordpress+phpmyadmin
    Linux nginx 配置 location 语法 正则表达式
    linux下用ctrl+r快速搜索history命令
    常用服务的默认端口
    nginx rewrite不支持if 嵌套也不支持逻辑或和逻辑并
    nginx的301与302如何配置
    nginx $document_uri 参数使用
    选项“6”对 /langversion 无效;必须是 ISO-1、ISO-2、3、4、5 或 Default
    为什么托管代码要慢
  • 原文地址:https://www.cnblogs.com/yiweiaimeng/p/4998166.html
Copyright © 2011-2022 走看看