ZXing笔记(2)—portrait ZXing,竖直扫码

0.前言:

上一篇我们简单的玩了玩Zxing,将官方的Demo跑了下,有一个问题就是,这哥们屏幕是横着的,我们做的APP大多数都是竖着的。这肯定不开心的。闲话不多说,咱直接开始进入正题。把昨天的代码down下来直接改。

1.xml切换成竖屏试错:

观察清单文件:

  <application
        android:allowBackup="true"
        android:icon="@drawable/launcher_icon"
        android:label="@string/app_name"
        android:logo="@drawable/launcher_icon">
        <activity
            android:name=".CaptureActivity"
            android:clearTaskOnLaunch="true"
  .......

很明显,CaptureActivity.java是我们需要关注的类。
现在我在清单文件内手动将其设为竖屏。

    <activity
            ...
            android:screenOrientation="portrait"
            .../>

但是这只是看着竖屏了,实际上还无法扫描。
所以只能能另寻办法。

2.解决竖屏带来的问题—不能扫码:

其中的原理我试图整理,但是本人水平有限,想透彻搞明白所有的细节,还是需要花点时间,涉及到底层Camera原理,甚至扫码的算法,所以这里我就不强行解释了,等后面真的搞明白之后再来阐释这个问题,但是在本文尾部的推荐的大神博客内有所论述这个问题。现阶段就先操作操作吧。

温馨提示:注意 add by tancolo 和 end 的区间才是需要添加的代码。

step_1.删除 android:screenOrientation=”sensorLandscape”

AndroidManifest.xml

step_2.CaptureActivity内部类MyOrientationDetector使用。

添加内部类

private class MyOrientationDetector extends OrientationEventListener {

      private int lastOrientation = -1;

      MyOrientationDetector(Context context) {
          super(context);
      }

      void setLastOrientation(int rotation) {
          switch (rotation) {
              case Surface.ROTATION_90:
                  lastOrientation = 270;
                  break;
              case Surface.ROTATION_270:
                  lastOrientation = 90;
                  break;
              default:
                  lastOrientation = -1;
          }
      }

      @Override
      public void onOrientationChanged(int orientation) {
          Log.d(TAG, "orientation:" + orientation);
          if (orientation > 45 && orientation < 135) {
              orientation = 90;
          } else if (orientation > 225 && orientation < 315) {
              orientation = 270;
          } else {
              orientation = -1;
          }
          if ((orientation == 90  && lastOrientation == 270) || (orientation == 270  && lastOrientation == 90)) {
              Log.i(TAG, "orientation:" + orientation + "lastOrientation:" + lastOrientation);
              Intent intent = getIntent();
              finish();
              startActivity(intent);
              lastOrientation = orientation;
              Log.i(TAG, "SUCCESS");
          }
      }
  }

声明MyOrientationDetector变量

MyOrientationDetector myOrientationDetector;

onCreate中使用

//add by tancolo
    myOrientationDetector = new MyOrientationDetector(this);
    myOrientationDetector.setLastOrientation(getWindowManager().getDefaultDisplay().getRotation());
    //end add

onResume中使用

if (prefs.getBoolean(PreferencesActivity.KEY_DISABLE_AUTO_ORIENTATION, true)) {
      setRequestedOrientation(getCurrentOrientation());
    } else {
      setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR); // 旋转
      myOrientationDetector.enable(); //启用监听
    }

onPause中使用

  //add by tancolo
    myOrientationDetector.disable();
    //end add

    super.onPause();

step_3.获得准确的相机预览框 (CameraManager.java)。

getFramingRectInPreview()

/**
   * Like {@link #getFramingRect} but coordinates are in terms of the preview frame,
   * not UI / screen.
   *
   * @return {@link Rect} expressing barcode scan area in terms of the preview size
   */
  public synchronized Rect getFramingRectInPreview() {
    if (framingRectInPreview == null) {
      Rect framingRect = getFramingRect();
      if (framingRect == null) {
        return null;
      }
      Rect rect = new Rect(framingRect);
      Point cameraResolution = configManager.getCameraResolution();
      Point screenResolution = configManager.getScreenResolution();
      if (cameraResolution == null || screenResolution == null) {
        // Called early, before init even finished
        return null;
      }

      //add by tancolo
      if(screenResolution.x < screenResolution.y){
        // portrait
        rect.left = rect.left * cameraResolution.y / screenResolution.x;
        rect.right = rect.right * cameraResolution.y / screenResolution.x;
        rect.top = rect.top * cameraResolution.x / screenResolution.y;
        rect.bottom = rect.bottom * cameraResolution.x / screenResolution.y;
      } else {
        // landscape
        rect.left = rect.left * cameraResolution.x / screenResolution.x;
        rect.right = rect.right * cameraResolution.x / screenResolution.x;
        rect.top = rect.top * cameraResolution.y / screenResolution.y;
        rect.bottom = rect.bottom * cameraResolution.y / screenResolution.y;
      }
      // end add

//      rect.left = rect.left * cameraResolution.x / screenResolution.x;
//      rect.right = rect.right * cameraResolution.x / screenResolution.x;
//      rect.top = rect.top * cameraResolution.y / screenResolution.y;
//      rect.bottom = rect.bottom * cameraResolution.y / screenResolution.y;

      framingRectInPreview = rect;
    }
    return framingRectInPreview;
  }

step_4.修改PreviewCallback.java

onPreviewFrame()

  @Override
  public void onPreviewFrame(byte[] data, Camera camera) {
    Point cameraResolution = configManager.getCameraResolution();
    Handler thePreviewHandler = previewHandler;

    if (cameraResolution != null && thePreviewHandler != null) {
      //add by tancolo
      Point screenResolution = configManager.getScreenResolution();
      Message message;
      if (screenResolution.x < screenResolution.y){
        // portrait
        message = thePreviewHandler.obtainMessage(previewMessage, cameraResolution.y,
                cameraResolution.x, data);
      } else {
        // landscape
        message = thePreviewHandler.obtainMessage(previewMessage, cameraResolution.x,
                cameraResolution.y, data);
      }
//      Message message = thePreviewHandler.obtainMessage(previewMessage, cameraResolution.x,
//          cameraResolution.y, data);
      //end add

      message.sendToTarget();
      previewHandler = null;
    } else {
      Log.d(TAG, "Got preview callback, but no handler or resolution available");
    }
  }

step_5.DecodeHandler.java

decode()

  private void decode(byte[] data, int width, int height) {
    long start = System.currentTimeMillis();


    //add by tancolo
    if (width < height) {
      // portrait
      byte[] rotatedData = new byte[data.length];
      for (int x = 0; x < width; x++) {
        for (int y = 0; y < height; y++)
          rotatedData[y * width + width - x - 1] = data[y + x * height];
      }
      data = rotatedData;
    }
    //end add

    Result rawResult = null;
    PlanarYUVLuminanceSource source = activity.getCameraManager().buildLuminanceSource(data, width, height);
    if (source != null) {
      BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
      try {
        rawResult = multiFormatReader.decodeWithState(bitmap);
      } catch (ReaderException re) {
        // continue
      } finally {
        multiFormatReader.reset();
      }
    }

    Handler handler = activity.getHandler();
    if (rawResult != null) {
      // Don't log the barcode contents for security.
      long end = System.currentTimeMillis();
      Log.d(TAG, "Found barcode in " + (end - start) + " ms");
      if (handler != null) {
        Message message = Message.obtain(handler, R.id.decode_succeeded, rawResult);
        Bundle bundle = new Bundle();
        bundleThumbnail(source, bundle);        
        message.setData(bundle);
        message.sendToTarget();
      }
    } else {
      if (handler != null) {
        Message message = Message.obtain(handler, R.id.decode_failed);
        message.sendToTarget();
      }
    }
  }

step_6.运行Over,验证效果。

Demo:

https://github.com/zj614android/ZxingPortrait

Thanks:

Android二维码扫描的简单实现及源码分析

Google ZXing系列讲解(一)——导入AS
Google ZXing系列讲解(二)——生成WIFi二维码
Google ZXing系列讲解(三)——ZXing 目录结构与主体流程
Google ZXing系列讲解(四)——ZXing 解决竖屏扫描问题
Google ZXing系列讲解(五)——ZXing 仿微信扫描UI

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值