二维码

布局================================================================

mian_activity----------------------------------------------------------------------------------

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.daydayup.day07_erwei.MainActivity">


    <ImageView
        android:id="@+id/scan"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:src="@drawable/sao_hei" />

    <TextView
        android:id="@+id/result_text"
        android:text="结果:"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

activity_capture------------------------------------------------------------------------------------------------------

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/transparent"
    android:orientation="vertical" >

    <SurfaceView
        android:id="@+id/capture_preview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <RelativeLayout
        android:id="@+id/capture_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <ImageView
            android:id="@+id/capture_mask_top"
            android:layout_width="match_parent"
            android:layout_height="120dp"
            android:layout_alignParentTop="true"
            android:background="@drawable/shadow" />

        <RelativeLayout
            android:id="@+id/capture_crop_view"
            android:layout_width="200dp"
            android:layout_height="200dp"
            android:layout_below="@id/capture_mask_top"
            android:layout_centerHorizontal="true"
            android:background="@drawable/qr_code_bg" >

            <ImageView
                android:id="@+id/capture_scan_line"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentTop="true"
                android:layout_marginBottom="5dp"
                android:layout_marginTop="5dp"
                android:src="@drawable/scan_line" />
        </RelativeLayout>

        <ImageView
            android:id="@+id/capture_mask_bottom"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_below="@id/capture_crop_view"
            android:background="@drawable/shadow" />

        <ImageView
            android:id="@+id/capture_mask_left"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_above="@id/capture_mask_bottom"
            android:layout_alignParentLeft="true"
            android:layout_below="@id/capture_mask_top"
            android:layout_toLeftOf="@id/capture_crop_view"
            android:background="@drawable/shadow" />

        <ImageView
            android:id="@+id/capture_mask_right"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_above="@id/capture_mask_bottom"
            android:layout_alignParentRight="true"
            android:layout_below="@id/capture_mask_top"
            android:layout_toRightOf="@id/capture_crop_view"
            android:background="@drawable/shadow" />
    </RelativeLayout>

</RelativeLayout>

activity_result----------------------------------------------------------------------------------------------------

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white"
    android:gravity="center_horizontal"
    android:orientation="vertical" >

    <ImageView
        android:id="@+id/result_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@android:color/darker_gray"
        android:scaleType="fitXY" />

    <TextView
        android:id="@+id/result_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:layout_marginTop="20dp"
        android:background="#D8D8D8"
        android:gravity="left|top"
        android:padding="10dp"
        android:textColor="@android:color/black"
        android:textSize="14sp" />

</LinearLayout>

Values.ids.xml

package com.daydayup.day07_erwei.qrcode;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.TypedValue;
import android.widget.ImageView;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;

import com.daydayup.day07_erwei.R;
import com.daydayup.day07_erwei.qrcode.decode.DecodeThread;


public class ResultActivity extends Activity {

   private ImageView mResultImage;
   private TextView mResultText;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_result);

      Bundle extras = getIntent().getExtras();

      mResultImage = (ImageView) findViewById(R.id.result_image);
      mResultText = (TextView) findViewById(R.id.result_text);

      if (null != extras) {
         int width = extras.getInt("width");
         int height = extras.getInt("height");

         LayoutParams lps = new LayoutParams(width, height);
         lps.topMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 30, getResources().getDisplayMetrics());
         lps.leftMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, getResources().getDisplayMetrics());
         lps.rightMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, getResources().getDisplayMetrics());
         
         mResultImage.setLayoutParams(lps);

         String result = extras.getString("result");
         mResultText.setText(result);

         Bitmap barcode = null;
         byte[] compressedBitmap = extras.getByteArray(DecodeThread.BARCODE_BITMAP);
         if (compressedBitmap != null) {
            barcode = BitmapFactory.decodeByteArray(compressedBitmap, 0, compressedBitmap.length, null);
            // Mutable copy:
            barcode = barcode.copy(Bitmap.Config.RGB_565, true);
         }

         mResultImage.setImageBitmap(barcode);
      }
   }
}

MianActivity================================================================

package com.daydayup.day07_erwei;

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import com.daydayup.day07_erwei.qrcode.CaptureActivity;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity====";
    private final int REQUEST_CODE = 0;
    private TextView result_tv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initPermission();

        ImageView scan = findViewById(R.id.scan);
        result_tv = findViewById(R.id.result_text);
        scan.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //点击开始扫描

                Intent intent = new Intent(MainActivity.this, CaptureActivity.class);

                startActivityForResult(intent,REQUEST_CODE);

            }
        });
    }

    private void initPermission() {
        if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(MainActivity.this, new String[]
                    {Manifest.permission.CAMERA}, 1);
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        Log.d(TAG, "接收到数据-----: ");
        Bundle extras = data.getBundleExtra("data");
        String result = extras.getString("result");
        result_tv.setText(result+"----------");

    }
}

AutoFocusManage================================================

/*
 * Copyright (C) 2012 ZXing authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.daydayup.day07_erwei.qrcode.camera;

import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.RejectedExecutionException;
import android.annotation.SuppressLint;
import android.content.Context;
import android.hardware.Camera;
import android.os.AsyncTask;
import android.os.Build;
import android.util.Log;

public class AutoFocusManager implements Camera.AutoFocusCallback {

   private static final String TAG = AutoFocusManager.class.getSimpleName();

   private static final long AUTO_FOCUS_INTERVAL_MS = 2000L;
   private static final Collection<String> FOCUS_MODES_CALLING_AF;

   static {
      FOCUS_MODES_CALLING_AF = new ArrayList<String>(2);
      FOCUS_MODES_CALLING_AF.add(Camera.Parameters.FOCUS_MODE_AUTO);
      FOCUS_MODES_CALLING_AF.add(Camera.Parameters.FOCUS_MODE_MACRO);
   }

   private boolean stopped;
   private boolean focusing;
   private final boolean useAutoFocus;
   private final Camera camera;
   private AsyncTask<?, ?, ?> outstandingTask;

   public AutoFocusManager(Context context, Camera camera) {
      this.camera = camera;
      String currentFocusMode = camera.getParameters().getFocusMode();
      useAutoFocus = FOCUS_MODES_CALLING_AF.contains(currentFocusMode);
      Log.i(TAG, "Current focus mode '" + currentFocusMode + "'; use auto focus? " + useAutoFocus);
      start();
   }

   @Override
   public synchronized void onAutoFocus(boolean success, Camera theCamera) {
      focusing = false;
      autoFocusAgainLater();
   }

   @SuppressLint("NewApi")
   private synchronized void autoFocusAgainLater() {
      if (!stopped && outstandingTask == null) {
         AutoFocusTask newTask = new AutoFocusTask();
         try {
            if (Build.VERSION.SDK_INT >= 11) {
               newTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
            } else {
               newTask.execute();
            }
            outstandingTask = newTask;
         } catch (RejectedExecutionException ree) {
            Log.w(TAG, "Could not request auto focus", ree);
         }
      }
   }

   public synchronized void start() {
      if (useAutoFocus) {
         outstandingTask = null;
         if (!stopped && !focusing) {
            try {
               camera.autoFocus(this);
               focusing = true;
            } catch (RuntimeException re) {
               // Have heard RuntimeException reported in Android 4.0.x+;
               // continue?
               Log.w(TAG, "Unexpected exception while focusing", re);
               // Try again later to keep cycle going
               autoFocusAgainLater();
            }
         }
      }
   }

   private synchronized void cancelOutstandingTask() {
      if (outstandingTask != null) {
         if (outstandingTask.getStatus() != AsyncTask.Status.FINISHED) {
            outstandingTask.cancel(true);
         }
         outstandingTask = null;
      }
   }

   public synchronized void stop() {
      stopped = true;
      if (useAutoFocus) {
         cancelOutstandingTask();
         // Doesn't hurt to call this even if not focusing
         try {
            camera.cancelAutoFocus();
         } catch (RuntimeException re) {
            // Have heard RuntimeException reported in Android 4.0.x+;
            // continue?
            Log.w(TAG, "Unexpected exception while cancelling focusing", re);
         }
      }
   }

   private final class AutoFocusTask extends AsyncTask<Object, Object, Object> {
      @Override
      protected Object doInBackground(Object... voids) {
         try {
            Thread.sleep(AUTO_FOCUS_INTERVAL_MS);
         } catch (InterruptedException e) {
            // continue
         }
         start();
         return null;
      }
   }

}

CameraConfigurationManager======================================

/*
 * Copyright (C) 2008 ZXing authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.daydayup.day07_erwei.qrcode.camera;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Point;
import android.hardware.Camera;
import android.util.Log;
import android.view.Display;
import android.view.WindowManager;

/**
 * 
 * 邮箱: 1076559197@qq.com | tauchen1990@gmail.com
 * 
 * 作者: 陈涛
 * 
 * 日期: 2014年8月20日
 * 
 * 描述: 该类主要负责设置相机的参数信息,获取最佳的预览界面
 * 
 */
public final class CameraConfigurationManager {

   private static final String TAG = "CameraConfiguration";

   private static final int MIN_PREVIEW_PIXELS = 480 * 320;
   private static final double MAX_ASPECT_DISTORTION = 0.15;

   private final Context context;

   // 屏幕分辨率
   private Point screenResolution;
   // 相机分辨率
   private Point cameraResolution;

   public CameraConfigurationManager(Context context) {
      this.context = context;
   }

   public void initFromCameraParameters(Camera camera) {
      Camera.Parameters parameters = camera.getParameters();
      WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
      Display display = manager.getDefaultDisplay();
      Point theScreenResolution = new Point();
      theScreenResolution = getDisplaySize(display);

      screenResolution = theScreenResolution;
      Log.i(TAG, "Screen resolution: " + screenResolution);

      /** 因为换成了竖屏显示,所以不替换屏幕宽高得出的预览图是变形的 */
      Point screenResolutionForCamera = new Point();
      screenResolutionForCamera.x = screenResolution.x;
      screenResolutionForCamera.y = screenResolution.y;

      if (screenResolution.x < screenResolution.y) {
         screenResolutionForCamera.x = screenResolution.y;
         screenResolutionForCamera.y = screenResolution.x;
      }

      cameraResolution = findBestPreviewSizeValue(parameters, screenResolutionForCamera);
      Log.i(TAG, "Camera resolution x: " + cameraResolution.x);
      Log.i(TAG, "Camera resolution y: " + cameraResolution.y);
   }

   @SuppressWarnings("deprecation")
   @SuppressLint("NewApi")
   private Point getDisplaySize(final Display display) {
      final Point point = new Point();
      try {
         display.getSize(point);
      } catch (NoSuchMethodError ignore) {
         point.x = display.getWidth();
         point.y = display.getHeight();
      }
      return point;
   }

   public void setDesiredCameraParameters(Camera camera, boolean safeMode) {
      Camera.Parameters parameters = camera.getParameters();

      if (parameters == null) {
         Log.w(TAG, "Device error: no camera parameters are available. Proceeding without configuration.");
         return;
      }

      Log.i(TAG, "Initial camera parameters: " + parameters.flatten());

      if (safeMode) {
         Log.w(TAG, "In camera config safe mode -- most settings will not be honored");
      }

      parameters.setPreviewSize(cameraResolution.x, cameraResolution.y);
      camera.setParameters(parameters);

      Camera.Parameters afterParameters = camera.getParameters();
      Camera.Size afterSize = afterParameters.getPreviewSize();
      if (afterSize != null && (cameraResolution.x != afterSize.width || cameraResolution.y != afterSize.height)) {
         Log.w(TAG, "Camera said it supported preview size " + cameraResolution.x + 'x' + cameraResolution.y + ", but after setting it, preview size is " + afterSize.width + 'x' + afterSize.height);
         cameraResolution.x = afterSize.width;
         cameraResolution.y = afterSize.height;
      }

      /** 设置相机预览为竖屏 */
      camera.setDisplayOrientation(90);
   }

   public Point getCameraResolution() {
      return cameraResolution;
   }

   public Point getScreenResolution() {
      return screenResolution;
   }

   /**
    * 从相机支持的分辨率中计算出最适合的预览界面尺寸
    * 
    * @param parameters
    * @param screenResolution
    * @return
    */
   private Point findBestPreviewSizeValue(Camera.Parameters parameters, Point screenResolution) {
      List<Camera.Size> rawSupportedSizes = parameters.getSupportedPreviewSizes();
      if (rawSupportedSizes == null) {
         Log.w(TAG, "Device returned no supported preview sizes; using default");
         Camera.Size defaultSize = parameters.getPreviewSize();
         return new Point(defaultSize.width, defaultSize.height);
      }

      // Sort by size, descending
      List<Camera.Size> supportedPreviewSizes = new ArrayList<Camera.Size>(rawSupportedSizes);
      Collections.sort(supportedPreviewSizes, new Comparator<Camera.Size>() {
         @Override
         public int compare(Camera.Size a, Camera.Size b) {
            int aPixels = a.height * a.width;
            int bPixels = b.height * b.width;
            if (bPixels < aPixels) {
               return -1;
            }
            if (bPixels > aPixels) {
               return 1;
            }
            return 0;
         }
      });

      if (Log.isLoggable(TAG, Log.INFO)) {
         StringBuilder previewSizesString = new StringBuilder();
         for (Camera.Size supportedPreviewSize : supportedPreviewSizes) {
            previewSizesString.append(supportedPreviewSize.width).append('x').append(supportedPreviewSize.height).append(' ');
         }
         Log.i(TAG, "Supported preview sizes: " + previewSizesString);
      }

      double screenAspectRatio = (double) screenResolution.x / (double) screenResolution.y;

      // Remove sizes that are unsuitable
      Iterator<Camera.Size> it = supportedPreviewSizes.iterator();
      while (it.hasNext()) {
         Camera.Size supportedPreviewSize = it.next();
         int realWidth = supportedPreviewSize.width;
         int realHeight = supportedPreviewSize.height;
         if (realWidth * realHeight < MIN_PREVIEW_PIXELS) {
            it.remove();
            continue;
         }

         boolean isCandidatePortrait = realWidth < realHeight;
         int maybeFlippedWidth = isCandidatePortrait ? realHeight : realWidth;
         int maybeFlippedHeight = isCandidatePortrait ? realWidth : realHeight;

         double aspectRatio = (double) maybeFlippedWidth / (double) maybeFlippedHeight;
         double distortion = Math.abs(aspectRatio - screenAspectRatio);
         if (distortion > MAX_ASPECT_DISTORTION) {
            it.remove();
            continue;
         }

         if (maybeFlippedWidth == screenResolution.x && maybeFlippedHeight == screenResolution.y) {
            Point exactPoint = new Point(realWidth, realHeight);
            Log.i(TAG, "Found preview size exactly matching screen size: " + exactPoint);
            return exactPoint;
         }
      }

      // If no exact match, use largest preview size. This was not a great
      // idea on older devices because
      // of the additional computation needed. We're likely to get here on
      // newer Android 4+ devices, where
      // the CPU is much more powerful.
      if (!supportedPreviewSizes.isEmpty()) {
         Camera.Size largestPreview = supportedPreviewSizes.get(0);
         Point largestSize = new Point(largestPreview.width, largestPreview.height);
         Log.i(TAG, "Using largest suitable preview size: " + largestSize);
         return largestSize;
      }

      // If there is nothing at all suitable, return current preview size
      Camera.Size defaultPreview = parameters.getPreviewSize();
      Point defaultSize = new Point(defaultPreview.width, defaultPreview.height);
      Log.i(TAG, "No suitable preview sizes, using default: " + defaultSize);

      return defaultSize;
   }
}

CameraManager===============================================

/*
 * Copyright (C) 2008 ZXing authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.daydayup.day07_erwei.qrcode.camera;

import java.io.IOException;

import android.content.Context;
import android.graphics.Point;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.os.Handler;
import android.util.Log;
import android.view.SurfaceHolder;

import com.daydayup.day07_erwei.qrcode.camera.open.OpenCameraInterface;

/**
 * This object wraps the Camera service object and expects to be the only one
 * talking to it. The implementation encapsulates the steps needed to take
 * preview-sized images, which are used for both preview and decoding.
 * 
 * @author dswitkin@google.com (Daniel Switkin)
 */
public class CameraManager {

   private static final String TAG = CameraManager.class.getSimpleName();

   private final Context context;
   private final CameraConfigurationManager configManager;
   private Camera camera;
   private AutoFocusManager autoFocusManager;

   private boolean initialized;
   private boolean previewing;
   private int requestedCameraId = -1;
   /**
    * Preview frames are delivered here, which we pass on to the registered
    * handler. Make sure to clear the handler so it will only receive one
    * message.
    */
   private final PreviewCallback previewCallback;

   public CameraManager(Context context) {
      this.context = context;
      this.configManager = new CameraConfigurationManager(context);
      previewCallback = new PreviewCallback(configManager);
   }

   /**
    * Opens the camera driver and initializes the hardware parameters.
    * 
    * @param holder
    *            The surface object which the camera will draw preview frames
    *            into.
    * @throws IOException
    *             Indicates the camera driver failed to open.
    */
   public synchronized void openDriver(SurfaceHolder holder) throws IOException {
      Camera theCamera = camera;
      if (theCamera == null) {

         if (requestedCameraId >= 0) {
            theCamera = OpenCameraInterface.open(requestedCameraId);
         } else {
            theCamera = OpenCameraInterface.open();
         }

         if (theCamera == null) {
            throw new IOException();
         }
         camera = theCamera;
      }
      theCamera.setPreviewDisplay(holder);

      if (!initialized) {
         initialized = true;
         configManager.initFromCameraParameters(theCamera);
      }

      Camera.Parameters parameters = theCamera.getParameters();
      String parametersFlattened = parameters == null ? null : parameters.flatten(); // Save
                                                                  // these,
                                                                  // temporarily
      try {
         configManager.setDesiredCameraParameters(theCamera, false);
      } catch (RuntimeException re) {
         // Driver failed
         Log.w(TAG, "Camera rejected parameters. Setting only minimal safe-mode parameters");
         Log.i(TAG, "Resetting to saved camera params: " + parametersFlattened);
         // Reset:
         if (parametersFlattened != null) {
            parameters = theCamera.getParameters();
            parameters.unflatten(parametersFlattened);
            try {
               theCamera.setParameters(parameters);
               configManager.setDesiredCameraParameters(theCamera, true);
            } catch (RuntimeException re2) {
               // Well, darn. Give up
               Log.w(TAG, "Camera rejected even safe-mode parameters! No configuration");
            }
         }
      }

   }

   public synchronized boolean isOpen() {
      return camera != null;
   }

   /**
    * Closes the camera driver if still in use.
    */
   public synchronized void closeDriver() {
      if (camera != null) {
         camera.release();
         camera = null;
         // Make sure to clear these each time we close the camera, so that
         // any scanning rect
         // requested by intent is forgotten.
      }
   }

   /**
    * Asks the camera hardware to begin drawing preview frames to the screen.
    */
   public synchronized void startPreview() {
      Camera theCamera = camera;
      if (theCamera != null && !previewing) {
         theCamera.startPreview();
         previewing = true;
         autoFocusManager = new AutoFocusManager(context, camera);
      }
   }

   /**
    * Tells the camera to stop drawing preview frames.
    */
   public synchronized void stopPreview() {
      if (autoFocusManager != null) {
         autoFocusManager.stop();
         autoFocusManager = null;
      }
      if (camera != null && previewing) {
         camera.stopPreview();
         previewCallback.setHandler(null, 0);
         previewing = false;
      }
   }

   /**
    * A single preview frame will be returned to the handler supplied. The data
    * will arrive as byte[] in the message.obj field, with width and height
    * encoded as message.arg1 and message.arg2, respectively.
    * 
    * @param handler
    *            The handler to send the message to.
    * @param message
    *            The what field of the message to be sent.
    */
   public synchronized void requestPreviewFrame(Handler handler, int message) {
      Camera theCamera = camera;
      if (theCamera != null && previewing) {
         previewCallback.setHandler(handler, message);
         theCamera.setOneShotPreviewCallback(previewCallback);
      }
   }

   /**
    * Allows third party apps to specify the camera ID, rather than determine
    * it automatically based on available cameras and their orientation.
    * 
    * @param cameraId
    *            camera ID of the camera to use. A negative value means
    *            "no preference".
    */
   public synchronized void setManualCameraId(int cameraId) {
      requestedCameraId = cameraId;
   }

   /**
    * 获取相机分辨率
    * 
    * @return
    */
   public Point getCameraResolution() {
      return configManager.getCameraResolution();
   }

   public Size getPreviewSize() {
      if (null != camera) {
         return camera.getParameters().getPreviewSize();
      }
      return null;
   }
}

PreviewCallback================================================

/*
 * Copyright (C) 2010 ZXing authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.daydayup.day07_erwei.qrcode.camera;

import android.graphics.Point;
import android.hardware.Camera;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

public class PreviewCallback implements Camera.PreviewCallback {

   private static final String TAG = PreviewCallback.class.getSimpleName();

   private final CameraConfigurationManager configManager;
   private Handler previewHandler;
   private int previewMessage;

   public PreviewCallback(CameraConfigurationManager configManager) {
      this.configManager = configManager;
   }

   public void setHandler(Handler previewHandler, int previewMessage) {
      this.previewHandler = previewHandler;
      this.previewMessage = previewMessage;
   }

   @Override
   public void onPreviewFrame(byte[] data, Camera camera) {
      Point cameraResolution = configManager.getCameraResolution();
      Handler thePreviewHandler = previewHandler;
      if (cameraResolution != null && thePreviewHandler != null) {
         Message message = thePreviewHandler.obtainMessage(previewMessage, cameraResolution.x, cameraResolution.y, data);
         message.sendToTarget();
         previewHandler = null;
      } else {
         Log.d(TAG, "Got preview callback, but no handler or resolution available");
      }
   }

}

DecodeFormatManage============================================

/*
 * Copyright (C) 2010 ZXing authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.daydayup.day07_erwei.qrcode.decode;

import java.util.Collection;
import java.util.EnumSet;
import java.util.Set;

import com.google.zxing.BarcodeFormat;

public class DecodeFormatManager {

   // 1D解码
   private static final Set<BarcodeFormat> PRODUCT_FORMATS;
   private static final Set<BarcodeFormat> INDUSTRIAL_FORMATS;
   private static final Set<BarcodeFormat> ONE_D_FORMATS;

   // 二维码解码
   private static final Set<BarcodeFormat> QR_CODE_FORMATS;

   static {
      PRODUCT_FORMATS = EnumSet.of(BarcodeFormat.UPC_A, BarcodeFormat.UPC_E, BarcodeFormat.EAN_13, BarcodeFormat.EAN_8, BarcodeFormat.RSS_14, BarcodeFormat.RSS_EXPANDED);
      INDUSTRIAL_FORMATS = EnumSet.of(BarcodeFormat.CODE_39, BarcodeFormat.CODE_93, BarcodeFormat.CODE_128, BarcodeFormat.ITF, BarcodeFormat.CODABAR);
      ONE_D_FORMATS = EnumSet.copyOf(PRODUCT_FORMATS);
      ONE_D_FORMATS.addAll(INDUSTRIAL_FORMATS);

      QR_CODE_FORMATS = EnumSet.of(BarcodeFormat.QR_CODE);
   }

   public static Collection<BarcodeFormat> getQrCodeFormats() {
      return QR_CODE_FORMATS;
   }

   public static Collection<BarcodeFormat> getBarCodeFormats() {
      return ONE_D_FORMATS;
   }
}

DecodeHandler================================================

/*
 * Copyright (C) 2010 ZXing authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.daydayup.day07_erwei.qrcode.decode;

import java.io.ByteArrayOutputStream;
import java.util.Map;

import android.graphics.Bitmap;
import android.graphics.Rect;
import android.hardware.Camera.Size;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;

import com.daydayup.day07_erwei.R;
import com.daydayup.day07_erwei.qrcode.CaptureActivity;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.PlanarYUVLuminanceSource;
import com.google.zxing.ReaderException;
import com.google.zxing.Result;
import com.google.zxing.common.HybridBinarizer;

public class DecodeHandler extends Handler {

   private final CaptureActivity activity;
   private final MultiFormatReader multiFormatReader;
   private boolean running = true;

   public DecodeHandler(CaptureActivity activity, Map<DecodeHintType, Object> hints) {
      multiFormatReader = new MultiFormatReader();
      multiFormatReader.setHints(hints);
      this.activity = activity;
   }

   @Override
   public void handleMessage(Message message) {
      if (!running) {
         return;
      }
      switch (message.what) {
      case R.id.decode:
         decode((byte[]) message.obj, message.arg1, message.arg2);
         break;
      case R.id.quit:
         running = false;
         Looper.myLooper().quit();
         break;
      }
   }

   /**
    * Decode the data within the viewfinder rectangle, and time how long it
    * took. For efficiency, reuse the same reader objects from one decode to
    * the next.
    * 
    * @param data
    *            The YUV preview frame.
    * @param width
    *            The width of the preview frame.
    * @param height
    *            The height of the preview frame.
    */
   private void decode(byte[] data, int width, int height) {
      Size size = activity.getCameraManager().getPreviewSize();

      // 这里需要将获取的data翻转一下,因为相机默认拿的的横屏的数据
      byte[] rotatedData = new byte[data.length];
      for (int y = 0; y < size.height; y++) {
         for (int x = 0; x < size.width; x++)
            rotatedData[x * size.height + size.height - y - 1] = data[x + y * size.width];
      }

      // 宽高也要调整
      int tmp = size.width;
      size.width = size.height;
      size.height = tmp;

      Result rawResult = null;
      PlanarYUVLuminanceSource source = buildLuminanceSource(rotatedData, size.width, size.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.
         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();
         }
      }

   }

   private static void bundleThumbnail(PlanarYUVLuminanceSource source, Bundle bundle) {
      int[] pixels = source.renderThumbnail();
      int width = source.getThumbnailWidth();
      int height = source.getThumbnailHeight();
      Bitmap bitmap = Bitmap.createBitmap(pixels, 0, width, width, height, Bitmap.Config.ARGB_8888);
      ByteArrayOutputStream out = new ByteArrayOutputStream();
      bitmap.compress(Bitmap.CompressFormat.JPEG, 50, out);
      bundle.putByteArray(DecodeThread.BARCODE_BITMAP, out.toByteArray());
   }

   /**
    * A factory method to build the appropriate LuminanceSource object based on
    * the format of the preview buffers, as described by Camera.Parameters.
    * 
    * @param data
    *            A preview frame.
    * @param width
    *            The width of the image.
    * @param height
    *            The height of the image.
    * @return A PlanarYUVLuminanceSource instance.
    */
   public PlanarYUVLuminanceSource buildLuminanceSource(byte[] data, int width, int height) {
      Rect rect = activity.getCropRect();
      if (rect == null) {
         return null;
      }
      // Go ahead and assume it's YUV rather than die.
      return new PlanarYUVLuminanceSource(data, width, height, rect.left, rect.top, rect.width(), rect.height(), false);
   }

}

DecodeThread===================================================

/*
 * Copyright (C) 2008 ZXing authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.daydayup.day07_erwei.qrcode.decode;

import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Map;
import java.util.concurrent.CountDownLatch;

import android.os.Handler;
import android.os.Looper;

import com.daydayup.day07_erwei.qrcode.CaptureActivity;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.DecodeHintType;

/**
 * This thread does all the heavy lifting of decoding the images.
 * 
 * @author dswitkin@google.com (Daniel Switkin)
 */
public class DecodeThread extends Thread {

   public static final String BARCODE_BITMAP = "barcode_bitmap";

   public static final int BARCODE_MODE = 0X100;
   public static final int QRCODE_MODE = 0X200;
   public static final int ALL_MODE = 0X300;

   private final CaptureActivity activity;
   private final Map<DecodeHintType, Object> hints;
   private Handler handler;
   private final CountDownLatch handlerInitLatch;

   public DecodeThread(CaptureActivity activity, int decodeMode) {

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

      hints = new EnumMap<DecodeHintType, Object>(DecodeHintType.class);

      Collection<BarcodeFormat> decodeFormats = new ArrayList<BarcodeFormat>();
      decodeFormats.addAll(EnumSet.of(BarcodeFormat.AZTEC));
      decodeFormats.addAll(EnumSet.of(BarcodeFormat.PDF_417));

      switch (decodeMode) {
      case BARCODE_MODE:
         decodeFormats.addAll(DecodeFormatManager.getBarCodeFormats());
         break;

      case QRCODE_MODE:
         decodeFormats.addAll(DecodeFormatManager.getQrCodeFormats());
         break;

      case ALL_MODE:
         decodeFormats.addAll(DecodeFormatManager.getBarCodeFormats());
         decodeFormats.addAll(DecodeFormatManager.getQrCodeFormats());
         break;

      default:
         break;
      }

      hints.put(DecodeHintType.POSSIBLE_FORMATS, decodeFormats);
   }

   public Handler getHandler() {
      try {
         handlerInitLatch.await();
      } catch (InterruptedException ie) {
         // continue?
      }
      return handler;
   }

   @Override
   public void run() {
      Looper.prepare();
      handler = new DecodeHandler(activity, hints);
      handlerInitLatch.countDown();
      Looper.loop();
   }

}

BeepManager=================================================

/*
 * Copyright (C) 2010 ZXing authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.daydayup.day07_erwei.qrcode.utils;

import java.io.Closeable;
import java.io.IOException;

import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.AssetFileDescriptor;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Vibrator;
import android.preference.PreferenceManager;
import android.util.Log;

import com.daydayup.day07_erwei.R;


/**
 * Manages beeps and vibrations for {@link CaptureActivity}.
 */
public class BeepManager implements MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener, Closeable {

   private static final String TAG = BeepManager.class.getSimpleName();

   private static final float BEEP_VOLUME = 0.10f;
   private static final long VIBRATE_DURATION = 200L;

   private final Activity activity;
   private MediaPlayer mediaPlayer;
   private boolean playBeep;
   private boolean vibrate;

   public BeepManager(Activity activity) {
      this.activity = activity;
      this.mediaPlayer = null;
      updatePrefs();
   }

   private synchronized void updatePrefs() {
      SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
      playBeep = shouldBeep(prefs, activity);
      vibrate = true;
      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.
         activity.setVolumeControlStream(AudioManager.STREAM_MUSIC);
         mediaPlayer = buildMediaPlayer(activity);
      }
   }

   public synchronized void playBeepSoundAndVibrate() {
      if (playBeep && mediaPlayer != null) {
         mediaPlayer.start();
      }
      if (vibrate) {
         Vibrator vibrator = (Vibrator) activity.getSystemService(Context.VIBRATOR_SERVICE);
         vibrator.vibrate(VIBRATE_DURATION);
      }
   }

   private static boolean shouldBeep(SharedPreferences prefs, Context activity) {
      boolean shouldPlayBeep = true;
      if (shouldPlayBeep) {
         // See if sound settings overrides this
         AudioManager audioService = (AudioManager) activity.getSystemService(Context.AUDIO_SERVICE);
         if (audioService.getRingerMode() != AudioManager.RINGER_MODE_NORMAL) {
            shouldPlayBeep = false;
         }
      }
      return shouldPlayBeep;
   }

   private MediaPlayer buildMediaPlayer(Context activity) {
      MediaPlayer mediaPlayer = new MediaPlayer();
      mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
      mediaPlayer.setOnCompletionListener(this);
      mediaPlayer.setOnErrorListener(this);
      try {
         AssetFileDescriptor file = activity.getResources().openRawResourceFd(R.raw.beep);
         try {
            mediaPlayer.setDataSource(file.getFileDescriptor(), file.getStartOffset(), file.getLength());
         } finally {
            file.close();
         }
         mediaPlayer.setVolume(BEEP_VOLUME, BEEP_VOLUME);
         mediaPlayer.prepare();
         return mediaPlayer;
      } catch (IOException ioe) {
         Log.w(TAG, ioe);
         mediaPlayer.release();
         return null;
      }
   }

   @Override
   public void onCompletion(MediaPlayer mp) {
      // When the beep has finished playing, rewind to queue up another one.
      mp.seekTo(0);
   }

   @Override
   public synchronized boolean onError(MediaPlayer mp, int what, int extra) {
      if (what == MediaPlayer.MEDIA_ERROR_SERVER_DIED) {
         // we are finished, so put up an appropriate error toast if required
         // and finish
         activity.finish();
      } else {
         // possibly media player error, so release and recreate
         mp.release();
         mediaPlayer = null;
         updatePrefs();
      }
      return true;
   }

   @Override
   public synchronized void close() {
      if (mediaPlayer != null) {
         mediaPlayer.release();
         mediaPlayer = null;
      }
   }

}

CaptureActivityHandler==========================================

/*
 * Copyright (C) 2008 ZXing authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.daydayup.day07_erwei.qrcode.utils;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;

import com.daydayup.day07_erwei.R;
import com.daydayup.day07_erwei.qrcode.CaptureActivity;
import com.daydayup.day07_erwei.qrcode.camera.CameraManager;
import com.daydayup.day07_erwei.qrcode.decode.DecodeThread;
import com.google.zxing.Result;

/**
 * This class handles all the messaging which comprises the state machine for
 * capture.
 * 
 * @author dswitkin@google.com (Daniel Switkin)
 */
public class CaptureActivityHandler extends Handler {

   private final CaptureActivity activity;
   private final DecodeThread decodeThread;
   private final CameraManager cameraManager;
   private State state;

   private enum State {
      PREVIEW, SUCCESS, DONE
   }

   public CaptureActivityHandler(CaptureActivity activity, CameraManager cameraManager, int decodeMode) {
      this.activity = activity;
      decodeThread = new DecodeThread(activity, decodeMode);
      decodeThread.start();
      state = State.SUCCESS;

      // Start ourselves capturing previews and decoding.
      this.cameraManager = cameraManager;
      cameraManager.startPreview();
      restartPreviewAndDecode();
   }

   @Override
   public void handleMessage(Message message) {
      switch (message.what) {
      case R.id.restart_preview:
         restartPreviewAndDecode();
         break;
      case R.id.decode_succeeded:
         state = State.SUCCESS;
         Bundle bundle = message.getData();

         activity.handleDecode((Result) message.obj, bundle);
         break;
      case R.id.decode_failed:
         // We're decoding as fast as possible, so when one decode fails,
         // start another.
         state = State.PREVIEW;
         cameraManager.requestPreviewFrame(decodeThread.getHandler(), R.id.decode);
         break;
      case R.id.return_scan_result:
         activity.setResult(Activity.RESULT_OK, (Intent) message.obj);
         activity.finish();
         break;
      }
   }

   public void quitSynchronously() {
      state = State.DONE;
      cameraManager.stopPreview();
      Message quit = Message.obtain(decodeThread.getHandler(), R.id.quit);
      quit.sendToTarget();
      try {
         // Wait at most half a second; should be enough time, and onPause()
         // will timeout quickly
         decodeThread.join(500L);
      } catch (InterruptedException e) {
         // continue
      }

      // Be absolutely sure we don't send any queued up messages
      removeMessages(R.id.decode_succeeded);
      removeMessages(R.id.decode_failed);
   }

   private void restartPreviewAndDecode() {
      if (state == State.SUCCESS) {
         state = State.PREVIEW;
         cameraManager.requestPreviewFrame(decodeThread.getHandler(), R.id.decode);
      }
   }

}

InactivityTimer=====================================================

/*
 * Copyright (C) 2010 ZXing authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.daydayup.day07_erwei.qrcode.utils;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.AsyncTask;
import android.os.BatteryManager;
import android.os.Build;
import android.util.Log;

/**
 * Finishes an activity after a period of inactivity if the device is on battery
 * power.
 */
public class InactivityTimer {

   private static final String TAG = InactivityTimer.class.getSimpleName();

   private static final long INACTIVITY_DELAY_MS = 5 * 60 * 1000L;

   private Activity activity;
   private BroadcastReceiver powerStatusReceiver;
   private boolean registered;
   private AsyncTask<Object, Object, Object> inactivityTask;

   public InactivityTimer(Activity activity) {
      this.activity = activity;
      powerStatusReceiver = new PowerStatusReceiver();
      registered = false;
      onActivity();
   }

   @SuppressLint("NewApi")
   public synchronized void onActivity() {
      cancel();
      inactivityTask = new InactivityAsyncTask();
      if (Build.VERSION.SDK_INT >= 11) {
         inactivityTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
      } else {
         inactivityTask.execute();
      }
   }

   public synchronized void onPause() {
      cancel();
      if (registered) {
         activity.unregisterReceiver(powerStatusReceiver);
         registered = false;
      } else {
         Log.w(TAG, "PowerStatusReceiver was never registered?");
      }
   }

   public synchronized void onResume() {
      if (registered) {
         Log.w(TAG, "PowerStatusReceiver was already registered?");
      } else {
         activity.registerReceiver(powerStatusReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
         registered = true;
      }
      onActivity();
   }

   private synchronized void cancel() {
      AsyncTask<?, ?, ?> task = inactivityTask;
      if (task != null) {
         task.cancel(true);
         inactivityTask = null;
      }
   }

   public void shutdown() {
      cancel();
   }

   private class PowerStatusReceiver extends BroadcastReceiver {
      @Override
      public void onReceive(Context context, Intent intent) {
         if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
            // 0 indicates that we're on battery
            boolean onBatteryNow = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) <= 0;
            if (onBatteryNow) {
               InactivityTimer.this.onActivity();
            } else {
               InactivityTimer.this.cancel();
            }
         }
      }
   }

   private class InactivityAsyncTask extends AsyncTask<Object, Object, Object> {
      @Override
      protected Object doInBackground(Object... objects) {
         try {
            Thread.sleep(INACTIVITY_DELAY_MS);
            Log.i(TAG, "Finishing activity due to inactivity");
            activity.finish();
         } catch (InterruptedException e) {
            // continue without killing
         }
         return null;
      }
   }

}

CaptureActivity=================================================

/*
 * Copyright (C) 2008 ZXing authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.daydayup.day07_erwei.qrcode;

import java.io.IOException;
import java.lang.reflect.Field;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.Window;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.ImageView;
import android.widget.RelativeLayout;

import com.daydayup.day07_erwei.MainActivity;
import com.daydayup.day07_erwei.R;
import com.daydayup.day07_erwei.qrcode.camera.CameraManager;
import com.daydayup.day07_erwei.qrcode.decode.DecodeThread;
import com.daydayup.day07_erwei.qrcode.utils.BeepManager;
import com.daydayup.day07_erwei.qrcode.utils.CaptureActivityHandler;
import com.daydayup.day07_erwei.qrcode.utils.InactivityTimer;
import com.google.zxing.Result;

/**
 * This activity opens the camera and does the actual scanning on a background
 * thread. It draws a viewfinder to help the user place the barcode correctly,
 * shows feedback as the image processing is happening, and then overlays the
 * results when a scan is successful.
 *
 * @author dswitkin@google.com (Daniel Switkin)
 * @author Sean Owen
 */
public final class CaptureActivity extends Activity implements SurfaceHolder.Callback {

    private static final String TAG = CaptureActivity.class.getSimpleName()+"-----------";

    private CameraManager cameraManager;
    private CaptureActivityHandler handler;
    private InactivityTimer inactivityTimer;
    private BeepManager beepManager;

    private SurfaceView scanPreview = null;
    private RelativeLayout scanContainer;
    private RelativeLayout scanCropView;
    private ImageView scanLine;

    private Rect mCropRect = null;

    public Handler getHandler() {
        return handler;
    }

    public CameraManager getCameraManager() {
        return cameraManager;
    }

    private boolean isHasSurface = false;

    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);

        Window window = getWindow();
        window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        setContentView(R.layout.activity_capture);

        scanPreview = (SurfaceView) findViewById(R.id.capture_preview);
        scanContainer = (RelativeLayout) findViewById(R.id.capture_container);
        scanCropView = (RelativeLayout) findViewById(R.id.capture_crop_view);
        scanLine = (ImageView) findViewById(R.id.capture_scan_line);

        inactivityTimer = new InactivityTimer(this);
        beepManager = new BeepManager(this);

        TranslateAnimation animation = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, 0.0f, Animation.RELATIVE_TO_PARENT, 0.0f, Animation.RELATIVE_TO_PARENT, 0.0f, Animation.RELATIVE_TO_PARENT,
                0.9f);
        animation.setDuration(4500);
        animation.setRepeatCount(-1);
        animation.setRepeatMode(Animation.RESTART);
        scanLine.startAnimation(animation);
    }

    @Override
    protected void onResume() {
        super.onResume();

        // CameraManager must be initialized here, not in onCreate(). This is
        // necessary because we don't
        // want to open the camera driver and measure the screen size if we're
        // going to show the help on
        // first launch. That led to bugs where the scanning rectangle was the
        // wrong size and partially
        // off screen.
        cameraManager = new CameraManager(getApplication());

        handler = null;

        if (isHasSurface) {
            // The activity was paused but not stopped, so the surface still
            // exists. Therefore
            // surfaceCreated() won't be called, so init the camera here.
            initCamera(scanPreview.getHolder());
        } else {
            // Install the callback and wait for surfaceCreated() to init the
            // camera.
            scanPreview.getHolder().addCallback(this);
        }

        inactivityTimer.onResume();
    }

    @Override
    protected void onPause() {
        if (handler != null) {
            handler.quitSynchronously();
            handler = null;
        }
        inactivityTimer.onPause();
        beepManager.close();
        cameraManager.closeDriver();
        if (!isHasSurface) {
            scanPreview.getHolder().removeCallback(this);
        }
        super.onPause();
    }

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

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        if (holder == null) {
            Log.e(TAG, "*** WARNING *** surfaceCreated() gave us a null surface!");
        }
        if (!isHasSurface) {
            isHasSurface = true;
            initCamera(holder);
        }
    }

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

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    /**
     * A valid barcode has been found, so give an indication of success and show
     * the results.
     *
     * @param rawResult The contents of the barcode.
     * @param bundle    The extras
     */
    public void handleDecode(Result rawResult, Bundle bundle) {
        inactivityTimer.onActivity();
        beepManager.playBeepSoundAndVibrate();

        bundle.putInt("width", mCropRect.width());
        bundle.putInt("height", mCropRect.height());
        bundle.putString("result", rawResult.getText());

        Intent intent = getIntent();
        intent.putExtra("data", bundle);
        setResult(1, intent);

        Log.d(TAG, "结果-------");

        finish();
//        startActivity(new Intent(CaptureActivity.this, ResultActivity.class).putExtras(bundle));
    }

    private void initCamera(SurfaceHolder surfaceHolder) {
        if (surfaceHolder == null) {
            throw new IllegalStateException("No SurfaceHolder provided");
        }
        if (cameraManager.isOpen()) {
            Log.w(TAG, "initCamera() while already open -- late SurfaceView callback?");
            return;
        }
        try {
            cameraManager.openDriver(surfaceHolder);
            // Creating the handler starts the preview, which can also throw a
            // RuntimeException.
            if (handler == null) {
                handler = new CaptureActivityHandler(this, cameraManager, DecodeThread.ALL_MODE);
            }

            initCrop();
        } catch (IOException ioe) {
            Log.w(TAG, ioe);
            displayFrameworkBugMessageAndExit();
        } catch (RuntimeException e) {
            // Barcode Scanner has seen crashes in the wild of this variety:
            // java.?lang.?RuntimeException: Fail to connect to camera service
            Log.w(TAG, "Unexpected error initializing camera", e);
            displayFrameworkBugMessageAndExit();
        }
    }

    private void displayFrameworkBugMessageAndExit() {
        // camera error
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle(getString(R.string.app_name));
        builder.setMessage("相机打开出错,请稍后重试");
        builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {
                finish();
            }

        });
        builder.setOnCancelListener(new DialogInterface.OnCancelListener() {

            @Override
            public void onCancel(DialogInterface dialog) {
                finish();
            }
        });
        builder.show();
    }

    public void restartPreviewAfterDelay(long delayMS) {
        if (handler != null) {
            handler.sendEmptyMessageDelayed(R.id.restart_preview, delayMS);
        }
    }

    public Rect getCropRect() {
        return mCropRect;
    }

    /**
     * 初始化截取的矩形区域
     */
    private void initCrop() {
        int cameraWidth = cameraManager.getCameraResolution().y;
        int cameraHeight = cameraManager.getCameraResolution().x;

        /** 获取布局中扫描框的位置信息 */
        int[] location = new int[2];
        scanCropView.getLocationInWindow(location);

        int cropLeft = location[0];
        int cropTop = location[1] - getStatusBarHeight();

        int cropWidth = scanCropView.getWidth();
        int cropHeight = scanCropView.getHeight();

        /** 获取布局容器的宽高 */
        int containerWidth = scanContainer.getWidth();
        int containerHeight = scanContainer.getHeight();

        /** 计算最终截取的矩形的左上角顶点x坐标 */
        int x = cropLeft * cameraWidth / containerWidth;
        /** 计算最终截取的矩形的左上角顶点y坐标 */
        int y = cropTop * cameraHeight / containerHeight;

        /** 计算最终截取的矩形的宽度 */
        int width = cropWidth * cameraWidth / containerWidth;
        /** 计算最终截取的矩形的高度 */
        int height = cropHeight * cameraHeight / containerHeight;

        /** 生成最终的截取的矩形 */
        mCropRect = new Rect(x, y, width + x, height + y);
    }

    private int getStatusBarHeight() {
        try {
            Class<?> c = Class.forName("com.android.internal.R$dimen");
            Object obj = c.newInstance();
            Field field = c.getField("status_bar_height");
            int x = Integer.parseInt(field.get(obj).toString());
            return getResources().getDimensionPixelSize(x);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }
}

ResultActivity==========================================================

package com.daydayup.day07_erwei.qrcode;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.TypedValue;
import android.widget.ImageView;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;

import com.daydayup.day07_erwei.R;
import com.daydayup.day07_erwei.qrcode.decode.DecodeThread;


public class ResultActivity extends Activity {

   private ImageView mResultImage;
   private TextView mResultText;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_result);

      Bundle extras = getIntent().getExtras();

      mResultImage = (ImageView) findViewById(R.id.result_image);
      mResultText = (TextView) findViewById(R.id.result_text);

      if (null != extras) {
         int width = extras.getInt("width");
         int height = extras.getInt("height");

         LayoutParams lps = new LayoutParams(width, height);
         lps.topMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 30, getResources().getDisplayMetrics());
         lps.leftMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, getResources().getDisplayMetrics());
         lps.rightMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, getResources().getDisplayMetrics());
         
         mResultImage.setLayoutParams(lps);

         String result = extras.getString("result");
         mResultText.setText(result);

         Bitmap barcode = null;
         byte[] compressedBitmap = extras.getByteArray(DecodeThread.BARCODE_BITMAP);
         if (compressedBitmap != null) {
            barcode = BitmapFactory.decodeByteArray(compressedBitmap, 0, compressedBitmap.length, null);
            // Mutable copy:
            barcode = barcode.copy(Bitmap.Config.RGB_565, true);
         }

         mResultImage.setImageBitmap(barcode);
      }
   }
}

依赖=========================================================================

apply plugin: 'com.android.application'

android {
    compileSdkVersion 26
    defaultConfig {
        applicationId "com.daydayup.day07_erwei"
        minSdkVersion 15
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
    implementation files('libs/zxing.jar')
}

权限=========================================================================

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

<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.WAKE_LOCK" />


<activity android:name=".qrcode.CaptureActivity"></activity>
<activity android:name=".qrcode.ResultActivity"></activity>


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值