From 5308d04e20f3dca6d56ccc3e2b460374540716a6 Mon Sep 17 00:00:00 2001
From: wjc <1243177876@qq.com>
Date: 星期二, 06 六月 2023 18:20:13 +0800
Subject: [PATCH] 2023年06月06日18:19:36

---
 third-zxing/src/main/res/values/styles.xml                                    |   24 
 third-zxing/src/main/java/com/zxing/camera/CameraManager.java                 |  195 ++
 third-zxing/src/main/java/com/zxing/camera/CameraConfigurationManager.java    |  207 +++
 app/src/main/res/drawable/fast_scan_light_close.png                           |    0 
 third-zxing/.gitignore                                                        |    1 
 third-zxing/src/main/java/com/zxing/decode/DecodeHandler.java                 |  136 ++
 third-zxing/src/main/java/com/zxing/qrcode/CaptureActivity.java               |  398 +++++
 third-zxing/src/main/res/drawable/transparent_divider.xml                     |    5 
 third-zxing/src/main/res/values/strings.xml                                   |   13 
 third-zxing/src/main/java/com/zxing/camera/PreviewCallback.java               |   40 
 third-zxing/src/main/java/com/zxing/Extras.java                               |   34 
 .idea/misc.xml                                                                |   19 
 third-zxing/libs/zxing_3.3.0.jar                                              |    0 
 third-zxing/src/main/res/values/ids.xml                                       |    9 
 app/src/main/res/drawable/fast_scan_light_open.png                            |    0 
 third-zxing/src/main/java/com/zxing/ContextHelper.java                        |  131 +
 third-zxing/src/main/res/drawable/fast_scan_light_open.png                    |    0 
 third-zxing/src/main/res/drawable-xxhdpi/scan_line.png                        |    0 
 third-zxing/src/main/res/raw/beep.ogg                                         |    0 
 app/build.gradle                                                              |    3 
 third-zxing/build.gradle                                                      |   45 
 app/src/main/res/values/strings.xml                                           |    1 
 third-zxing/src/main/java/com/zxing/utils/CaptureActivityHandler.java         |   95 +
 third-zxing/src/main/java/com/zxing/utils/Validator.java                      |  202 +++
 third-zxing/src/main/res/drawable/fast_scan_light_close.png                   |    0 
 third-zxing/src/main/res/drawable/back.png                                    |    0 
 third-zxing/src/main/java/com/zxing/DeviceHelper.java                         |  469 +++++++
 third-zxing/src/main/java/com/zxing/utils/ZXingBitmapUtils.java               |  333 ++++
 third-zxing/src/main/java/com/zxing/utils/BeepManager.java                    |  125 +
 third-zxing/src/main/java/com/zxing/camera/AutoFocusManager.java              |  114 +
 third-zxing/src/main/java/com/zxing/decode/RGBLuminanceSource.java            |   72 +
 third-zxing/src/main/res/values/colors_ui.xml                                 |   33 
 app/src/main/res/values/colors.xml                                            |    3 
 app/src/main/res/layout/toolbar_top_view_52.xml                               |    1 
 third-zxing/src/main/java/com/zxing/IZxingActivity.java                       |   28 
 app/src/main/java/com/hdl/photovoltaic/ui/device/FastScanActivity.java        |  415 ++++++
 third-zxing/src/main/java/com/zxing/utils/InactivityTimer.java                |  108 +
 settings.gradle                                                               |    1 
 third-zxing/src/main/java/com/zxing/decode/DecodeFormatManager.java           |   37 
 app/src/main/res/layout/activity_fast_scan.xml                                |  109 +
 third-zxing/src/main/res/layout/activity_capture.xml                          |  117 +
 third-zxing/src/main/java/com/zxing/utils/Strings.java                        |  179 ++
 app/src/main/AndroidManifest.xml                                              |   15 
 third-zxing/src/main/AndroidManifest.xml                                      |   14 
 gradle.properties                                                             |    4 
 third-zxing/src/main/res/drawable-xxhdpi/ic_shadow.png                        |    0 
 app/src/main/res/drawable/back.png                                            |    0 
 third-zxing/proguard-rules.pro                                                |   25 
 third-zxing/src/main/res/drawable-xxhdpi/scan_capture.9.png                   |    0 
 third-zxing/src/main/java/com/zxing/decode/DecodeThread.java                  |   82 +
 app/src/main/java/com/hdl/photovoltaic/ui/MyPowerStationActivity.java         |    1 
 third-zxing/src/main/java/com/zxing/camera/open/OpenCameraInterface.java      |   69 +
 third-zxing/src/main/res/layout/toolbar.xml                                   |   34 
 app/src/main/java/com/hdl/photovoltaic/base/BaseFragment.java                 |    6 
 app/src/main/java/com/hdl/photovoltaic/ui/powerstation/HouseListFragment.java |   16 
 55 files changed, 3,939 insertions(+), 29 deletions(-)

diff --git a/.idea/misc.xml b/.idea/misc.xml
index 2a2e4cc..613a21b 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -3,7 +3,26 @@
   <component name="DesignSurface">
     <option name="filePathToZoomLevelMap">
       <map>
+        <entry key="../../../../../layout/custom_preview.xml" value="0.22923076923076924" />
+        <entry key="../../../.gradle/caches/transforms-2/files-2.1/7c2cbaa925629e10707989293f119941/jetified-zxing-android-embedded-3.4.0/res/layout/zxing_barcode_scanner.xml" value="0.20625" />
+        <entry key="../../../.gradle/caches/transforms-2/files-2.1/7c2cbaa925629e10707989293f119941/jetified-zxing-android-embedded-3.4.0/res/layout/zxing_capture.xml" value="0.20625" />
+        <entry key="app/src/main/res/layout/activity_1.xml" value="0.20625" />
+        <entry key="app/src/main/res/layout/activity_123.xml" value="0.20625" />
+        <entry key="app/src/main/res/layout/activity_capture.xml" value="0.20625" />
+        <entry key="app/src/main/res/layout/activity_fast_scan.xml" value="0.20625" />
+        <entry key="app/src/main/res/layout/activity_home_login.xml" value="0.20625" />
         <entry key="app/src/main/res/layout/activity_my_power_station.xml" value="0.20625" />
+        <entry key="app/src/main/res/layout/activity_new_capture.xml" value="0.20625" />
+        <entry key="app/src/main/res/layout/fragment_house_list.xml" value="0.20625" />
+        <entry key="app/src/main/res/layout/fragment_me.xml" value="0.1" />
+        <entry key="app/src/main/res/layout/frgment_house_list_line.xml" value="0.20625" />
+        <entry key="app/src/main/res/layout/toolbar_top_view_52.xml" value="0.20625" />
+        <entry key="app/src/main/res/layout/toolbar_top_view_53.xml" value="0.20625" />
+        <entry key="third-zxing/src/main/res/drawable/transparent_divider.xml" value="0.1275" />
+        <entry key="third-zxing/src/main/res/layout/activity_capture.xml" value="0.20625" />
+        <entry key="third-zxing/src/main/res/layout/toolbar.xml" value="0.20625" />
+        <entry key="third-zxing/src/main/res/layout/toolbar_top_view.xml" value="0.20625" />
+        <entry key="third-zxing/src/main/res/layout/toolbar_top_view_52.xml" value="0.20625" />
       </map>
     </option>
   </component>
diff --git a/app/build.gradle b/app/build.gradle
index 2c43ce4..f2ec162 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -39,8 +39,11 @@
     implementation 'androidx.navigation:navigation-fragment:2.3.5'
     implementation 'androidx.navigation:navigation-ui:2.3.5'
     implementation 'androidx.legacy:legacy-support-v4:1.0.0'
+    implementation project(path: ':third-zxing')
     testImplementation 'junit:junit:4.13.2'
     androidTestImplementation 'androidx.test.ext:junit:1.1.3'
     androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
     implementation 'org.greenrobot:eventbus:3.0.0'
+
+
 }
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 09168e4..85db82f 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,6 +1,15 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.hdl.photovoltaic">
+    xmlns:tools="http://schemas.android.com/tools"
+    package="com.hdl.photovoltaic" >
+
+    <uses-permission
+        android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
+        tools:ignore="ProtectedPermissions" />
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.CAMERA" />
+    <uses-permission android:name="android.permission.VIBRATE" />
 
     <application
         android:name=".HDLApp"
@@ -9,7 +18,7 @@
         android:label="@string/app_name"
         android:roundIcon="@mipmap/ic_launcher_round"
         android:supportsRtl="true"
-        android:theme="@style/Theme.PhotovoltaicDebug">
+        android:theme="@style/Theme.PhotovoltaicDebug" >
         <activity
             android:name=".ui.device.FastScanActivity"
             android:exported="false" />
@@ -21,7 +30,7 @@
             android:exported="false" />
         <activity
             android:name=".ui.StartActivity"
-            android:exported="true">
+            android:exported="true" >
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
 
diff --git a/app/src/main/java/com/hdl/photovoltaic/base/BaseFragment.java b/app/src/main/java/com/hdl/photovoltaic/base/BaseFragment.java
index 4a88c53..5598bea 100644
--- a/app/src/main/java/com/hdl/photovoltaic/base/BaseFragment.java
+++ b/app/src/main/java/com/hdl/photovoltaic/base/BaseFragment.java
@@ -123,7 +123,7 @@
     /**
      * 鏄剧ずView
      *
-     * @param view
+     * @param view -
      */
     public void setViewVisible(View view) {
         if (view.getVisibility() != View.VISIBLE && _mActivity != null) {
@@ -134,7 +134,7 @@
     /**
      * 闅愯棌View
      *
-     * @param view
+     * @param view -
      */
     protected void setViewGone(View view) {
         if (view.getVisibility() != View.GONE && _mActivity != null) {
@@ -145,7 +145,7 @@
     /**
      * 绠�鍗曠殑璺宠浆Activity
      *
-     * @param clazz
+     * @param clazz -
      */
     protected void startActivity(Class<?> clazz) {
         if (_mActivity != null) {
diff --git a/app/src/main/java/com/hdl/photovoltaic/ui/MyPowerStationActivity.java b/app/src/main/java/com/hdl/photovoltaic/ui/MyPowerStationActivity.java
index b82cea7..77d9ac2 100644
--- a/app/src/main/java/com/hdl/photovoltaic/ui/MyPowerStationActivity.java
+++ b/app/src/main/java/com/hdl/photovoltaic/ui/MyPowerStationActivity.java
@@ -58,7 +58,6 @@
 
     private void bottomViewChangeOfStyle() {
         if (this.currentFragmentIndex == 0) {
-
             viewBinding.myPowerStationFcv1.setVisibility(View.VISIBLE);
             viewBinding.myPowerStationFcv2.setVisibility(View.GONE);
             viewBinding.myPowerStationBottomIl1.iconIv.setImageDrawable(AppCompatResources.getDrawable(_mActivity, R.drawable.selectedpowerstation));
diff --git a/app/src/main/java/com/hdl/photovoltaic/ui/device/FastScanActivity.java b/app/src/main/java/com/hdl/photovoltaic/ui/device/FastScanActivity.java
index 7c31db8..93ddc2f 100644
--- a/app/src/main/java/com/hdl/photovoltaic/ui/device/FastScanActivity.java
+++ b/app/src/main/java/com/hdl/photovoltaic/ui/device/FastScanActivity.java
@@ -1,17 +1,78 @@
 package com.hdl.photovoltaic.ui.device;
 
-import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.content.res.AppCompatResources;
 
+import android.content.Intent;
+import android.database.Cursor;
+import android.graphics.Rect;
+import android.hardware.Camera;
+import android.net.Uri;
 import android.os.Bundle;
+import android.os.Handler;
+import android.provider.MediaStore;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.View;
+import android.view.animation.Animation;
+import android.view.animation.TranslateAnimation;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
+import android.widget.Toast;
 
+import com.google.zxing.BinaryBitmap;
+import com.google.zxing.ChecksumException;
+import com.google.zxing.DecodeHintType;
+import com.google.zxing.FormatException;
+import com.google.zxing.NotFoundException;
+import com.google.zxing.Result;
+import com.google.zxing.common.HybridBinarizer;
+import com.google.zxing.qrcode.QRCodeReader;
 import com.hdl.photovoltaic.R;
 import com.hdl.photovoltaic.base.CustomBaseActivity;
 import com.hdl.photovoltaic.databinding.ActivityFastScanBinding;
+import com.zxing.IZxingActivity;
+import com.zxing.camera.CameraManager;
+import com.zxing.decode.DecodeThread;
+import com.zxing.decode.RGBLuminanceSource;
+import com.zxing.utils.BeepManager;
+import com.zxing.utils.CaptureActivityHandler;
+import com.zxing.utils.InactivityTimer;
 
-public class FastScanActivity extends CustomBaseActivity {
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.Hashtable;
 
-
+public class FastScanActivity extends CustomBaseActivity implements IZxingActivity, SurfaceHolder.Callback {
+    private static final String TAG = com.zxing.qrcode.CaptureActivity.class.getSimpleName();
+    private final int REQUEST_CODE = 33;
+    private CameraManager cameraManager;
+    private CaptureActivityHandler handler;
+    private InactivityTimer inactivityTimer;
+    private BeepManager beepManager;
+    private SurfaceView scanPreview = null;
+    private RelativeLayout scanContainer;
+    private RelativeLayout scanCropView;
+    private Rect mCropRect = null;
+    private boolean isHasSurface = false;
     private ActivityFastScanBinding viewBinding;
+
+    @Override
+    public Handler getHandler() {
+        return handler;
+    }
+
+    @Override
+    public void drawViewfinder() {
+
+    }
+
+    @Override
+    public CameraManager getCameraManager() {
+        return cameraManager;
+    }
 
     @Override
     public Object getContentView() {
@@ -21,6 +82,352 @@
 
     @Override
     public void onBindView(Bundle savedInstanceState) {
+//        Window window = getWindow();
+//        window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+//        //璁剧疆鏍硅鍥�
+//        View mContentView = LayoutInflater.from(this).inflate(R.layout.activity_new_capture, null);
+//        setContentView(mContentView);
+        //鍒濆鍖�
+        initView(savedInstanceState);
+        //鍒濆鍖栫晫闈㈢洃鍚櫒
+        initEvent();
+    }
+
+
+    private void initView(Bundle savedInstanceState) {
+
+
+        scanPreview = findViewById(R.id.new_capture_preview);
+        scanContainer = findViewById(R.id.new_capture_rl);
+        scanCropView = findViewById(R.id.new_capture_crop_view);
+        ImageView scanLine = findViewById(R.id.new_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(2000);
+        animation.setRepeatCount(-1);
+        animation.setRepeatMode(Animation.RESTART);
+        scanLine.startAnimation(animation);
+    }
+
+    private void initEvent() {
+        viewBinding.newTopBackBtn.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                finish();
+            }
+        });
+
+        viewBinding.newTopMoreBtn.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                //璺冲埌鍏ョ綉
+            }
+        });
+
+        viewBinding.newLightIv.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                v.setSelected(!v.isSelected());
+                if (v.isSelected()) {
+                    viewBinding.newLightIv.setImageDrawable(AppCompatResources.getDrawable(FastScanActivity.this, com.zxing.R.drawable.fast_scan_light_open));
+                } else {
+                    viewBinding.newLightIv.setImageDrawable(AppCompatResources.getDrawable(FastScanActivity.this, com.zxing.R.drawable.fast_scan_light_close));
+                }
+                flashLightOnOrOff();
+
+            }
+        });
+    }
+
+
+    public void enterGallery() {
+        // 杩涘叆鍥惧簱
+        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
+        intent.addCategory(Intent.CATEGORY_OPENABLE);
+        intent.setType("image/*");
+        intent.putExtra("return-data", true);
+        startActivityForResult(intent, REQUEST_CODE);
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        cameraManager = new CameraManager(getApplication());
+        handler = null;
+        if (isHasSurface) {
+            initCamera(scanPreview.getHolder());
+        } else {
+            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.d(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) {
 
     }
-}
\ No newline at end of file
+
+    /**
+     * 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
+     */
+    @Override
+    public void handleDecode(Result rawResult, Bundle bundle) {
+        inactivityTimer.onActivity();
+        beepManager.playBeepSoundAndVibrate();
+        doProcess(rawResult.getText());
+        restartPreviewAfterDelay(3000);
+    }
+
+    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);
+            Toast.makeText(this, com.zxing.R.string.capture_no_camera, Toast.LENGTH_SHORT).show();
+            finish();
+        } catch (RuntimeException e) {
+            Log.w(TAG, "Unexpected error initializing camera", e);
+            Toast.makeText(this, com.zxing.R.string.capture_no_camera, Toast.LENGTH_SHORT).show();
+            finish();
+        }
+    }
+
+    public void restartPreviewAfterDelay(long delayMS) {
+        if (handler != null) {
+            handler.sendEmptyMessageDelayed(com.zxing.R.id.restart_preview, delayMS);
+        }
+    }
+
+    @Override
+    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;
+    }
+
+    private void doProcess(String result) {
+        Log.d("panlili", "scanResult: " + result);
+        /*if (!DeviceHelper.getNetworkState()) {
+            Toast.makeText(this, R.string.capture_no_network, Toast.LENGTH_SHORT).show();
+            return;
+        }*/
+
+        if (TextUtils.isEmpty(result)) {
+            Toast.makeText(this, com.zxing.R.string.capture_no_result, Toast.LENGTH_SHORT).show();
+        } else {
+            Intent intent = new Intent();
+            intent.putExtra("data", result);
+            setResult(RESULT_OK, intent);
+            finish();
+        }
+    }
+
+    @Override
+    public void onActivityResult(int requestCode, int resultCode, Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+        if (requestCode == REQUEST_CODE && resultCode == RESULT_OK && data != null) {
+            Uri originalUri = data.getData();
+            if (originalUri != null) {
+                String path = originalUri.getPath();
+                String[] proj = {MediaStore.Images.Media.DATA};
+                Cursor cursor = getContentResolver().query(originalUri, proj, null, null, null);
+                if (cursor != null) {
+                    int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
+                    cursor.moveToFirst();
+                    path = cursor.getString(column_index);
+                    cursor.close();
+                }
+
+                if (!TextUtils.isEmpty(path)) {
+                    handleQRCodeFormPhoto(path);
+                } else {
+                    Toast.makeText(this, "鍥剧墖宸叉崯鍧忥紝璇烽噸鏂伴�夋嫨锛�", Toast.LENGTH_SHORT).show();
+                }
+            }
+        }
+    }
+
+    /**
+     * 瑙f瀽鍥惧簱閫夋嫨鐨勪簩缁寸爜
+     */
+    public void handleQRCodeFormPhoto(final String filePath) {
+        Thread dealThread = new Thread(new Runnable() {
+            @Override
+            public void run() {
+                Hashtable<DecodeHintType, String> hints = new Hashtable<>();
+                hints.put(DecodeHintType.CHARACTER_SET, "utf-8");
+                RGBLuminanceSource source = null;
+                try {
+                    source = new RGBLuminanceSource(filePath);
+                } catch (FileNotFoundException e) {
+                    e.printStackTrace();
+                }
+                BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(source));
+                QRCodeReader reader = new QRCodeReader();
+                Result result;
+                try {
+                    result = reader.decode(binaryBitmap, hints);
+                    if (!TextUtils.isEmpty(result.getText())) {
+                        dealUIInfo(result.getText());
+                    } else {
+                        dealUIInfo(null);
+                    }
+                } catch (NotFoundException | ChecksumException | FormatException e) {
+                    dealUIInfo(null);
+                    e.printStackTrace();
+                }
+            }
+        });
+        dealThread.start();
+    }
+
+    private void dealUIInfo(final Object progressInfo) {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                if (progressInfo == null) {
+                    Toast.makeText(FastScanActivity.this, com.zxing.R.string.capture_no_result2, Toast.LENGTH_SHORT).show();
+                } else {
+                    doProcess(progressInfo.toString());
+                }
+            }
+        });
+    }
+
+
+    /**
+     * 闂厜鐏紑鍚垨鑰呭叧闂�
+     */
+    private void flashLightOnOrOff() {
+//
+        android.hardware.Camera camera = cameraManager.getCamera();
+        if (camera == null) {
+            return;
+        }
+        android.hardware.Camera.Parameters parameters = camera.getParameters();
+//		鍒ゆ柇闂厜鐏綋鍓嶇姸鎬�
+        if (Camera.Parameters.FLASH_MODE_OFF.equals(parameters.getFlashMode())) {
+            onLight(camera, parameters);
+        } else if (Camera.Parameters.FLASH_MODE_TORCH.equals(parameters.getFlashMode())) {
+            offLight(camera, parameters);
+        }
+    }
+
+    private void onLight(android.hardware.Camera camera, Camera.Parameters parameters) {
+        parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
+        camera.setParameters(parameters);
+    }
+
+    private void offLight(android.hardware.Camera camera, Camera.Parameters parameters) {
+        parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
+        camera.setParameters(parameters);
+    }
+
+
+}
diff --git a/app/src/main/java/com/hdl/photovoltaic/ui/powerstation/HouseListFragment.java b/app/src/main/java/com/hdl/photovoltaic/ui/powerstation/HouseListFragment.java
index 346bf75..55b887a 100644
--- a/app/src/main/java/com/hdl/photovoltaic/ui/powerstation/HouseListFragment.java
+++ b/app/src/main/java/com/hdl/photovoltaic/ui/powerstation/HouseListFragment.java
@@ -1,6 +1,7 @@
 package com.hdl.photovoltaic.ui.powerstation;
 
 import android.content.Context;
+import android.content.Intent;
 import android.hardware.camera2.CameraManager;
 import android.os.Bundle;
 import android.util.Log;
@@ -14,6 +15,7 @@
 import com.hdl.photovoltaic.base.CustomBaseFragment;
 import com.hdl.photovoltaic.ui.adapter.HouseInfoAdapter;
 import com.hdl.photovoltaic.ui.bean.HouseInfoBean;
+import com.hdl.photovoltaic.ui.device.FastScanActivity;
 import com.hdl.photovoltaic.utils.FlashLightUtils;
 
 import java.util.ArrayList;
@@ -22,7 +24,6 @@
 public class HouseListFragment extends CustomBaseFragment {
     private FragmentHouseListBinding viewBinding;
     private HouseInfoAdapter houseInfoAdapter;
-    private FlashLightUtils flashLightUtils;
     private CameraManager manager;
 
     private List<HouseInfoBean> houseInfoBeanList = null;
@@ -35,7 +36,6 @@
 
     @Override
     public void onBindView(Bundle savedInstanceState) {
-        flashLightUtils = new FlashLightUtils(_mActivity);
         manager = (CameraManager) _mActivity.getSystemService(Context.CAMERA_SERVICE);
 
         initData();
@@ -49,12 +49,12 @@
 
 
     private void initEvent() {
-
-
         viewBinding.toolbarTopFragmentHouseListRl.topMoreIv.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
-
+                Intent intent = new Intent();
+                intent.setClass(_mActivity, FastScanActivity.class);
+                startActivity(intent);
             }
         });
         //璁剧疆涓嬫媺绠ご棰滆壊
@@ -73,7 +73,6 @@
         viewBinding.toolbarTopFragmentHouseListRl.topTitleTv.setText(R.string.my_power_station_鎴戠殑鐢电珯);
         viewBinding.toolbarTopFragmentHouseListRl.topMoreIv.setVisibility(View.VISIBLE);
         viewBinding.toolbarTopFragmentHouseListRl.topMoreIv.setImageResource(R.drawable.add);
-
         LinearLayoutManager linearLayout = new LinearLayoutManager(_mActivity);
         houseInfoAdapter = new HouseInfoAdapter(this.houseInfoBeanList);
         viewBinding.fragmentHouseSrlListRc.setLayoutManager(linearLayout);
@@ -89,11 +88,6 @@
             houseInfoBean.setName("鐢电珯" + i);
             this.houseInfoBeanList.add(houseInfoBean);
         }
-
-
-    }
-
-    private void openCamera() {
 
 
     }
diff --git a/app/src/main/res/drawable/back.png b/app/src/main/res/drawable/back.png
new file mode 100644
index 0000000..64507b9
--- /dev/null
+++ b/app/src/main/res/drawable/back.png
Binary files differ
diff --git a/app/src/main/res/drawable/fast_scan_light_close.png b/app/src/main/res/drawable/fast_scan_light_close.png
new file mode 100644
index 0000000..56f42cf
--- /dev/null
+++ b/app/src/main/res/drawable/fast_scan_light_close.png
Binary files differ
diff --git a/app/src/main/res/drawable/fast_scan_light_open.png b/app/src/main/res/drawable/fast_scan_light_open.png
new file mode 100644
index 0000000..454e02f
--- /dev/null
+++ b/app/src/main/res/drawable/fast_scan_light_open.png
Binary files differ
diff --git a/app/src/main/res/layout/activity_fast_scan.xml b/app/src/main/res/layout/activity_fast_scan.xml
index ce5b771..66cbe7f 100644
--- a/app/src/main/res/layout/activity_fast_scan.xml
+++ b/app/src/main/res/layout/activity_fast_scan.xml
@@ -1,9 +1,108 @@
 <?xml version="1.0" encoding="utf-8"?>
-<androidx.constraintlayout.widget.ConstraintLayout 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"
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/new_capture_rl"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    tools:context=".ui.device.FastScanActivity">
+    android:background="#636363">
 
-</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
+    <RelativeLayout
+        android:id="@+id/new_top_bar_view"
+        android:layout_width="match_parent"
+        android:layout_height="52dp"
+        android:background="#245EC3"
+        android:orientation="horizontal">
+
+        <!--1.杩斿洖鎸夐挳 澧炲ぇ鐐瑰嚮鍖哄煙-->
+        <LinearLayout
+            android:id="@+id/new_top_back_btn"
+            android:layout_width="56dp"
+            android:layout_height="match_parent"
+            android:gravity="center_vertical"
+            android:orientation="horizontal">
+
+            <ImageView
+                android:layout_width="24dp"
+                android:layout_height="24dp"
+                android:layout_gravity="center"
+                android:layout_marginLeft="16dp"
+                android:scaleType="centerInside"
+                android:src="@drawable/back" />
+        </LinearLayout>
+
+        <!--2.鏍囬鏂囨湰-->
+        <TextView
+            android:id="@+id/new_top_title_tv"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerInParent="true"
+            android:layout_marginLeft="60dp"
+            android:layout_marginRight="60dp"
+            android:fontFamily="sans-serif-medium"
+            android:gravity="center"
+            android:maxLines="1"
+            android:text="蹇�熸壂鐮�"
+            android:textColor="#FFFFFFFF"
+            android:textSize="18sp" />
+
+        <!--3.鏇村鎸夐挳 榛樿闅愯棌-->
+        <LinearLayout
+            android:id="@+id/new_top_more_btn"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_alignParentEnd="true"
+            android:gravity="center_vertical"
+            android:orientation="horizontal">
+
+            <TextView
+                android:id="@+id/new_top_connect_tv"
+                android:layout_width="wrap_content"
+                android:layout_height="20dp"
+                android:layout_marginEnd="20dp"
+                android:text="@string/device_鎵嬪姩杩炴帴"
+                android:textColor="@color/text_FFFFFFFF"
+                android:textSize="@dimen/text_14" />
+
+        </LinearLayout>
+
+    </RelativeLayout>
+
+    <SurfaceView
+        android:id="@+id/new_capture_preview"
+        android:layout_width="367dp"
+        android:layout_height="367dp"
+        android:layout_centerInParent="true" />
+
+    <RelativeLayout
+        android:id="@+id/new_capture_crop_view"
+        android:layout_width="367dp"
+        android:layout_height="367dp"
+        android:layout_centerInParent="true"
+        android:background="@drawable/scan_capture">
+
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_height="367dp"
+            android:layout_marginTop="182dp">
+
+            <ImageView
+                android:id="@+id/new_capture_scan_line"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_alignParentTop="true"
+                android:layout_marginTop="5dp"
+                android:layout_marginBottom="5dp"
+                android:src="@drawable/scan_line" />
+        </RelativeLayout>
+
+    </RelativeLayout>
+
+    <ImageView
+        android:id="@+id/new_light_iv"
+        android:layout_width="127dp"
+        android:layout_height="127dp"
+        android:layout_alignParentBottom="true"
+        android:layout_centerInParent="true"
+        android:layout_marginBottom="13dp"
+        android:background="@drawable/fast_scan_light_close" />
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/toolbar_top_view_52.xml b/app/src/main/res/layout/toolbar_top_view_52.xml
index 02e2249..2ce085a 100644
--- a/app/src/main/res/layout/toolbar_top_view_52.xml
+++ b/app/src/main/res/layout/toolbar_top_view_52.xml
@@ -57,6 +57,7 @@
             android:scaleType="centerInside"
             android:visibility="gone" />
 
+
     </LinearLayout>
 
 </RelativeLayout>
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index 05de233..864d506 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -29,6 +29,7 @@
     <color name="text_06B92A">#06B92A</color>
     <color name="text_F9FAFB">#F9FAFB</color>
     <color name="text_CBCDD1">#CBCDD1</color>/
-    <color name="text_FF245EC3">#FF245EC3</color>
+    <color name="text_FF245EC3">#FF245EC3</color>#
+    <color name="text_636363">#636363</color>
 
 </resources>
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 2bd4d75..750d136 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -42,6 +42,7 @@
     <string name="my_power_station_绂荤嚎">绂荤嚎</string>
     <string name="my_power_station_鏁呴殰">鏁呴殰</string>
     <string name="my_power_station_杩愯">杩愯</string>
+    <string name="device_鎵嬪姩杩炴帴">鎵嬪姩杩炴帴</string>
 
 
     <!--鎴戠殑-->
diff --git a/gradle.properties b/gradle.properties
index dab7c28..98aeb05 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -18,4 +18,6 @@
 # Enables namespacing of each library's R class so that its R class includes only the
 # resources declared in the library itself and none from the library's dependencies,
 # thereby reducing the size of the R class for that library
-android.nonTransitiveRClass=true
\ No newline at end of file
+android.nonTransitiveRClass=true
+# 鍙互灏唙4,v7搴撹浆鎴怉ndroid X
+android.enableJetifier=true
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
index d2a636d..c8e8029 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,2 +1,3 @@
 rootProject.name = "PhotovoltaicDebug"
 include ':app'
+include ':third-zxing'
diff --git a/third-zxing/.gitignore b/third-zxing/.gitignore
new file mode 100644
index 0000000..3543521
--- /dev/null
+++ b/third-zxing/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/third-zxing/build.gradle b/third-zxing/build.gradle
new file mode 100644
index 0000000..fd81dd7
--- /dev/null
+++ b/third-zxing/build.gradle
@@ -0,0 +1,45 @@
+apply plugin: 'com.android.library'
+
+
+android {
+    compileSdkVersion 29
+    buildToolsVersion "29.0.1"
+
+    defaultConfig {
+        minSdkVersion 21
+        targetSdkVersion 26
+        versionCode 1
+        versionName "1.0"
+
+        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+        javaCompileOptions {
+            annotationProcessorOptions {
+                arguments = [moduleName: project.getName()]
+            }
+        }
+
+    }
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+        }
+    }
+    android {
+        lintOptions {
+            abortOnError false
+        }
+    }
+}
+
+dependencies {
+    api fileTree(include: ['*.jar'], dir: 'libs')
+//    compileOnly fileTree(include: ['*.jar'], dir: 'libs')
+    androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
+        exclude group: 'com.android.support', module: 'support-annotations'
+    })
+    testImplementation 'junit:junit:4.12'
+    implementation 'com.android.support:support-annotations:28.0.0'
+//    api 'com.android.support:appcompat-v7:28.0.0'
+    implementation 'androidx.appcompat:appcompat:1.3.0'
+}
diff --git a/third-zxing/libs/zxing_3.3.0.jar b/third-zxing/libs/zxing_3.3.0.jar
new file mode 100644
index 0000000..94f7406
--- /dev/null
+++ b/third-zxing/libs/zxing_3.3.0.jar
Binary files differ
diff --git a/third-zxing/proguard-rules.pro b/third-zxing/proguard-rules.pro
new file mode 100644
index 0000000..48f7715
--- /dev/null
+++ b/third-zxing/proguard-rules.pro
@@ -0,0 +1,25 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /Users/ye/Library/Android/sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/third-zxing/src/main/AndroidManifest.xml b/third-zxing/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..bd46698
--- /dev/null
+++ b/third-zxing/src/main/AndroidManifest.xml
@@ -0,0 +1,14 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.zxing">
+
+    <application >
+
+        <activity
+            android:name=".qrcode.CaptureActivity"
+            android:configChanges="orientation|keyboardHidden|screenSize|locale"
+            android:exported="false"
+            android:screenOrientation="portrait"
+            android:theme="@style/AppTheme.Base"/>
+    </application>
+
+</manifest>
diff --git a/third-zxing/src/main/java/com/zxing/ContextHelper.java b/third-zxing/src/main/java/com/zxing/ContextHelper.java
new file mode 100644
index 0000000..9975547
--- /dev/null
+++ b/third-zxing/src/main/java/com/zxing/ContextHelper.java
@@ -0,0 +1,131 @@
+package com.zxing;
+
+import android.app.Activity;
+import android.app.Application;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.os.Build;
+
+import com.zxing.utils.Strings;
+
+public final class ContextHelper {
+
+    private static Application application;
+    private static Class splashCls;
+
+    /**
+     * 鍒濆鍖�
+     *
+     * @param application app
+     */
+    public static void init(Application application) {
+        if (ContextHelper.application == null) {
+            ContextHelper.application = application;
+        }
+    }
+
+    public static Context getAppContext() {
+        if (application != null) {
+            return application.getApplicationContext();
+        }
+        return null;
+    }
+
+    public static Application getApp() {
+        return application;
+    }
+
+    public static Resources getResources() {
+        Context context = getAppContext();
+        if (context != null) {
+            return context.getResources();
+        }
+        return null;
+    }
+
+    public static void setSplashCls(Class cls) {
+        ContextHelper.splashCls = cls;
+    }
+
+    public static Class getSplashCls() {
+        return splashCls;
+    }
+
+    /**
+     * 璧勬簮ID鑾峰彇String
+     */
+    public static String getString(int stringId) {
+        if (getAppContext() == null) {
+            return Strings.EMPTY;
+        }
+        return getAppContext().getString(stringId);
+    }
+
+    public static String getString(int stringId, Object... formatArgs) {
+        if (getAppContext() == null) {
+            return Strings.EMPTY;
+        }
+        return getAppContext().getString(stringId, formatArgs);
+    }
+
+
+    public static int getDimensionPixelSize(int dimenId) {
+        try {
+            return getResources().getDimensionPixelSize(dimenId);
+        } catch (Resources.NotFoundException e) {
+            e.printStackTrace();
+        }
+        return 0;
+    }
+
+    public static int getDimen(int dimenId) {
+        try {
+            return getResources().getDimensionPixelSize(dimenId);
+        } catch (Resources.NotFoundException e) {
+            e.printStackTrace();
+        }
+        return 0;
+    }
+
+    /**
+     * 鑾峰彇搴旂敤鐨勭増鏈彿
+     */
+    public static String getAppVersion() {
+        Context context = getAppContext();
+        if (context != null) {
+            PackageManager packageManager = context.getPackageManager();
+            PackageInfo packageInfo;
+            try {
+                packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
+                return packageInfo.versionName;
+            } catch (PackageManager.NameNotFoundException e) {
+                e.printStackTrace();
+            }
+        }
+        return Strings.EMPTY;
+    }
+
+    public static boolean isUsable(Context context) {
+        if (context == null) {
+            return false;
+        }
+
+        if (context instanceof Activity && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+            return !((Activity) context).isDestroyed();
+        }
+        return true;
+    }
+
+    public static void startAppSetting(){
+        if(getAppContext()!=null) {
+            Intent intent = new Intent("android.settings.SETTINGS");
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            getAppContext().startActivity(intent);
+        }
+    }
+
+}
+
diff --git a/third-zxing/src/main/java/com/zxing/DeviceHelper.java b/third-zxing/src/main/java/com/zxing/DeviceHelper.java
new file mode 100644
index 0000000..adb06bb
--- /dev/null
+++ b/third-zxing/src/main/java/com/zxing/DeviceHelper.java
@@ -0,0 +1,469 @@
+package com.zxing;
+
+import android.app.Activity;
+import android.content.ClipboardManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
+import android.graphics.Point;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Environment;
+import android.os.StatFs;
+import android.provider.MediaStore;
+import android.provider.Settings;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.util.DisplayMetrics;
+import android.view.WindowManager;
+
+import com.zxing.utils.Strings;
+import com.zxing.utils.Validator;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.util.List;
+import java.util.Locale;
+
+import static android.telephony.TelephonyManager.SIM_STATE_READY;
+
+/**
+ * 鐢ㄩ�旓細鍙栬澶囩浉鍏充俊鎭�
+ */
+public class DeviceHelper {
+
+    /**
+     * 鑾峰彇搴旂敤鐨勭増鏈彿
+     */
+    public static String getAppVersion() {
+        Context context = ContextHelper.getAppContext();
+        if (context != null) {
+            PackageManager packageManager = context.getPackageManager();
+            PackageInfo packageInfo;
+            try {
+                packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
+                return packageInfo.versionName;
+            } catch (PackageManager.NameNotFoundException e) {
+                e.printStackTrace();
+            }
+        }
+        return Strings.EMPTY;
+    }
+
+    public static void ClipData(String content) {
+        ClipboardManager cm = (ClipboardManager) ContextHelper.getAppContext().getSystemService(Context.CLIPBOARD_SERVICE);
+        // 灏嗘枃鏈唴瀹规斁鍒扮郴缁熷壀璐存澘閲屻��
+        if (cm != null) {
+            cm.setText(content);
+        }
+    }
+
+    /**
+     * 鍚姩搴旂敤鐨勮缃�
+     */
+    public static void startAppSettings(Activity activity, int requestCode) {
+        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+        Uri uri = Uri.fromParts("package", activity.getPackageName(), null);
+        intent.setData(uri);
+        activity.startActivityForResult(intent, requestCode);
+    }
+
+    /**
+     * 鑾峰彇鐗堟湰淇℃伅 versioncode
+     */
+    public static int getVersionCode() {
+        final Context context = ContextHelper.getAppContext();
+        int version = 1;
+        if (context != null) {
+            PackageManager packageManager = context.getPackageManager();
+            PackageInfo packInfo = null;
+            try {
+                packInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
+            } catch (PackageManager.NameNotFoundException e) {
+                e.printStackTrace();
+            }
+            if (packInfo != null) {
+                version = packInfo.versionCode;
+            }
+        }
+        return version;
+    }
+
+    /**
+     * 鑾峰彇璁惧鐨勫埗閫犲晢
+     */
+    public static String getFactory() {
+        return Build.MANUFACTURER;
+    }
+
+    /**
+     * 鑾峰彇绯荤粺鐗堟湰鍙�
+     */
+    public static String getPhoneOS() {
+        return "Android " + getSysVersion() + " " + Build.VERSION.RELEASE;
+    }
+
+    /**
+     * 鐗堟湰鏄惁鍦ˋndroid6.0 浠ヤ笂
+     */
+    public static boolean isOverMarshmallow() {
+        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
+    }
+
+    /**
+     * 鑾峰彇Android API鐗堟湰
+     */
+    public static String getSysVersion() {
+        return Build.VERSION.SDK_INT + Strings.EMPTY;
+    }
+
+    /**
+     * 鑾峰彇Android API鐗堟湰
+     */
+    public static int getSysVersionInt() {
+        return Build.VERSION.SDK_INT;
+    }
+
+    /**
+     * 鑾峰彇鎵嬫満鍨嬪彿
+     */
+    public static String getPhoneModel() {
+        String model = Build.BRAND + " " + Build.MODEL;
+        if (!TextUtils.isEmpty(model) && model.length() > 50) {
+            model = model.substring(0, 49);
+        }
+        return Validator.replaceHanzi(model);
+    }
+
+    /**
+     * 鍒ゆ柇IMEI鏄惁涓虹函鏁板瓧涓�
+     */
+    private static boolean isNumber(String str) {
+        if (TextUtils.isEmpty(str)) {
+            return false;
+        }
+        boolean isNumber = true;
+        int i;
+        char c;
+        for (i = 0; i < str.length(); i++) {
+            c = str.charAt(i);
+            if (!((c >= '0') && (c <= '9')) || "000000000000000".equals(str) || "0".equals(str)) {
+                isNumber = false;
+                break;
+            }
+        }
+        return isNumber;
+    }
+
+    private static String loadFileAsString(String fileName) throws Exception {
+        FileReader reader = new FileReader(fileName);
+        String text = loadReaderAsString(reader);
+        reader.close();
+        return text;
+    }
+
+    private static String loadReaderAsString(Reader reader) throws Exception {
+        StringBuilder builder = new StringBuilder();
+        char[] buffer = new char[4096];
+        int readLength = reader.read(buffer);
+        while (readLength >= 0) {
+            builder.append(buffer, 0, readLength);
+            readLength = reader.read(buffer);
+        }
+        return builder.toString();
+    }
+
+    /**
+     * 鍒ゆ柇mac鍦板潃鏄惁鍚堟硶
+     */
+    private static boolean isCorrectMacAddress(String address) {
+        boolean flag = false;
+        if (!TextUtils.isEmpty(address) && address.length() == 17) {
+            address = address.replaceAll(":", Strings.EMPTY);
+            flag = isHex(address);
+        }
+        return flag;
+    }
+
+    /**
+     * 鍒ゆ柇鏄惁涓虹函16杩涘埗鏁板瓧涓�
+     */
+    private static boolean isHex(String str) {
+        boolean isHexFlg = true;
+        int i;
+        char c;
+        for (i = 0; i < str.length(); i++) {
+            c = str.charAt(i);
+            if (!(((c >= '0') && (c <= '9')) ||
+                    ((c >= 'A') && (c <= 'F')) ||
+                    (c >= 'a') && (c <= 'f'))) {
+                isHexFlg = false;
+                break;
+            }
+        }
+        return isHexFlg;
+    }
+
+    /**
+     * 鍒ゆ柇绯荤粺涓槸鍚﹀瓨鍦ㄥ彲浠ュ惎鍔ㄧ殑鐩告満搴旂敤
+     *
+     * @return 瀛樺湪杩斿洖true锛屼笉瀛樺湪杩斿洖false
+     */
+    public static boolean hasCamera(Context context) {
+        PackageManager packageManager = context.getPackageManager();
+        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
+        List<ResolveInfo> list = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
+        return list.size() > 0;
+    }
+
+
+    /**
+     * 妫�娴嬬郴缁熸槸鍚︿负MIUI
+     */
+    private static final String KEY_MIUI_VERSION_CODE = "ro.miui.ui.version.code";
+    private static final String KEY_MIUI_VERSION_NAME = "ro.miui.ui.version.name";
+    private static final String KEY_MIUI_INTERNAL_STORAGE = "ro.miui.internal.storage";
+
+    /**
+     * 鑾峰彇娓犻亾
+     */
+    public static String getChannel() {
+        return "";
+    }
+
+    /**
+     * 鑾峰彇鎵嬫満瀹介珮
+     */
+    public static String getPhonePixels(Activity activity) {
+        if (activity != null) {
+            DisplayMetrics dm = new DisplayMetrics();
+            activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
+            int widthPixels = dm.widthPixels;
+            int heightPixels = dm.heightPixels;
+            return widthPixels + "-" + heightPixels;
+        }
+        return "0-0";
+    }
+
+    /**
+     * x
+     * 灞忓箷瀹藉害
+     */
+    public static int getDeviceWidth(Context context) {
+        if (context != null) {
+            WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+            if (wm != null) {
+                Point p = new Point();
+                wm.getDefaultDisplay().getSize(p);
+                return p.x;
+            }
+        }
+        return 0;
+    }
+
+    /**
+     * 灞忓箷瀹藉害
+     */
+    public static int getDeviceWidth(Activity activity) {
+        if (activity != null) {
+            DisplayMetrics dm = new DisplayMetrics();
+            activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
+            return dm.widthPixels;
+        }
+        return 0;
+    }
+
+    /**
+     * 灞忓箷楂樺害
+     */
+    public static int getDeviceHeight(Activity activity) {
+        if (activity != null) {
+            DisplayMetrics dm = new DisplayMetrics();
+            activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
+            return dm.heightPixels;
+        }
+        return 0;
+    }
+
+
+    /**
+     * 鍒ゆ柇褰撳墠鏈夋病鏈夌綉缁滆繛鎺�
+     */
+    public static boolean getNetworkState() {
+        Context context = ContextHelper.getAppContext();
+        if (context != null) {
+            ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+            NetworkInfo networkinfo = manager.getActiveNetworkInfo();
+            return !(networkinfo == null || !networkinfo.isAvailable());
+        }
+        return false;
+    }
+
+    /**
+     * SD鍗℃槸鍚︽寕杞�
+     */
+    public static boolean mountedSdCard() {
+        return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
+    }
+
+    /**
+     * 妫�娴嬪簲鐢ㄦ槸鍚﹀畨瑁�
+     **/
+    public static boolean isApkInstalled(String packageName) {
+        Context context = ContextHelper.getAppContext();
+        if (context != null) {
+            final PackageManager packageManager = context.getPackageManager();
+            List<PackageInfo> pinfo = packageManager.getInstalledPackages(0);
+            for (int i = 0; i < pinfo.size(); i++) {
+                if (pinfo.get(i).packageName.equalsIgnoreCase(packageName)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+        return false;
+    }
+
+    /**
+     * 鎵撶數璇�
+     */
+    public static void callPhone(Activity activity, String phone) {
+        Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + phone));
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        activity.startActivity(intent);
+    }
+
+    /**
+     * 璋冪敤绯荤粺鍙戦�佺煭淇�
+     */
+    public static void sendSMSView(Activity activity, String phone, String sms) {
+        Uri smsToUri = Uri.parse("smsto:" + phone);
+        Intent sendIntent = new Intent(Intent.ACTION_SENDTO, smsToUri);
+        sendIntent.putExtra("sms_body", sms);
+        activity.startActivity(sendIntent);
+    }
+
+    private static TelephonyManager getTelManager() {
+        Context context = ContextHelper.getAppContext();
+        if (context == null) {
+            return null;
+        }
+        return (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+    }
+
+    /**
+     * 鑾峰彇ISO鍥藉鐮侊紝鐩稿綋浜庢彁渚汼IM鍗$殑鍥藉鐮�
+     */
+    public static String getSimCountryIso() {
+        if (getTelManager() != null) {
+            return getTelManager().getSimCountryIso();
+        }
+
+        return Strings.EMPTY;
+    }
+
+    /**
+     * 鑾峰彇杩愯惀鍟嗗悕绉�
+     */
+    public static String getSimOperatorName() {
+        if (getTelManager() != null && SIM_STATE_READY == getTelManager().getSimState()) {
+            return getTelManager().getSimOperatorName();
+        }
+
+        return Strings.EMPTY;
+    }
+
+    /**
+     * 鑾峰彇绯荤粺杩愯鍐呭瓨澶у皬 鍗曚綅KB
+     */
+    public static long getTotalMemory() {
+        String str1 = "/proc/meminfo";// 绯荤粺鍐呭瓨淇℃伅鏂囦欢
+        String str2;
+        String[] arrayOfString;
+        long initial_memory = 0;
+
+        try {
+            FileReader localFileReader = new FileReader(str1);
+            BufferedReader localBufferedReader = new BufferedReader(
+                    localFileReader, 8192);
+            str2 = localBufferedReader.readLine();// 璇诲彇meminfo绗竴琛岋紝绯荤粺鎬诲唴瀛樺ぇ灏�
+            if (TextUtils.isEmpty(str2)) {
+                arrayOfString = str2.split("\\s+");
+                initial_memory = Integer.valueOf(arrayOfString[1]);// 鑾峰緱绯荤粺鎬诲唴瀛橈紝鍗曚綅鏄疜B
+            }
+            localBufferedReader.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return initial_memory;// Byte杞崲涓篕B鎴栬�匨B锛屽唴瀛樺ぇ灏忚鏍煎寲
+    }
+
+    /**
+     * 璁惧璇█缂栫爜
+     */
+    public static String getLanguage() {
+        String language = Strings.EMPTY;
+        Resources resources = ContextHelper.getResources();
+        if (resources != null) {
+            Locale locale = ContextHelper.getResources().getConfiguration().locale;
+            language = locale.getLanguage();
+        }
+
+        return language;
+    }
+
+    /**
+     * 鑾峰彇鏈鸿韩鎬诲瓨鍌�(涓嶅寘鍚玈D鍗�)
+     */
+    public static long getRomMemory() {
+        long[] romInfo = new long[1];
+        File path = Environment.getDataDirectory();
+        StatFs stat = new StatFs(path.getPath());
+        long blockSize = stat.getBlockSize();
+        long totalBlocks = stat.getBlockCount();
+        //Total rom memory
+        romInfo[0] = blockSize * totalBlocks;
+        return romInfo[0];
+    }
+
+    /**
+     * 鑾峰彇CPU鏈�澶ч鐜囷紙鍗曚綅KHZ锛�
+     */
+    public static String getMaxCpuFreq() {
+        StringBuilder result = new StringBuilder(Strings.EMPTY);
+        ProcessBuilder cmd;
+        try {
+            String[] args = {"/system/bin/cat",
+                    "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq"};
+            cmd = new ProcessBuilder(args);
+            Process process = cmd.start();
+            InputStream in = process.getInputStream();
+            byte[] re = new byte[24];
+            while (in.read(re) != -1) {
+                result.append(new String(re));
+            }
+            in.close();
+        } catch (IOException ex) {
+            ex.printStackTrace();
+            result = new StringBuilder("N/A");
+        }
+        return result.toString().trim();
+    }
+
+    /**
+     * 鏄惁鍙栧埌鎵�鏈変俊鎭�
+     */
+    private static boolean isGetSuccess() {
+        return !TextUtils.isEmpty(getPhoneModel()) && !TextUtils.isEmpty(getFactory())
+                && !TextUtils.isEmpty(getMaxCpuFreq()) && getRomMemory() > 0 && getTotalMemory() > 0;
+    }
+}
diff --git a/third-zxing/src/main/java/com/zxing/Extras.java b/third-zxing/src/main/java/com/zxing/Extras.java
new file mode 100644
index 0000000..62090d9
--- /dev/null
+++ b/third-zxing/src/main/java/com/zxing/Extras.java
@@ -0,0 +1,34 @@
+package com.zxing;
+
+/**
+ * 璺ㄦā鍧楀弬鏁板畾涔�
+ * 娉ㄦ剰锛氭绫讳粎浠呯敤浜庡瓨鏀捐法妯″潡鐨勫弬鏁帮紝妯″潡鍐呯殑鍙傛暟璇锋斁鍦ㄦā鍧楃殑constants鐞�
+ * <p>
+ *
+ */
+public interface Extras {
+
+    interface device{
+        String EXREAS_CHANNEL = "extra_channel";
+        String EXTRAS_DEVICE_DISPATCH = "extra_device_dispatch";
+        String EXTRAS_FROM_DISPATCH = "extra_from_dispatch";
+    }
+
+    interface enterprise {
+        String cropId = "extra_crop_id";
+        String appId = "extra_app_id";
+        String deptId = "extra_dept_id";
+        String CREATE_DEPT = "extra_create_dept";//缁勭粐鏋舵瀯鍒涘缓閮ㄩ棬
+    }
+
+
+    /**
+     * from
+     **/
+    interface FROM {
+        String FROM = "from";
+        String SCAN_BACK = "scan";
+        String H5_SCAN_JUMP = "scan_jump";
+    }
+
+}
diff --git a/third-zxing/src/main/java/com/zxing/IZxingActivity.java b/third-zxing/src/main/java/com/zxing/IZxingActivity.java
new file mode 100644
index 0000000..a8b496a
--- /dev/null
+++ b/third-zxing/src/main/java/com/zxing/IZxingActivity.java
@@ -0,0 +1,28 @@
+package com.zxing;
+
+import android.content.Intent;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.Handler;
+
+import com.google.zxing.Result;
+import com.zxing.camera.CameraManager;
+
+
+public interface IZxingActivity {
+    Handler getHandler();
+
+    void startActivity(Intent intent);
+
+    void setResult(int code, Intent intent);
+
+    void finish();
+
+    void drawViewfinder();
+
+    CameraManager getCameraManager();
+
+    Rect getCropRect();
+
+    void handleDecode(Result obj, Bundle bundle);
+}
diff --git a/third-zxing/src/main/java/com/zxing/camera/AutoFocusManager.java b/third-zxing/src/main/java/com/zxing/camera/AutoFocusManager.java
new file mode 100644
index 0000000..f87262a
--- /dev/null
+++ b/third-zxing/src/main/java/com/zxing/camera/AutoFocusManager.java
@@ -0,0 +1,114 @@
+package com.zxing.camera;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.hardware.Camera;
+import android.os.AsyncTask;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.concurrent.RejectedExecutionException;
+
+public class AutoFocusManager implements Camera.AutoFocusCallback {
+
+    private static final String TAG = AutoFocusManager.class.getSimpleName();
+
+    private static final long AUTO_FOCUS_INTERVAL_MS = 1800L;
+    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 final boolean useAutoFocus;
+    private final Camera camera;
+    private boolean stopped;
+    private boolean focusing;
+    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 {
+                newTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+                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;
+        }
+    }
+
+}
diff --git a/third-zxing/src/main/java/com/zxing/camera/CameraConfigurationManager.java b/third-zxing/src/main/java/com/zxing/camera/CameraConfigurationManager.java
new file mode 100644
index 0000000..e55cb14
--- /dev/null
+++ b/third-zxing/src/main/java/com/zxing/camera/CameraConfigurationManager.java
@@ -0,0 +1,207 @@
+package com.zxing.camera;
+
+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;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * 鎻忚堪: 璇ョ被涓昏璐熻矗璁剧疆鐩告満鐨勫弬鏁颁俊鎭紝鑾峰彇鏈�浣崇殑棰勮鐣岄潰
+ */
+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;
+    }
+}
diff --git a/third-zxing/src/main/java/com/zxing/camera/CameraManager.java b/third-zxing/src/main/java/com/zxing/camera/CameraManager.java
new file mode 100644
index 0000000..289b6fb
--- /dev/null
+++ b/third-zxing/src/main/java/com/zxing/camera/CameraManager.java
@@ -0,0 +1,195 @@
+package com.zxing.camera;
+
+import android.content.Context;
+import android.content.pm.FeatureInfo;
+import android.content.pm.PackageManager;
+import android.graphics.Point;
+import android.hardware.Camera;
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCharacteristics;
+import android.os.Build;
+import android.os.Handler;
+import android.util.Log;
+import android.view.SurfaceHolder;
+
+import com.zxing.camera.open.OpenCameraInterface;
+
+import java.io.IOException;
+
+/**
+ * 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.
+ */
+public class CameraManager {
+
+    private static final String TAG = CameraManager.class.getSimpleName();
+    private boolean status = false;     // 璁板綍鎵嬫満鐘舵��
+    private final Context context;
+    private final CameraConfigurationManager configManager;
+    /**
+     * 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;
+    private Camera camera;
+    private AutoFocusManager autoFocusManager;
+    private boolean initialized;
+    private boolean previewing;
+    private int requestedCameraId = -1;
+
+    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 Camera.Size getPreviewSize() {
+        if (null != camera) {
+            return camera.getParameters().getPreviewSize();
+        }
+        return null;
+    }
+
+    public Camera getCamera() {
+       return camera;
+    }
+
+
+}
diff --git a/third-zxing/src/main/java/com/zxing/camera/PreviewCallback.java b/third-zxing/src/main/java/com/zxing/camera/PreviewCallback.java
new file mode 100644
index 0000000..214d334
--- /dev/null
+++ b/third-zxing/src/main/java/com/zxing/camera/PreviewCallback.java
@@ -0,0 +1,40 @@
+package com.zxing.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");
+        }
+    }
+
+}
diff --git a/third-zxing/src/main/java/com/zxing/camera/open/OpenCameraInterface.java b/third-zxing/src/main/java/com/zxing/camera/open/OpenCameraInterface.java
new file mode 100644
index 0000000..79fd06f
--- /dev/null
+++ b/third-zxing/src/main/java/com/zxing/camera/open/OpenCameraInterface.java
@@ -0,0 +1,69 @@
+package com.zxing.camera.open;
+
+import android.hardware.Camera;
+import android.util.Log;
+
+public class OpenCameraInterface {
+
+    private static final String TAG = OpenCameraInterface.class.getName();
+
+    /**
+     * Opens the requested camera with {@link Camera#open(int)}, if one exists.
+     *
+     * @param cameraId camera ID of the camera to use. A negative value means
+     *                 "no preference"
+     * @return handle to {@link Camera} that was opened
+     */
+    public static Camera open(int cameraId) {
+
+        int numCameras = Camera.getNumberOfCameras();
+        if (numCameras == 0) {
+            Log.w(TAG, "No cameras!");
+            return null;
+        }
+
+        boolean explicitRequest = cameraId >= 0;
+
+        if (!explicitRequest) {
+            // Select a camera if no explicit camera requested
+            int index = 0;
+            while (index < numCameras) {
+                Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
+                Camera.getCameraInfo(index, cameraInfo);
+                if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
+                    break;
+                }
+                index++;
+            }
+
+            cameraId = index;
+        }
+
+        Camera camera;
+        if (cameraId < numCameras) {
+            Log.i(TAG, "Opening camera #" + cameraId);
+            camera = Camera.open(cameraId);
+        } else {
+            if (explicitRequest) {
+                Log.w(TAG, "Requested camera does not exist: " + cameraId);
+                camera = null;
+            } else {
+                Log.i(TAG, "No camera facing back; returning camera #0");
+                camera = Camera.open(0);
+            }
+        }
+
+        return camera;
+    }
+
+    /**
+     * Opens a rear-facing camera with {@link Camera#open(int)}, if one exists,
+     * or opens camera 0.
+     *
+     * @return handle to {@link Camera} that was opened
+     */
+    public static Camera open() {
+        return open(-1);
+    }
+
+}
diff --git a/third-zxing/src/main/java/com/zxing/decode/DecodeFormatManager.java b/third-zxing/src/main/java/com/zxing/decode/DecodeFormatManager.java
new file mode 100644
index 0000000..b7c9b74
--- /dev/null
+++ b/third-zxing/src/main/java/com/zxing/decode/DecodeFormatManager.java
@@ -0,0 +1,37 @@
+package com.zxing.decode;
+
+import com.google.zxing.BarcodeFormat;
+
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.Set;
+
+public class DecodeFormatManager {
+
+    // 1D瑙g爜
+    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;
+    }
+}
diff --git a/third-zxing/src/main/java/com/zxing/decode/DecodeHandler.java b/third-zxing/src/main/java/com/zxing/decode/DecodeHandler.java
new file mode 100644
index 0000000..6c6212f
--- /dev/null
+++ b/third-zxing/src/main/java/com/zxing/decode/DecodeHandler.java
@@ -0,0 +1,136 @@
+package com.zxing.decode;
+
+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.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;
+import com.zxing.IZxingActivity;
+import com.zxing.R;
+
+import java.io.ByteArrayOutputStream;
+import java.util.Map;
+
+public class DecodeHandler extends Handler {
+
+    private final IZxingActivity activity;
+    private final MultiFormatReader multiFormatReader;
+    private boolean running = true;
+
+    public DecodeHandler(IZxingActivity activity, Map<DecodeHintType, Object> hints) {
+        multiFormatReader = new MultiFormatReader();
+        multiFormatReader.setHints(hints);
+        this.activity = activity;
+    }
+
+    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());
+    }
+
+    @Override
+    public void handleMessage(Message message) {
+        if (!running) {
+            return;
+        }
+        if (message.what == R.id.decode) {
+            decode((byte[]) message.obj, message.arg1, message.arg2);
+
+        } else if (message.what == R.id.quit) {
+            running = false;
+            Looper.myLooper().quit();
+
+        }
+    }
+
+    /**
+     * 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();
+
+        // 杩欓噷闇�瑕佸皢鑾峰彇鐨刣ata缈昏浆涓�涓嬶紝鍥犱负鐩告満榛樿鎷跨殑鐨勬í灞忕殑鏁版嵁
+        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();
+            }
+        }
+
+    }
+
+    /**
+     * 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);
+    }
+
+}
diff --git a/third-zxing/src/main/java/com/zxing/decode/DecodeThread.java b/third-zxing/src/main/java/com/zxing/decode/DecodeThread.java
new file mode 100644
index 0000000..319461b
--- /dev/null
+++ b/third-zxing/src/main/java/com/zxing/decode/DecodeThread.java
@@ -0,0 +1,82 @@
+package com.zxing.decode;
+
+import android.os.Handler;
+import android.os.Looper;
+
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.DecodeHintType;
+import com.zxing.IZxingActivity;
+
+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;
+
+/**
+ * This thread does all the heavy lifting of decoding the images.
+ */
+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 IZxingActivity activity;
+    private final Map<DecodeHintType, Object> hints;
+    private final CountDownLatch handlerInitLatch;
+    private Handler handler;
+
+    public DecodeThread(IZxingActivity 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();
+    }
+
+}
diff --git a/third-zxing/src/main/java/com/zxing/decode/RGBLuminanceSource.java b/third-zxing/src/main/java/com/zxing/decode/RGBLuminanceSource.java
new file mode 100644
index 0000000..bc53f0a
--- /dev/null
+++ b/third-zxing/src/main/java/com/zxing/decode/RGBLuminanceSource.java
@@ -0,0 +1,72 @@
+package com.zxing.decode;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+
+import com.google.zxing.LuminanceSource;
+
+import java.io.FileNotFoundException;
+
+public class RGBLuminanceSource extends LuminanceSource {
+    private final byte[] luminances;
+
+    public RGBLuminanceSource(String path) throws FileNotFoundException {
+        this(loadBitmap(path));
+    }
+
+    public RGBLuminanceSource(Bitmap bitmap) {
+        super(bitmap.getWidth(), bitmap.getHeight());
+        int width = bitmap.getWidth();
+        int height = bitmap.getHeight();
+        int[] pixels = new int[width * height];
+        bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
+        // In order to measure pure decoding speed, we convert the entire image
+        // to a greyscale array
+        // up front, which is the same as the Y channel of the
+        // YUVLuminanceSource in the real app.
+        luminances = new byte[width * height];
+        for (int y = 0; y < height; y++) {
+            int offset = y * width;
+            for (int x = 0; x < width; x++) {
+                int pixel = pixels[offset + x];
+                int r = (pixel >> 16) & 0xff;
+                int g = (pixel >> 8) & 0xff;
+                int b = pixel & 0xff;
+                if (r == g && g == b) {
+                    // Image is already greyscale, so pick any channel.
+                    luminances[offset + x] = (byte) r;
+                } else {
+                    // Calculate luminance cheaply, favoring green.
+                    luminances[offset + x] = (byte) ((r + g + g + b) >> 2);
+                }
+            }
+        }
+    }
+
+    @Override
+    public byte[] getRow(int y, byte[] row) {
+        if (y < 0 || y >= getHeight()) {
+            throw new IllegalArgumentException(
+                    "Requested row is outside the image: " + y);
+        }
+        int width = getWidth();
+        if (row == null || row.length < width) {
+            row = new byte[width];
+        }
+        System.arraycopy(luminances, y * width, row, 0, width);
+        return row;
+    }
+
+    @Override
+    public byte[] getMatrix() {
+        return luminances;
+    }
+
+    private static Bitmap loadBitmap(String path) throws FileNotFoundException {
+        Bitmap bitmap = BitmapFactory.decodeFile(path);
+        if (bitmap == null) {
+            throw new FileNotFoundException("Couldn't open " + path);
+        }
+        return bitmap;
+    }
+}
diff --git a/third-zxing/src/main/java/com/zxing/qrcode/CaptureActivity.java b/third-zxing/src/main/java/com/zxing/qrcode/CaptureActivity.java
new file mode 100644
index 0000000..8e15982
--- /dev/null
+++ b/third-zxing/src/main/java/com/zxing/qrcode/CaptureActivity.java
@@ -0,0 +1,398 @@
+package com.zxing.qrcode;///*
+
+import android.app.Activity;
+import android.content.Intent;
+import android.database.Cursor;
+import android.graphics.Rect;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.provider.MediaStore;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.View;
+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.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.Toast;
+
+import androidx.appcompat.content.res.AppCompatResources;
+
+import com.google.zxing.BinaryBitmap;
+import com.google.zxing.ChecksumException;
+import com.google.zxing.DecodeHintType;
+import com.google.zxing.FormatException;
+import com.google.zxing.NotFoundException;
+import com.google.zxing.Result;
+import com.google.zxing.common.HybridBinarizer;
+import com.google.zxing.qrcode.QRCodeReader;
+import com.zxing.IZxingActivity;
+import com.zxing.R;
+import com.zxing.camera.CameraManager;
+import com.zxing.decode.DecodeThread;
+import com.zxing.decode.RGBLuminanceSource;
+import com.zxing.utils.BeepManager;
+import com.zxing.utils.CaptureActivityHandler;
+import com.zxing.utils.InactivityTimer;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.Hashtable;
+
+/**
+ * 鐢ㄩ�旓細鎵竴鎵�
+ */
+public final class CaptureActivity extends Activity implements IZxingActivity, SurfaceHolder.Callback {
+    private static final String TAG = CaptureActivity.class.getSimpleName();
+    private final int REQUEST_CODE = 33;
+    private CameraManager cameraManager;
+    private CaptureActivityHandler handler;
+    private InactivityTimer inactivityTimer;
+    private BeepManager beepManager;
+    private SurfaceView scanPreview = null;
+    private RelativeLayout scanContainer;
+    private RelativeLayout scanCropView;
+    private LinearLayout backll;
+    private ImageView light_iv;
+    private Rect mCropRect = null;
+    private boolean isHasSurface = false;
+
+    @Override
+    public Handler getHandler() {
+        return handler;
+    }
+
+    @Override
+    public void drawViewfinder() {
+
+    }
+
+    @Override
+    public CameraManager getCameraManager() {
+        return cameraManager;
+    }
+
+    public int getRootLayoutId() {
+        return R.layout.activity_capture;
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        Window window = getWindow();
+        window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+        //璁剧疆鏍硅鍥�
+        View mContentView = LayoutInflater.from(this).inflate(getRootLayoutId(), null);
+        setContentView(mContentView);
+        afterViewBind(mContentView, savedInstanceState);
+
+
+    }
+
+    public void afterViewBind(View rootView, Bundle savedInstanceState) {
+
+        light_iv = findViewById(R.id.light_iv);
+        backll = findViewById(R.id.top_back_btn);
+        backll.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                finish();
+            }
+        });
+        scanPreview = findViewById(R.id.capture_preview);
+        scanContainer = findViewById(R.id.capture_container);
+        scanCropView = findViewById(R.id.capture_crop_view);
+        ImageView scanLine = 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(2000);
+        animation.setRepeatCount(-1);
+        animation.setRepeatMode(Animation.RESTART);
+        scanLine.startAnimation(animation);
+        light_iv.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                v.setSelected(!v.isSelected());
+                if (v.isSelected()) {
+//                    cameraManager.open();
+                    light_iv.setImageDrawable(AppCompatResources.getDrawable(CaptureActivity.this, R.drawable.fast_scan_light_open));
+                } else {
+//                    cameraManager.close();
+                    light_iv.setImageDrawable(AppCompatResources.getDrawable(CaptureActivity.this, R.drawable.fast_scan_light_close));
+                }
+
+            }
+        });
+
+    }
+
+    public void enterGallery() {
+        // 杩涘叆鍥惧簱
+        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
+        intent.addCategory(Intent.CATEGORY_OPENABLE);
+        intent.setType("image/*");
+        intent.putExtra("return-data", true);
+        startActivityForResult(intent, REQUEST_CODE);
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        cameraManager = new CameraManager(getApplication());
+        handler = null;
+        if (isHasSurface) {
+            initCamera(scanPreview.getHolder());
+        } else {
+            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.d(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
+     */
+    @Override
+    public void handleDecode(Result rawResult, Bundle bundle) {
+        inactivityTimer.onActivity();
+        beepManager.playBeepSoundAndVibrate();
+        doProcess(rawResult.getText());
+        restartPreviewAfterDelay(3000);
+    }
+
+    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);
+            Toast.makeText(this, R.string.capture_no_camera, Toast.LENGTH_SHORT).show();
+            finish();
+        } catch (RuntimeException e) {
+            Log.w(TAG, "Unexpected error initializing camera", e);
+            Toast.makeText(this, R.string.capture_no_camera, Toast.LENGTH_SHORT).show();
+            finish();
+        }
+    }
+
+    public void restartPreviewAfterDelay(long delayMS) {
+        if (handler != null) {
+            handler.sendEmptyMessageDelayed(R.id.restart_preview, delayMS);
+        }
+    }
+
+    @Override
+    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;
+    }
+
+    private void doProcess(String result) {
+        Log.d("panlili", "scanResult: " + result);
+        /*if (!DeviceHelper.getNetworkState()) {
+            Toast.makeText(this, R.string.capture_no_network, Toast.LENGTH_SHORT).show();
+            return;
+        }*/
+
+        if (TextUtils.isEmpty(result)) {
+            Toast.makeText(this, R.string.capture_no_result, Toast.LENGTH_SHORT).show();
+        } else {
+            Intent intent = new Intent();
+            intent.putExtra("data", result);
+            setResult(RESULT_OK, intent);
+            finish();
+        }
+    }
+
+    @Override
+    public void onActivityResult(int requestCode, int resultCode, Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+        if (requestCode == REQUEST_CODE && resultCode == RESULT_OK && data != null) {
+            Uri originalUri = data.getData();
+            if (originalUri != null) {
+                String path = originalUri.getPath();
+                String[] proj = {MediaStore.Images.Media.DATA};
+                Cursor cursor = getContentResolver().query(originalUri, proj, null, null, null);
+                if (cursor != null) {
+                    int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
+                    cursor.moveToFirst();
+                    path = cursor.getString(column_index);
+                    cursor.close();
+                }
+
+                if (!TextUtils.isEmpty(path)) {
+                    handleQRCodeFormPhoto(path);
+                } else {
+                    Toast.makeText(this, "鍥剧墖宸叉崯鍧忥紝璇烽噸鏂伴�夋嫨锛�", Toast.LENGTH_SHORT).show();
+                }
+            }
+        }
+    }
+
+    /**
+     * 瑙f瀽鍥惧簱閫夋嫨鐨勪簩缁寸爜
+     */
+    public void handleQRCodeFormPhoto(final String filePath) {
+        Thread dealThread = new Thread(new Runnable() {
+            @Override
+            public void run() {
+                Hashtable<DecodeHintType, String> hints = new Hashtable<>();
+                hints.put(DecodeHintType.CHARACTER_SET, "utf-8");
+                RGBLuminanceSource source = null;
+                try {
+                    source = new RGBLuminanceSource(filePath);
+                } catch (FileNotFoundException e) {
+                    e.printStackTrace();
+                }
+                BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(source));
+                QRCodeReader reader = new QRCodeReader();
+                Result result;
+                try {
+                    result = reader.decode(binaryBitmap, hints);
+                    if (!TextUtils.isEmpty(result.getText())) {
+                        dealUIInfo(result.getText());
+                    } else {
+                        dealUIInfo(null);
+                    }
+                } catch (NotFoundException | ChecksumException | FormatException e) {
+                    dealUIInfo(null);
+                    e.printStackTrace();
+                }
+            }
+        });
+        dealThread.start();
+    }
+
+    private void dealUIInfo(final Object progressInfo) {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                if (progressInfo == null) {
+                    Toast.makeText(CaptureActivity.this, R.string.capture_no_result2, Toast.LENGTH_SHORT).show();
+                } else {
+                    doProcess(progressInfo.toString());
+                }
+            }
+        });
+    }
+
+
+}
\ No newline at end of file
diff --git a/third-zxing/src/main/java/com/zxing/utils/BeepManager.java b/third-zxing/src/main/java/com/zxing/utils/BeepManager.java
new file mode 100644
index 0000000..c0fca3c
--- /dev/null
+++ b/third-zxing/src/main/java/com/zxing/utils/BeepManager.java
@@ -0,0 +1,125 @@
+package com.zxing.utils;
+
+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.zxing.R;
+
+import java.io.Closeable;
+import java.io.IOException;
+
+/**
+ * Manages beeps and vibrations for {}.
+ */
+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 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 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 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;
+        }
+    }
+
+}
diff --git a/third-zxing/src/main/java/com/zxing/utils/CaptureActivityHandler.java b/third-zxing/src/main/java/com/zxing/utils/CaptureActivityHandler.java
new file mode 100644
index 0000000..9be31c5
--- /dev/null
+++ b/third-zxing/src/main/java/com/zxing/utils/CaptureActivityHandler.java
@@ -0,0 +1,95 @@
+package com.zxing.utils;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+
+import com.google.zxing.Result;
+import com.zxing.IZxingActivity;
+import com.zxing.R;
+import com.zxing.camera.CameraManager;
+import com.zxing.decode.DecodeThread;
+
+/**
+ * This class handles all the messaging which comprises the state machine for
+ * capture.
+ */
+public class CaptureActivityHandler extends Handler {
+
+    private final IZxingActivity activity;
+    private final DecodeThread decodeThread;
+    private final CameraManager cameraManager;
+    private State state;
+
+    public CaptureActivityHandler(IZxingActivity 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) {
+        if (message.what == R.id.restart_preview) {
+            restartPreviewAndDecode();
+
+        } else if (message.what == R.id.decode_succeeded) {
+            state = State.SUCCESS;
+            Bundle bundle = message.getData();
+
+            activity.handleDecode((Result) message.obj, bundle);
+
+        } else if (message.what == 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);
+
+        } else if (message.what == R.id.return_scan_result) {
+            activity.setResult(Activity.RESULT_OK, (Intent) message.obj);
+            activity.finish();
+
+        }
+    }
+
+    public void quitSynchronously() {
+        state = State.DONE;
+        try {
+            cameraManager.stopPreview();
+        } catch (RuntimeException e) {
+
+        }
+        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);
+        }
+    }
+
+    private enum State {
+        PREVIEW, SUCCESS, DONE
+    }
+
+}
diff --git a/third-zxing/src/main/java/com/zxing/utils/InactivityTimer.java b/third-zxing/src/main/java/com/zxing/utils/InactivityTimer.java
new file mode 100644
index 0000000..750b01f
--- /dev/null
+++ b/third-zxing/src/main/java/com/zxing/utils/InactivityTimer.java
@@ -0,0 +1,108 @@
+package com.zxing.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;
+        }
+    }
+
+}
diff --git a/third-zxing/src/main/java/com/zxing/utils/Strings.java b/third-zxing/src/main/java/com/zxing/utils/Strings.java
new file mode 100644
index 0000000..f736e6b
--- /dev/null
+++ b/third-zxing/src/main/java/com/zxing/utils/Strings.java
@@ -0,0 +1,179 @@
+package com.zxing.utils;
+
+import android.text.TextUtils;
+
+import java.util.Iterator;
+import java.util.regex.Pattern;
+
+public abstract class Strings {
+    public static final String EMPTY = "";
+    public static final String BLANK = " ";
+    public static final String EQUAL = "=";
+    public static final String AND = "&";
+    public static final String QMARK = "?";
+    public static final String TRUE = "true";
+    public static final String FALSE = "false";
+    public static final String CANCEL = "cancel";
+    public static final String NULL_STR = "null";
+    public static final String SUCCESS = "success";
+    public static final String FAIL = "fail";
+    public static final String ZERO = "0";
+    public static final String SEMICOLON = ";";
+    public static final String SPLITE = "/";
+    public static final String AT = "@";
+    public static final String COMMA = ",";
+    public static final String FILE_PRE = "file://";
+    public static final String HTTP_PRE = "http";
+    public static final String COLON = ":";
+    public static final String WRAP = "";
+    public static final String STAR = "*";
+    public static final String MORE = "...";
+
+    /**
+     * 鍘婚櫎瀛楃涓蹭腑鐨勭┖鏍�
+     */
+    public static String trimAll(CharSequence s) {
+        if (s == null || s.length() == 0) return Strings.EMPTY;
+        StringBuilder sb = new StringBuilder(s.length());
+        for (int i = 0, L = s.length(); i < L; i++) {
+            char c = s.charAt(i);
+            if (c != ' ') sb.append(c);
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 鍒ゆ柇鏄惁涓烘墜鏈哄彿鐮�
+     */
+    public static boolean isPhoneNum(String phoneNum) {
+        if (phoneNum == null || phoneNum.length() != 11) return false;
+        if (!TextUtils.isDigitsOnly(phoneNum)) return false;
+        Pattern p = Pattern.compile("^((13[0-9])|(14[0-9])|(15[^4,\\D])|(17[0-9])|(18[0-9]))\\d{8}$");
+        return p.matcher(phoneNum).find();
+    }
+
+    /**
+     * 鍒ゆ柇鏄惁涓哄骇鏈哄彿鐮�
+     */
+    public static boolean isTelNum(String num) {
+        if (TextUtils.isEmpty(num)) return false;
+        Pattern p = Pattern.compile("(\\(\\d{3,4}\\)|\\d{3,4}-|\\s)?\\d{8}");
+        return p.matcher(num).find();
+    }
+
+    /**
+     * 鍒ゆ柇瀛楃涓蹭腑鏄惁鏈変腑鏂囷紝鏈変腑鏂囪繑鍥瀟rue
+     */
+    public static boolean isChinese(String string) {
+        boolean flag = false;
+        for (int i = 0, L = string.length(); i < L; i++) {
+            char c = string.charAt(i);
+            if ((c >= 0x4e00) && (c <= 0x9FA5)) {
+                flag = true;
+            } else {
+                return false;
+            }
+        }
+        return flag;
+    }
+
+    /**
+     * 鍒ゆ柇瀛楃闀垮害鏄惁鍦ㄨ寖鍥撮噷闈€�� 褰搒tart end 涓� -1 鏃讹紝琛ㄧず瀛楃闀垮害涓嶈�冭檻涓婄嚎鎴栦笅绾�
+     *
+     * @param str
+     * @param start
+     * @param end
+     * @return
+     */
+    public static boolean isLengthInRange(String str, int start, int end) {
+        boolean isInRange = true;
+        int length = str.length();
+        if (start != -1 && length < start) {
+            isInRange = false;
+        }
+        if (end != -1 && end < length) {
+            isInRange = false;
+        }
+        return isInRange;
+    }
+
+    /**
+     * 瀛楃涓茶浆鎹负long鍨�
+     */
+    public static long toLong(String text, long defaultVal) {
+        if (TextUtils.isDigitsOnly(text)) {
+            try {
+                return Long.parseLong(text);
+            } catch (NumberFormatException e) {
+            }
+        }
+        return defaultVal;
+    }
+
+    /**
+     * 瀛楃涓茶浆鎹负int
+     */
+    public static int toInt(String text, int defaultVal) {
+        if (TextUtils.isDigitsOnly(text)) {
+            try {
+                return Integer.parseInt(text);
+            } catch (NumberFormatException e) {
+            }
+        }
+        return defaultVal;
+    }
+
+
+    public static String join(Iterable<?> iterable, String separator) {
+
+        // handle null, zero and one elements before building a buffer
+        if (iterable == null) {
+            return null;
+        }
+        Iterator<?> iterator = iterable.iterator();
+        if (!iterator.hasNext()) {
+            return EMPTY;
+        }
+        Object first = iterator.next();
+        if (!iterator.hasNext()) {
+            return toString(first);
+        }
+
+        // two or more elements
+        StringBuffer buf = new StringBuffer(256); // Java default is 16, probably too small
+        if (first != null) {
+            buf.append(first);
+        }
+
+        while (iterator.hasNext()) {
+            if (separator != null) {
+                buf.append(separator);
+            }
+            Object obj = iterator.next();
+            if (obj != null) {
+                buf.append(obj);
+            }
+        }
+        return buf.toString();
+    }
+
+    public static String toString(Object obj) {
+        return obj == null ? "" : obj.toString();
+    }
+
+    /**
+     * 鍒ゆ柇鏄惁涓哄瓧绗︿覆鏄惁涓虹┖
+     */
+    public static boolean toBoolean(String property, boolean defaultVal) {
+        return property == null ? defaultVal : Boolean.valueOf(property);
+    }
+
+    public static String format(String str, Object... obj) {
+        try {
+            return String.format(str, obj);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return str;
+    }
+}
diff --git a/third-zxing/src/main/java/com/zxing/utils/Validator.java b/third-zxing/src/main/java/com/zxing/utils/Validator.java
new file mode 100644
index 0000000..f461d5a
--- /dev/null
+++ b/third-zxing/src/main/java/com/zxing/utils/Validator.java
@@ -0,0 +1,202 @@
+package com.zxing.utils;
+
+import android.annotation.SuppressLint;
+import android.text.TextUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * 姝e垯琛ㄨ揪寮�
+ *
+ */
+@SuppressLint("WrongConstant")
+public class Validator {
+
+    public static boolean password(String password) {
+        return password.matches("[0-9a-zA-Z]{8,16}") && !password.matches("[0-9]+") && !password.matches("[a-zA-Z]+");
+    }
+
+    public static List<String> findMac(String src) {
+        List<String> list = new ArrayList<String>();
+        if (src == null || "".equals(src))
+            return list;
+        Pattern pattern = Pattern
+                .compile("[0-9a-z]{2}:[0-9a-z]{2}:[0-9a-z]{2}:[0-9a-z]{2}:[0-9a-z]{2}:[0-9a-z]{2}");
+        Matcher matcher = pattern.matcher(src);
+        while (matcher.find()) {
+            list.add(matcher.group(0));
+        }
+        return list;
+    }
+
+    public static List<String> findColor(String src) {
+        List<String> list = new ArrayList<String>();
+        if (src == null || src.equals(""))
+            return list;
+        Pattern pattern = Pattern
+                .compile("#[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8}");
+        Matcher matcher = pattern.matcher(src);
+        while (matcher.find()) {
+            list.add(matcher.group(0));
+        }
+        return list;
+    }
+
+    /**
+     * 鍘婚櫎姹夊瓧,褰掓缂栫爜
+     */
+    public static String replaceHanzi(String input) {
+        if (TextUtils.isEmpty(input)) {
+            return "";
+        }
+
+        /**
+         * 褰掓缂栫爜
+         */
+        byte[] bytes = input.getBytes();
+        String info = "";
+
+        for (int i = 0; i < bytes.length; i++) {
+            if (bytes[i] < 0) {
+                bytes[i] = 32;
+            }
+            info = info + new String(new byte[]{bytes[i]});
+        }
+
+        /**
+         * 鍘婚櫎涓枃
+         */
+        Pattern p = Pattern.compile("[\u4e00-\u9fa5]");
+        Matcher m = p.matcher(info);
+        List<String> inputs = new ArrayList<>();
+
+        if (m.find()) {
+            for (int i = 0; i < info.length(); i++) {
+                String ever = info.substring(i, i + 1);
+                Matcher m1 = p.matcher(ever);
+                if (m1.find()) {
+                    ever = "";
+                }
+                inputs.add(ever);
+            }
+
+            String inputNew = "";
+            for (int i = 0; i < inputs.size(); i++) {
+                inputNew = inputNew + inputs.get(i);
+            }
+            return inputNew.trim();
+
+        }
+        return info.trim();
+    }
+
+    /**
+     * 楠岃瘉閭
+     */
+    public static boolean checkEmail(String email) {
+        boolean flag;
+        try {
+            String check = "^([a-z0-9A-Z]+[-|_|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";
+            Pattern regex = Pattern.compile(check);
+            Matcher matcher = regex.matcher(email);
+            flag = matcher.matches();
+        } catch (Exception e) {
+            flag = false;
+        }
+        return flag;
+    }
+
+    /**
+     * 鑾峰緱姹夎鎷奸煶棣栧瓧姣�
+     */
+    public static String getAlpha(String str) {
+        if (str == null) {
+            return "#";
+        }
+
+        if (str.trim().length() == 0) {
+            return "#";
+        }
+
+        char c = str.trim().substring(0, 1).charAt(0);
+        // 姝e垯琛ㄨ揪寮忥紝鍒ゆ柇棣栧瓧姣嶆槸鍚︽槸鑻辨枃瀛楁瘝
+        Pattern pattern = Pattern.compile("^[A-Za-z]+$");
+        if (pattern.matcher(c + "").matches()) {
+            return (c + "").toUpperCase();
+        } else {
+            return "#";
+        }
+    }
+
+    /**
+     * 鏍¢獙URL
+     */
+    public static boolean checkUrl(String url) {
+        if (TextUtils.isEmpty(url)) return false;
+        boolean flag;
+        try {
+            String check = "^((https|http|ftp|rtsp|mms|axd):\\/\\/)[^\\s]+";
+            Pattern regex = Pattern.compile(check, Pattern.CASE_INSENSITIVE);
+            Matcher matcher = regex.matcher(url.replaceAll(" ", ""));
+            flag = matcher.matches();
+        } catch (Exception e) {
+            flag = false;
+        }
+
+        return flag;
+    }
+
+    /**
+     * 鏍¢獙鍥剧墖URL
+     */
+    public static boolean checkImageUrl(String url) {
+        if (TextUtils.isEmpty(url)) return false;
+        boolean flag;
+        try {
+            String check = "^((https|http):\\/\\/)[^\\s]+.(png|jpg|gif|webp)";
+            Pattern regex = Pattern.compile(check, Pattern.CASE_INSENSITIVE);
+            Matcher matcher = regex.matcher(url);
+            flag = matcher.matches();
+        } catch (Exception e) {
+            flag = false;
+        }
+
+        return flag;
+    }
+
+    /**
+     * 鏍¢獙姝f暣鏁�
+     */
+    public static boolean checkInt(String intContent) {
+        if (TextUtils.isEmpty(intContent)) return false;
+        boolean flag;
+        try {
+            String check = "^[1-9]\\d*$";
+            Pattern regex = Pattern.compile(check, Pattern.CASE_INSENSITIVE);
+            Matcher matcher = regex.matcher(intContent);
+            flag = matcher.matches();
+        } catch (Exception e) {
+            flag = false;
+        }
+
+        return flag;
+    }
+
+    public static boolean checkColor(String color) {
+        if (TextUtils.isEmpty(color))
+            return false;
+        boolean flag;
+        try {
+            String check = "^#([0-9a-fA-F]{6}|[0-9a-fA-F]{8})$";
+            Pattern regex = Pattern.compile(check, Pattern.CASE_INSENSITIVE);
+            Matcher matcher = regex.matcher(color);
+            flag = matcher.matches();
+        } catch (Exception e) {
+            flag = false;
+        }
+        return flag;
+    }
+}
\ No newline at end of file
diff --git a/third-zxing/src/main/java/com/zxing/utils/ZXingBitmapUtils.java b/third-zxing/src/main/java/com/zxing/utils/ZXingBitmapUtils.java
new file mode 100644
index 0000000..85d2e29
--- /dev/null
+++ b/third-zxing/src/main/java/com/zxing/utils/ZXingBitmapUtils.java
@@ -0,0 +1,333 @@
+package com.zxing.utils;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.PixelFormat;
+import android.graphics.drawable.Drawable;
+import android.media.ExifInterface;
+import android.net.Uri;
+import android.provider.MediaStore;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * Bitmap鎿嶄綔甯哥敤宸ュ叿绫�
+ */
+public class ZXingBitmapUtils {
+
+    private final static String TAG = ZXingBitmapUtils.class.getCanonicalName();
+    public final static String JPG_SUFFIX = ".jpg";
+    private final static String TIME_FORMAT = "yyyyMMddHHmmss";
+
+    /**
+     * 鏄剧ず鍥剧墖鍒扮浉鍐�
+     *
+     * @param context
+     * @param photoFile 瑕佷繚瀛樼殑鍥剧墖鏂囦欢
+     */
+    public static void displayToGallery(Context context, File photoFile) {
+        if (photoFile == null || !photoFile.exists()) {
+            return;
+        }
+        String photoPath = photoFile.getAbsolutePath();
+        String photoName = photoFile.getName();
+        // 鍏舵鎶婃枃浠舵彃鍏ュ埌绯荤粺鍥惧簱
+        try {
+            ContentResolver contentResolver = context.getContentResolver();
+            MediaStore.Images.Media.insertImage(contentResolver, photoPath, photoName, null);
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        }
+        // 鏈�鍚庨�氱煡鍥惧簱鏇存柊
+        context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + photoPath)));
+    }
+
+    /**
+     * 灏咮itmap淇濆瓨鍒版寚瀹氱洰褰曚笅
+     *
+     * @param bitmap
+     * @param folder
+     * @return 淇濆瓨鎴愬姛锛岃繑鍥炲叾瀵瑰簲鐨凢ile锛屼繚瀛樺け璐ュ垯杩斿洖null
+     */
+    public static File saveToFile(Bitmap bitmap, File folder) {
+        String fileName = new SimpleDateFormat(TIME_FORMAT).format(new Date());//鐩存帴浠ュ綋鍓嶆椂闂存埑浣滀负鏂囦欢鍚�
+        return saveToFile(bitmap, folder, fileName);
+    }
+
+    /**
+     * 灏咮itmap淇濆瓨鍒版寚瀹氱洰褰曚笅锛屽苟涓旀寚瀹氬ソ鏂囦欢鍚�
+     *
+     * @param bitmap
+     * @param folder
+     * @param fileName 鎸囧畾鐨勬枃浠跺悕鍖呭惈鍚庣紑
+     * @return 淇濆瓨鎴愬姛锛岃繑鍥炲叾瀵瑰簲鐨凢ile锛屼繚瀛樺け璐ュ垯杩斿洖null
+     */
+    public static File saveToFile(Bitmap bitmap, File folder, String fileName) {
+        if (bitmap != null) {
+            if (!folder.exists()) {
+                folder.mkdir();
+            }
+            File file = new File(folder, fileName + JPG_SUFFIX);
+            if (file.exists()) {
+                file.delete();
+            }
+            try {
+                file.createNewFile();
+                BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
+                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
+                bos.flush();
+                bos.close();
+                return file;
+            } catch (IOException e) {
+                e.printStackTrace();
+                return null;
+            }
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * 鑾峰彇鍥剧墖鐨勬棆杞搴�
+     *
+     * @param path 鍥剧墖缁濆璺緞
+     * @return 鍥剧墖鐨勬棆杞搴�
+     */
+    public static int getBitmapDegree(String path) {
+        int degree = 0;
+        try {
+            // 浠庢寚瀹氳矾寰勪笅璇诲彇鍥剧墖锛屽苟鑾峰彇鍏禘XIF淇℃伅
+            ExifInterface exifInterface = new ExifInterface(path);
+            // 鑾峰彇鍥剧墖鐨勬棆杞俊鎭�
+            int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
+            switch (orientation) {
+                case ExifInterface.ORIENTATION_ROTATE_90:
+                    degree = 90;
+                    break;
+                case ExifInterface.ORIENTATION_ROTATE_180:
+                    degree = 180;
+                    break;
+                case ExifInterface.ORIENTATION_ROTATE_270:
+                    degree = 270;
+                    break;
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return degree;
+    }
+
+    /**
+     * 灏嗗浘鐗囨寜鐓ф寚瀹氱殑瑙掑害杩涜鏃嬭浆
+     *
+     * @param bitmap 闇�瑕佹棆杞殑鍥剧墖
+     * @param degree 鎸囧畾鐨勬棆杞搴�
+     * @return 鏃嬭浆鍚庣殑鍥剧墖
+     */
+    public static Bitmap rotateBitmapByDegree(Bitmap bitmap, int degree) {
+        // 鏍规嵁鏃嬭浆瑙掑害锛岀敓鎴愭棆杞煩闃�
+        Matrix matrix = new Matrix();
+        matrix.postRotate(degree);
+        // 灏嗗師濮嬪浘鐗囨寜鐓ф棆杞煩闃佃繘琛屾棆杞紝骞跺緱鍒版柊鐨勫浘鐗�
+        Bitmap newBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
+        if (bitmap != null && !bitmap.isRecycled()) {
+            bitmap.recycle();
+        }
+        return newBitmap;
+    }
+
+    /**
+     * 鍘嬬缉Bitmap鐨勫ぇ灏�
+     *
+     * @param imageFile     鍥剧墖鏂囦欢
+     * @param requestWidth  鍘嬬缉鍒版兂瑕佺殑瀹藉害
+     * @param requestHeight 鍘嬬缉鍒版兂瑕佺殑楂樺害
+     * @return
+     */
+    public static Bitmap decodeBitmapFromFile(File imageFile, int requestWidth, int requestHeight) {
+        if (imageFile != null) {
+            return decodeBitmapFromFile(imageFile.getAbsolutePath(), requestWidth, requestHeight);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * 鍘嬬缉Bitmap鐨勫ぇ灏�
+     *
+     * @param imagePath     鍥剧墖鏂囦欢璺緞
+     * @param requestWidth  鍘嬬缉鍒版兂瑕佺殑瀹藉害
+     * @param requestHeight 鍘嬬缉鍒版兂瑕佺殑楂樺害
+     * @return
+     */
+    public static Bitmap decodeBitmapFromFile(String imagePath, int requestWidth, int requestHeight) {
+        if (!TextUtils.isEmpty(imagePath)) {
+            Log.i(TAG, "requestWidth: " + requestWidth);
+            Log.i(TAG, "requestHeight: " + requestHeight);
+            if (requestWidth <= 0 || requestHeight <= 0) {
+                Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
+                return bitmap;
+            }
+            BitmapFactory.Options options = new BitmapFactory.Options();
+            options.inJustDecodeBounds = true;//涓嶅姞杞藉浘鐗囧埌鍐呭瓨锛屼粎鑾峰緱鍥剧墖瀹介珮
+            BitmapFactory.decodeFile(imagePath, options);
+            Log.i(TAG, "original height: " + options.outHeight);
+            Log.i(TAG, "original width: " + options.outWidth);
+            if (options.outHeight == -1 || options.outWidth == -1) {
+                try {
+                    ExifInterface exifInterface = new ExifInterface(imagePath);
+                    int height = exifInterface.getAttributeInt(ExifInterface.TAG_IMAGE_LENGTH, ExifInterface.ORIENTATION_NORMAL);//鑾峰彇鍥剧墖鐨勯珮搴�
+                    int width = exifInterface.getAttributeInt(ExifInterface.TAG_IMAGE_WIDTH, ExifInterface.ORIENTATION_NORMAL);//鑾峰彇鍥剧墖鐨勫搴�
+                    Log.i(TAG, "exif height: " + height);
+                    Log.i(TAG, "exif width: " + width);
+                    options.outWidth = width;
+                    options.outHeight = height;
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+            options.inSampleSize = calculateInSampleSize(options, requestWidth, requestHeight); //璁$畻鑾峰彇鏂扮殑閲囨牱鐜�
+            Log.i(TAG, "inSampleSize: " + options.inSampleSize);
+            options.inJustDecodeBounds = false;
+            return BitmapFactory.decodeFile(imagePath, options);
+
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Decode and sample down a bitmap from resources to the requested width and height.
+     *
+     * @param res       The resources object containing the image data
+     * @param resId     The resource id of the image data
+     * @param reqWidth  The requested width of the resulting bitmap
+     * @param reqHeight The requested height of the resulting bitmap
+     * @return A bitmap sampled down from the original with the same aspect ratio and dimensions
+     * that are equal to or greater than the requested width and height
+     */
+    public static Bitmap decodeBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) {
+
+        // BEGIN_INCLUDE (read_bitmap_dimensions)
+        // First decode with inJustDecodeBounds=true to check dimensions
+        final BitmapFactory.Options options = new BitmapFactory.Options();
+        options.inJustDecodeBounds = true;
+        BitmapFactory.decodeResource(res, resId, options);
+
+        // Calculate inSampleSize
+        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
+        // END_INCLUDE (read_bitmap_dimensions)
+
+        // Decode bitmap with inSampleSize set
+        options.inJustDecodeBounds = false;
+        return BitmapFactory.decodeResource(res, resId, options);
+    }
+
+    /**
+     * Decode and sample down a bitmap from a file input stream to the requested width and height.
+     *
+     * @param fileDescriptor The file descriptor to read from
+     * @param reqWidth       The requested width of the resulting bitmap
+     * @param reqHeight      The requested height of the resulting bitmap
+     * @return A bitmap sampled down from the original with the same aspect ratio and dimensions
+     * that are equal to or greater than the requested width and height
+     */
+    public static Bitmap decodeBitmapFromDescriptor(FileDescriptor fileDescriptor, int reqWidth, int reqHeight) {
+
+        // First decode with inJustDecodeBounds=true to check dimensions
+        final BitmapFactory.Options options = new BitmapFactory.Options();
+        options.inJustDecodeBounds = true;
+        BitmapFactory.decodeFileDescriptor(fileDescriptor, null, options);
+
+        // Calculate inSampleSize
+        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
+
+        // Decode bitmap with inSampleSize set
+        options.inJustDecodeBounds = false;
+
+        return BitmapFactory.decodeFileDescriptor(fileDescriptor, null, options);
+    }
+
+    /**
+     * Google瀹樻柟浠g爜锛岃绠楀悎閫傜殑閲囨牱鐜�
+     * Calculate an inSampleSize for use in a {@link BitmapFactory.Options} object when decoding
+     * bitmaps using the decode* methods from {@link BitmapFactory}. This implementation calculates
+     * the closest inSampleSize that is a power of 2 and will result in the final decoded bitmap
+     * having a width and height equal to or larger than the requested width and height.
+     *
+     * @param options   An options object with out* params already populated (run through a decode*
+     *                  method with inJustDecodeBounds==true
+     * @param reqWidth  The requested width of the resulting bitmap
+     * @param reqHeight The requested height of the resulting bitmap
+     * @return The value to be used for inSampleSize
+     */
+    public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
+        // BEGIN_INCLUDE (calculate_sample_size)
+        // Raw height and width of image
+        final int height = options.outHeight;
+        final int width = options.outWidth;
+        int inSampleSize = 1;
+
+        if (height > reqHeight || width > reqWidth) {
+
+            final int halfHeight = height / 2;
+            final int halfWidth = width / 2;
+
+            // Calculate the largest inSampleSize value that is a power of 2 and keeps both
+            // height and width larger than the requested height and width.
+            while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) {
+                inSampleSize *= 2;
+            }
+
+            // This offers some additional logic in case the image has a strange
+            // aspect ratio. For example, a panorama may have a much larger
+            // width than height. In these cases the total pixels might still
+            // end up being too large to fit comfortably in memory, so we should
+            // be more aggressive with sample down the image (=larger inSampleSize).
+
+            long totalPixels = width * height / inSampleSize;
+
+            // Anything more than 2x the requested pixels we'll sample down further
+            final long totalReqPixelsCap = reqWidth * reqHeight * 2;
+
+            while (totalPixels > totalReqPixelsCap) {
+                inSampleSize *= 2;
+                totalPixels /= 2;
+            }
+        }
+        return inSampleSize;
+        // END_INCLUDE (calculate_sample_size)
+    }
+
+    /**
+     * drawable杞琤itmap
+     */
+    public static Bitmap drawableToBitmap(Drawable drawable) {
+        int w = drawable.getIntrinsicWidth();
+        int h = drawable.getIntrinsicHeight();
+        Bitmap.Config config =
+                drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
+                        : Bitmap.Config.RGB_565;
+        Bitmap bitmap = Bitmap.createBitmap(w, h, config);
+        //娉ㄦ剰锛屼笅闈笁琛屼唬鐮佽鐢ㄥ埌锛屽惁鍦ㄥ湪View鎴栬�卻urfaceview閲岀殑canvas.drawBitmap浼氱湅涓嶅埌鍥�
+        Canvas canvas = new Canvas(bitmap);
+        drawable.setBounds(0, 0, w, h);
+        drawable.draw(canvas);
+        return bitmap;
+    }
+}
diff --git a/third-zxing/src/main/res/drawable-xxhdpi/ic_shadow.png b/third-zxing/src/main/res/drawable-xxhdpi/ic_shadow.png
new file mode 100644
index 0000000..6be3091
--- /dev/null
+++ b/third-zxing/src/main/res/drawable-xxhdpi/ic_shadow.png
Binary files differ
diff --git a/third-zxing/src/main/res/drawable-xxhdpi/scan_capture.9.png b/third-zxing/src/main/res/drawable-xxhdpi/scan_capture.9.png
new file mode 100644
index 0000000..e03b3fc
--- /dev/null
+++ b/third-zxing/src/main/res/drawable-xxhdpi/scan_capture.9.png
Binary files differ
diff --git a/third-zxing/src/main/res/drawable-xxhdpi/scan_line.png b/third-zxing/src/main/res/drawable-xxhdpi/scan_line.png
new file mode 100644
index 0000000..23bebf8
--- /dev/null
+++ b/third-zxing/src/main/res/drawable-xxhdpi/scan_line.png
Binary files differ
diff --git a/third-zxing/src/main/res/drawable/back.png b/third-zxing/src/main/res/drawable/back.png
new file mode 100644
index 0000000..64507b9
--- /dev/null
+++ b/third-zxing/src/main/res/drawable/back.png
Binary files differ
diff --git a/third-zxing/src/main/res/drawable/fast_scan_light_close.png b/third-zxing/src/main/res/drawable/fast_scan_light_close.png
new file mode 100644
index 0000000..56f42cf
--- /dev/null
+++ b/third-zxing/src/main/res/drawable/fast_scan_light_close.png
Binary files differ
diff --git a/third-zxing/src/main/res/drawable/fast_scan_light_open.png b/third-zxing/src/main/res/drawable/fast_scan_light_open.png
new file mode 100644
index 0000000..454e02f
--- /dev/null
+++ b/third-zxing/src/main/res/drawable/fast_scan_light_open.png
Binary files differ
diff --git a/third-zxing/src/main/res/drawable/transparent_divider.xml b/third-zxing/src/main/res/drawable/transparent_divider.xml
new file mode 100644
index 0000000..a71236a
--- /dev/null
+++ b/third-zxing/src/main/res/drawable/transparent_divider.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <size android:height="13dp"/>
+    <solid android:color="@color/transparent"/>
+</shape>
\ No newline at end of file
diff --git a/third-zxing/src/main/res/layout/activity_capture.xml b/third-zxing/src/main/res/layout/activity_capture.xml
new file mode 100644
index 0000000..417171b
--- /dev/null
+++ b/third-zxing/src/main/res/layout/activity_capture.xml
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/capture_container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="#636363">
+
+
+
+    <RelativeLayout
+        android:id="@+id/top_bar_view"
+        android:layout_width="match_parent"
+        android:layout_height="52dp"
+        android:background="#245EC3"
+        android:orientation="horizontal">
+
+        <!--1.杩斿洖鎸夐挳 澧炲ぇ鐐瑰嚮鍖哄煙-->
+        <LinearLayout
+            android:id="@+id/top_back_btn"
+            android:layout_width="56dp"
+            android:layout_height="match_parent"
+            android:gravity="center_vertical"
+            android:orientation="horizontal"
+            >
+
+            <ImageView
+                android:layout_width="24dp"
+                android:layout_height="24dp"
+                android:layout_gravity="center"
+                android:layout_marginLeft="16dp"
+                android:scaleType="centerInside"
+                android:src="@drawable/back"
+                />
+        </LinearLayout>
+
+        <!--2.鏍囬鏂囨湰-->
+        <TextView
+            android:id="@+id/top_title_tv"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerInParent="true"
+            android:layout_marginLeft="60dp"
+            android:layout_marginRight="60dp"
+            android:fontFamily="sans-serif-medium"
+            android:gravity="center"
+            android:maxLines="1"
+            android:text="蹇�熸壂鐮�"
+            android:textColor="#FFFFFFFF"
+            android:textSize="18sp" />
+
+        <!--3.鏇村鎸夐挳 榛樿闅愯棌-->
+        <LinearLayout
+            android:id="@+id/top_more_btn"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_alignParentEnd="true"
+            android:gravity="center_vertical"
+            android:orientation="horizontal">
+
+            <ImageView
+                android:id="@+id/top_more_iv"
+                android:layout_width="28dp"
+                android:layout_height="28dp"
+                android:layout_marginStart="20dp"
+                android:layout_marginEnd="20dp"
+                android:adjustViewBounds="true"
+                android:scaleType="centerInside"
+                android:visibility="gone" />
+
+        </LinearLayout>
+
+    </RelativeLayout>
+
+    <SurfaceView
+        android:id="@+id/capture_preview"
+        android:layout_width="367dp"
+        android:layout_height="367dp"
+        android:layout_centerInParent="true"
+
+        />
+
+
+    <RelativeLayout
+        android:id="@+id/capture_crop_view"
+        android:layout_width="367dp"
+        android:layout_height="367dp"
+        android:layout_centerInParent="true"
+        android:background="@drawable/scan_capture">
+
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_height="367dp"
+            android:layout_marginTop="182dp">
+
+            <ImageView
+                android:id="@+id/capture_scan_line"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_alignParentTop="true"
+                android:layout_marginTop="5dp"
+                android:layout_marginBottom="5dp"
+                android:src="@drawable/scan_line" />
+        </RelativeLayout>
+
+    </RelativeLayout>
+
+    <ImageView
+        android:id="@+id/light_iv"
+        android:layout_width="127dp"
+        android:layout_height="127dp"
+        android:layout_alignParentBottom="true"
+        android:layout_centerInParent="true"
+        android:layout_marginBottom="13dp"
+        android:background="@drawable/fast_scan_light_close" />
+
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/third-zxing/src/main/res/layout/toolbar.xml b/third-zxing/src/main/res/layout/toolbar.xml
new file mode 100644
index 0000000..75014a6
--- /dev/null
+++ b/third-zxing/src/main/res/layout/toolbar.xml
@@ -0,0 +1,34 @@
+<?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="50dp"
+    >
+
+        <RelativeLayout
+            android:id="@+id/rl_back"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_marginStart="32dp">
+
+            <TextView
+                android:id="@+id/tv_text_cancel"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_centerVertical="true"
+                android:text="@string/scan_cancel"
+                android:textColor="#000000"
+                android:textSize="36sp" />
+        </RelativeLayout>
+
+        <TextView
+            android:id="@+id/tv_text_scan"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerInParent="true"
+            android:text="@string/scan_title"
+            android:textColor="#000000"
+            android:textSize="36sp" />
+
+
+</RelativeLayout>
diff --git a/third-zxing/src/main/res/raw/beep.ogg b/third-zxing/src/main/res/raw/beep.ogg
new file mode 100644
index 0000000..dc6e719
--- /dev/null
+++ b/third-zxing/src/main/res/raw/beep.ogg
Binary files differ
diff --git a/third-zxing/src/main/res/values/colors_ui.xml b/third-zxing/src/main/res/values/colors_ui.xml
new file mode 100644
index 0000000..966918a
--- /dev/null
+++ b/third-zxing/src/main/res/values/colors_ui.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <!--鍩虹鑹�-->
+    <color name="c0">#F18D00</color>   <!--鐢ㄤ簬鎸夐挳銆佽緝澶ч潰绉壊鍧楄緟鑹� 鍘烠10-->
+    <color name="c1">#F18D00</color>   <!--鐢ㄤ簬寮鸿皟鎬ф枃瀛�/鍥剧墖绛夐潪澶ч潰绉壊鍧楄壊鍊�-->
+    <color name="c2">#2C2C2C</color>    <!--涓绘爣棰�/涓绘枃瀛楄壊-->
+    <!--涓绘爣棰�/涓绘枃瀛楄壊-->
+    <color name="c3">#C8D1E6</color>    <!--Toolbar鏂囧瓧/鏅�氭寜閽瓸G鑹�-->
+    <!--鐐圭紑鑹�-->
+    <color name="c5">#888888</color>   <!--鏅�氭枃妗�/寮曞/娆¤鏂囧瓧-->
+    <color name="c6">#CCCCCC</color>   <!--缃伆/杈撳叆鎻愮ず-->
+
+    <!--搴曡壊/鍒嗗壊-->
+    <color name="c7">#F7F7F7</color>   <!--瀹㈡埛绔簳鑹�/鍗$墖鎻忚竟-->
+    <color name="c8">#F2F2F2</color>   <!--鍒嗗壊绾垮簳鑹�-->
+    <color name="c10">#FFFFFF</color>   <!--鍙嶇櫧-->
+
+    <!--甯﹂�忔槑搴︾殑棰滆壊-->
+    <!--鍏ㄥ眬閬僵-->
+    <color name="c14">#7FF18D00</color> <!--寮鸿皟閽畃ressed-->
+    <color name="c15">#7FF18D00</color> <!--寮鸿皟閽甦isabled-->
+    <!--鏅�氶挳pressed-->
+    <!--鏅�氶挳disabled-->
+
+    <!--鎴愬姛澶辫触鎻愮ず-->
+    <color name="c12">#EF6545</color>   <!--鍒犻櫎銆佽绀鸿壊锛涙坊鍔犺澶囪秴鏃剁孩鐏枃妗�-->
+    <color name="color_background">#ffffff</color>
+    <color name="transparent">#00000000</color>
+
+    <!--鏂癠I瑙勮寖棰滆壊鍊肩粺涓�鍛藉悕-->
+    <color name="color5">#424243</color>
+    <color name="color9">#cccccc</color>
+</resources>
diff --git a/third-zxing/src/main/res/values/ids.xml b/third-zxing/src/main/res/values/ids.xml
new file mode 100644
index 0000000..c16e2a0
--- /dev/null
+++ b/third-zxing/src/main/res/values/ids.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <item name="decode" type="id"/>
+    <item name="decode_failed" type="id"/>
+    <item name="decode_succeeded" type="id"/>
+    <item name="quit" type="id"/>
+    <item name="restart_preview" type="id"/>
+    <item name="return_scan_result" type="id"/>
+</resources>
\ No newline at end of file
diff --git a/third-zxing/src/main/res/values/strings.xml b/third-zxing/src/main/res/values/strings.xml
new file mode 100644
index 0000000..64eefbe
--- /dev/null
+++ b/third-zxing/src/main/res/values/strings.xml
@@ -0,0 +1,13 @@
+<resources>
+    <string name="app_name">third_zxing2</string>
+    <string name="scan_title">浜岀淮鐮佹壂鎻�</string>
+
+    <!--鎵爜-->
+    <string name="zxing_scan_tips">灏嗕簩缁寸爜鏀惧叆妗嗗唴锛屽嵆鍙嚜鍔ㄦ壂鎻�</string>
+    <string name="capture_no_camera">娌℃湁璁块棶鐩告満鐨勬潈闄愶紝璇锋墦寮�璁块棶鏉冮檺鍐嶈瘯</string>
+    <string name="capture_no_result">娌℃湁鎵弿鍑虹粨鏋�</string>
+    <string name="capture_no_network">褰撳墠缃戠粶涓嶅彲鐢�,璇锋鏌ョ綉缁滃悗鍐嶈瘯</string>
+    <string name="capture_no_result2">娌℃湁鎵弿鍑虹粨鏋滐紝鍙兘涓嶆槸鏈夋晥鐨勪簩缁寸爜</string>
+    <string name="scan_cancel">鍙栨秷</string>
+
+</resources>
diff --git a/third-zxing/src/main/res/values/styles.xml b/third-zxing/src/main/res/values/styles.xml
new file mode 100644
index 0000000..956c150
--- /dev/null
+++ b/third-zxing/src/main/res/values/styles.xml
@@ -0,0 +1,24 @@
+<resources>
+
+    <style name="AppTheme.Base" parent="Theme.AppCompat.Light.NoActionBar">
+        <item name="android:windowBackground">@color/color_background</item>
+        <item name="android:listViewStyle">@style/List</item>
+        <item name="android:windowAnimationStyle">@null</item>
+        <item name="android:textViewStyle">@style/TextView</item>
+        <item name="android:disabledAlpha">1</item>
+        <item name="android:listDivider">@drawable/transparent_divider</item>
+    </style>
+
+    <style name="List" parent="@android:style/Widget.ListView">
+        <item name="android:listSelector">@color/transparent</item>
+        <item name="android:cacheColorHint">@color/transparent</item>
+        <item name="android:divider">@null</item>
+    </style>
+
+
+    <style name="TextView" parent="@android:style/Widget.TextView">
+        <item name="android:textColorHint">@color/color9</item>
+        <item name="android:textColor">@color/color5</item>
+        <item name="android:textSize">14sp</item>
+    </style>
+</resources>

--
Gitblit v1.8.0