RaoMeng 9 éve
szülő
commit
30d2fa61ca
51 módosított fájl, 3272 hozzáadás és 10 törlés
  1. 2 1
      WeiChat/build.gradle
  2. 15 0
      WeiChat/src/main/AndroidManifest.xml
  3. 100 0
      WeiChat/src/main/java/com/xzjmyk/pm/activity/CaptureResultActivity.java
  4. 2 0
      WeiChat/src/main/java/com/xzjmyk/pm/activity/MyApplication.java
  5. 12 0
      WeiChat/src/main/java/com/xzjmyk/pm/activity/ui/erp/util/CommonUtil.java
  6. 44 2
      WeiChat/src/main/java/com/xzjmyk/pm/activity/ui/me/MeFragment.java
  7. BIN
      WeiChat/src/main/res/drawable-hdpi/ic_uu_scan_code.png
  8. BIN
      WeiChat/src/main/res/drawable-xhdpi/ic_scan_code_icon.png
  9. 11 0
      WeiChat/src/main/res/layout/activity_capture_result.xml
  10. 9 6
      WeiChat/src/main/res/layout/fragment_me.xml
  11. 11 0
      WeiChat/src/main/res/menu/menu_me_scan.xml
  12. 3 0
      lib-zxing/.gitignore
  13. 41 0
      lib-zxing/build.gradle
  14. BIN
      lib-zxing/libs/zxing.jar
  15. 17 0
      lib-zxing/proguard-rules.pro
  16. 26 0
      lib-zxing/src/androidTest/java/com/uuzuche/lib_zxing/ExampleInstrumentedTest.java
  17. 28 0
      lib-zxing/src/main/AndroidManifest.xml
  18. 36 0
      lib-zxing/src/main/java/com/uuzuche/lib_zxing/DisplayUtil.java
  19. 30 0
      lib-zxing/src/main/java/com/uuzuche/lib_zxing/ZApplication.java
  20. 53 0
      lib-zxing/src/main/java/com/uuzuche/lib_zxing/activity/CaptureActivity.java
  21. 261 0
      lib-zxing/src/main/java/com/uuzuche/lib_zxing/activity/CaptureFragment.java
  22. 218 0
      lib-zxing/src/main/java/com/uuzuche/lib_zxing/activity/CodeUtils.java
  23. 26 0
      lib-zxing/src/main/java/com/uuzuche/lib_zxing/activity/ZXingLibrary.java
  24. 48 0
      lib-zxing/src/main/java/com/uuzuche/lib_zxing/camera/AutoFocusCallback.java
  25. 41 0
      lib-zxing/src/main/java/com/uuzuche/lib_zxing/camera/BitmapLuminanceSource.java
  26. 278 0
      lib-zxing/src/main/java/com/uuzuche/lib_zxing/camera/CameraConfigurationManager.java
  27. 348 0
      lib-zxing/src/main/java/com/uuzuche/lib_zxing/camera/CameraManager.java
  28. 151 0
      lib-zxing/src/main/java/com/uuzuche/lib_zxing/camera/FlashlightManager.java
  29. 133 0
      lib-zxing/src/main/java/com/uuzuche/lib_zxing/camera/PlanarYUVLuminanceSource.java
  30. 59 0
      lib-zxing/src/main/java/com/uuzuche/lib_zxing/camera/PreviewCallback.java
  31. 133 0
      lib-zxing/src/main/java/com/uuzuche/lib_zxing/decoding/CaptureActivityHandler.java
  32. 107 0
      lib-zxing/src/main/java/com/uuzuche/lib_zxing/decoding/DecodeFormatManager.java
  33. 108 0
      lib-zxing/src/main/java/com/uuzuche/lib_zxing/decoding/DecodeHandler.java
  34. 86 0
      lib-zxing/src/main/java/com/uuzuche/lib_zxing/decoding/DecodeThread.java
  35. 46 0
      lib-zxing/src/main/java/com/uuzuche/lib_zxing/decoding/FinishListener.java
  36. 71 0
      lib-zxing/src/main/java/com/uuzuche/lib_zxing/decoding/InactivityTimer.java
  37. 190 0
      lib-zxing/src/main/java/com/uuzuche/lib_zxing/decoding/Intents.java
  38. 40 0
      lib-zxing/src/main/java/com/uuzuche/lib_zxing/encoding/EncodingHandler.java
  39. 34 0
      lib-zxing/src/main/java/com/uuzuche/lib_zxing/view/ViewfinderResultPointCallback.java
  40. 262 0
      lib-zxing/src/main/java/com/uuzuche/lib_zxing/view/ViewfinderView.java
  41. BIN
      lib-zxing/src/main/res/drawable/scan_light.png
  42. 11 0
      lib-zxing/src/main/res/layout/camera.xml
  43. 61 0
      lib-zxing/src/main/res/layout/fragment_capture.xml
  44. BIN
      lib-zxing/src/main/res/raw/beep.ogg
  45. 15 0
      lib-zxing/src/main/res/values/attrs.xml
  46. 33 0
      lib-zxing/src/main/res/values/colors.xml
  47. 31 0
      lib-zxing/src/main/res/values/ids.xml
  48. 6 0
      lib-zxing/src/main/res/values/strings.xml
  49. 17 0
      lib-zxing/src/main/res/values/styles.xml
  50. 17 0
      lib-zxing/src/test/java/com/uuzuche/lib_zxing/ExampleUnitTest.java
  51. 1 1
      settings.gradle

+ 2 - 1
WeiChat/build.gradle

@@ -4,7 +4,7 @@ apply plugin: 'com.getkeepsafe.dexcount'
 android {
     signingConfigs {
         config {
-            storeFile file('D:/config/applicationsignname[20150409]')
+            storeFile file('E:/CompanyProject/applicationsignname[20150409]')
             storePassword '13237658359'
             keyAlias 'jie-20150409'
             keyPassword '13237658359'
@@ -96,4 +96,5 @@ dependencies {
     compile 'com.android.support:multidex:1.0.1'
     compile project(':library-swipemenu_lv')
     compile project(':library-viewpager-indicator')
+    compile project(':lib-zxing')
 }

+ 15 - 0
WeiChat/src/main/AndroidManifest.xml

@@ -63,6 +63,20 @@
     <uses-permission android:name="android.permission.GET_TASKS" />
     <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
 
+
+    <uses-permission android:name="android.permission.CAMERA"/>
+    <uses-permission android:name="android.permission.INTERNET"/>
+    <uses-permission android:name="android.permission.VIBRATE"/>
+    <uses-permission android:name="android.permission.FLASHLIGHT"/>
+    <uses-permission android:name="android.permission.READ_CONTACTS"/>
+    <uses-permission android:name="com.android.browser.permission.READ_HISTORY_BOOKMARKS"/>
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
+    <uses-permission android:name="android.permission.VIBRATE" /> <!-- 震动权限 -->
+    <uses-permission android:name="android.permission.CAMERA" />
+    <uses-feature android:name="android.hardware.camera" /> <!-- 使用照相机权限 -->
+    <uses-feature android:name="android.hardware.camera.autofocus" /> <!-- 自动聚焦权限 -->
     <!-- 全局样式不要随意改动  @style/AppTheme -->
     <application
         android:name=".MyApplication"
@@ -196,6 +210,7 @@
         <activity
             android:name=".ui.me.BasicInfoEditActivity"
             android:windowSoftInputMode="stateHidden|stateAlwaysHidden" />
+        <activity android:name=".CaptureResultActivity"/>
         <!-- Tool Activity -->
         <activity
             android:name=".ui.tool.MultiImagePreviewActivity"

+ 100 - 0
WeiChat/src/main/java/com/xzjmyk/pm/activity/CaptureResultActivity.java

@@ -0,0 +1,100 @@
+/**
+ *
+ */
+package com.xzjmyk.pm.activity;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.webkit.WebSettings;
+import android.webkit.WebView;
+
+import com.uuzuche.lib_zxing.activity.CodeUtils;
+import com.xzjmyk.pm.activity.ui.erp.util.CommonUtil;
+import com.xzjmyk.pm.activity.view.crouton.Crouton;
+import com.xzjmyk.pm.activity.view.crouton.LifecycleCallback;
+
+
+/**
+ * @author RaoMeng
+ */
+public class CaptureResultActivity extends Activity {
+    private WebView mWebView;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_capture_result);
+        initActivity();
+        initData();
+    }
+
+    private void initActivity() {
+        mWebView = (WebView) findViewById(R.id.result_webview);
+
+        WebSettings webSettings = mWebView.getSettings();
+        //允许加载JavaScript
+        webSettings.setJavaScriptEnabled(true);
+        //网页自适应屏幕
+        webSettings.setUseWideViewPort(true);
+        webSettings.setLoadWithOverviewMode(true);
+
+        webSettings.setDomStorageEnabled(true);
+//        mWebView.setWebViewClient(new WebViewClient());
+    }
+
+    private void initData() {
+
+        Intent intent = getIntent();
+        if (null != intent) {
+            Bundle bundle = intent.getExtras();
+            if (bundle == null){
+                return;
+            }
+            if (bundle.getInt(CodeUtils.RESULT_TYPE) == CodeUtils.RESULT_SUCCESS){
+                String result = bundle.getString(CodeUtils.RESULT_STRING);
+                Log.d("scanurl",result);
+                if (CommonUtil.isWebsite(result)){
+                    mWebView.loadUrl(result);
+                    finish();
+                }else {
+                    Crouton crouton = Crouton.makeText(CaptureResultActivity.this, "您扫描的二维码不是网址", 0xffff4444, 1500);
+                    crouton.show();
+                    crouton.setLifecycleCallback(new LifecycleCallback() {
+                        @Override
+                        public void onDisplayed() {
+
+                        }
+
+                        @Override
+                        public void onRemoved() {
+                            finish();
+                        }
+                    });
+                    /*Timer timer = new Timer();
+                    TimerTask task = new TimerTask() {
+                        @Override
+                        public void run() {
+                            finish();
+                        }
+                    };
+                    timer.schedule(task,500);*/
+                }
+            }
+        }
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        if (keyCode == KeyEvent.KEYCODE_BACK){
+            if (mWebView.canGoBack()){
+                mWebView.goBack();
+                return true;
+            }
+        }
+        return super.onKeyDown(keyCode, event);
+    }
+}

+ 2 - 0
WeiChat/src/main/java/com/xzjmyk/pm/activity/MyApplication.java

@@ -23,6 +23,7 @@ import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
 import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
 import com.nostra13.universalimageloader.core.display.RoundedBitmapDisplayer;
 import com.umeng.analytics.MobclickAgent;
+import com.uuzuche.lib_zxing.activity.ZXingLibrary;
 import com.xzjmyk.pm.activity.bean.ConfigBean;
 import com.xzjmyk.pm.activity.bean.User;
 import com.xzjmyk.pm.activity.db.SQLiteHelper;
@@ -54,6 +55,7 @@ public class MyApplication extends Application {
     public void onCreate() {
         super.onCreate();
         INSTANCE = this;
+        ZXingLibrary.initDisplayOpinion(this);
 //        CrashReport.initCrashReport(getApplicationContext(), "900050585", false);
         PreferenceUtils.putBoolean(this, Constants.IS_NOTIFICATION, false);//不进行通知
         new Handler().postDelayed(new Runnable() {

+ 12 - 0
WeiChat/src/main/java/com/xzjmyk/pm/activity/ui/erp/util/CommonUtil.java

@@ -247,6 +247,18 @@ public class CommonUtil {
         return m.matches();
     }
 
+    /**
+     * 检验是否是正确的网址
+     * @param s
+     * @return
+     */
+    public static boolean isWebsite(String s){
+        String regex = "^([hH][tT]{2}[pP]://|[hH][tT]{2}[pP][sS]://)(([A-Za-z0-9-~]+).)+([A-Za-z0-9-~\\\\/])+$";
+        Pattern p = Pattern.compile(regex);
+        Matcher m = p.matcher(s);
+        return m.matches();
+    }
+
     /**
      * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
      */

+ 44 - 2
WeiChat/src/main/java/com/xzjmyk/pm/activity/ui/me/MeFragment.java

@@ -10,14 +10,21 @@ import android.os.Handler;
 import android.os.Message;
 import android.support.v4.content.LocalBroadcastManager;
 import android.util.Log;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
 import android.view.View;
 import android.widget.ImageView;
 import android.widget.RelativeLayout;
 import android.widget.TextView;
 
+import com.afollestad.materialdialogs.GravityEnum;
+import com.afollestad.materialdialogs.MaterialDialog;
 import com.lidroid.xutils.view.annotation.ViewInject;
 //import com.tencent.bugly.crashreport.CrashReport;
+import com.uuzuche.lib_zxing.activity.CaptureActivity;
 import com.xzjmyk.pm.activity.AppConstant;
+import com.xzjmyk.pm.activity.CaptureResultActivity;
 import com.xzjmyk.pm.activity.MyApplication;
 import com.xzjmyk.pm.activity.R;
 import com.xzjmyk.pm.activity.broadcast.MsgBroadcast;
@@ -43,6 +50,7 @@ import java.util.Map;
 
 public class MeFragment extends EasyFragment implements View.OnClickListener {
 
+    private static final int REQUEST_CODE = 11;
     private ImageView mAvatarImg;
     private TextView mNickNameTv;
     private TextView mPhoneNumTv;
@@ -65,6 +73,8 @@ public class MeFragment extends EasyFragment implements View.OnClickListener {
     private RelativeLayout rl_company_change;
     @ViewInject(R.id.rl_master_change)
     private RelativeLayout rl_master_change;
+    @ViewInject(R.id.app_scan_code_rl)
+    private RelativeLayout rl_scan_code;
 
     private Context ct;
     public MasterDialog mDialog;
@@ -167,6 +177,7 @@ public class MeFragment extends EasyFragment implements View.OnClickListener {
     @Override
     protected void onCreateView(Bundle savedInstanceState, boolean createView) {
         if (createView) {
+            setHasOptionsMenu(true);
             initView();
 //            CrashReport.testJavaCrash();
         }
@@ -183,6 +194,7 @@ public class MeFragment extends EasyFragment implements View.OnClickListener {
         rl_company_change.setOnClickListener(this);
         rl_master_change.setOnClickListener(this);
         rl_info.setOnClickListener(this);
+        rl_scan_code.setOnClickListener(this);
 
         mAvatarImg = (ImageView) findViewById(R.id.avatar_img);
         mNickNameTv = (TextView) findViewById(R.id.nick_name_tv);
@@ -222,7 +234,24 @@ public class MeFragment extends EasyFragment implements View.OnClickListener {
 
     }
 
-//    private void setApl() {
+    @Override
+    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+        super.onCreateOptionsMenu(menu, inflater);
+//        inflater = getActivity().getMenuInflater();
+        inflater.inflate(R.menu.menu_me_scan,menu);
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        if (item.getItemId() == R.id.me_scan){
+            Intent intent = new Intent();
+            intent.setClass(getActivity(), CaptureActivity.class);
+            startActivityForResult(intent,REQUEST_CODE);
+        }
+        return super.onOptionsItemSelected(item);
+    }
+
+    //    private void setApl() {
 //
 //        View view1=findViewById(R.id.info_rl);
 //        View view2=findViewById(R.id.my_data_rl);
@@ -285,16 +314,29 @@ public class MeFragment extends EasyFragment implements View.OnClickListener {
             case R.id.setting_rl:// 设置
                 startActivity(new Intent(getActivity(), SettingActivity.class));
                 break;
+            case R.id.app_scan_code_rl://APP二维码
+                ImageView imageView = new ImageView(getActivity());
+                imageView.setImageResource(R.drawable.ic_uu_scan_code);
+                MaterialDialog materialDialog = new MaterialDialog.Builder(getActivity())
+                        .title("UU互联最新版二维码")
+                        .customView(imageView, false)
+                        .titleGravity(GravityEnum.CENTER)
+                        .show();
         }
     }
 
     @Override
     public void onActivityResult(int requestCode, int resultCode, Intent data) {
         super.onActivityResult(requestCode, resultCode, data);
-        if (requestCode == 1 || resultCode == Activity.RESULT_OK) {// 个人资料更新了
+        if (requestCode == 1 && resultCode == Activity.RESULT_OK) {// 个人资料更新了
             AvatarHelper.getInstance().displayAvatar(MyApplication.getInstance().mLoginUser.getUserId(), mAvatarImg, true);
             mNickNameTv.setText(MyApplication.getInstance().mLoginUser.getNickName());
         }
+
+        if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK && data != null){
+            data.setClass(getActivity(), CaptureResultActivity.class);
+            startActivity(data);
+        }
     }
 
     //获取中文账套

BIN
WeiChat/src/main/res/drawable-hdpi/ic_uu_scan_code.png


BIN
WeiChat/src/main/res/drawable-xhdpi/ic_scan_code_icon.png


+ 11 - 0
WeiChat/src/main/res/layout/activity_capture_result.xml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="fill_parent"
+                android:layout_height="fill_parent">
+
+    <WebView
+        android:id="@+id/result_webview"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+
+</RelativeLayout>

+ 9 - 6
WeiChat/src/main/res/layout/fragment_me.xml

@@ -285,7 +285,7 @@
             android:background="@color/item_line" />
 
         <RelativeLayout
-            android:id="@+id/my_erp_rl"
+            android:id="@+id/app_scan_code_rl"
             style="@style/IMTbleLine_UP_Me">
 
             <TextView
@@ -293,10 +293,10 @@
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_centerVertical="true"
-                android:drawableLeft="@drawable/usa_zhanghu"
+                android:drawableLeft="@drawable/ic_scan_code_icon"
                 android:drawablePadding="10dp"
                 android:gravity="center"
-                android:text="@string/my_uas"
+                android:text="App二维码"
                 android:textColor="@color/text_main"
                 android:textSize="@dimen/text_main" />
 
@@ -307,7 +307,8 @@
                 android:layout_toRightOf="@+id/uas_text"
                 android:text="未登录"
                 android:textColor="@color/text_hine"
-                android:textSize="@dimen/text_hine" />
+                android:textSize="@dimen/text_hine"
+                android:visibility="gone"/>
 
             <ImageView
                 android:id="@+id/uas_arrow_img"
@@ -317,7 +318,8 @@
                 android:layout_centerVertical="true"
                 android:alpha="0.26"
                 android:background="@drawable/set_list_next"
-                android:contentDescription="@string/app_name" />
+                android:contentDescription="@string/app_name"
+                android:visibility="gone"/>
         </RelativeLayout>
 
         <View
@@ -328,7 +330,8 @@
         <RelativeLayout
             android:id="@+id/my_b2b_rl"
             style="@style/IMTbleLine_UP_Me"
-            android:layout_marginTop="7dp">
+            android:layout_marginTop="7dp"
+            android:visibility="gone">
 
             <TextView
                 android:id="@+id/b2b_text"

+ 11 - 0
WeiChat/src/main/res/menu/menu_me_scan.xml

@@ -0,0 +1,11 @@
+<menu 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"
+    tools:context="com.xzjmyk.pm.activity.MainActivity">
+    <item
+        android:id="@+id/me_scan"
+        android:icon="@drawable/ic_scan"
+        android:title="扫描"
+        app:showAsAction="always"
+        />
+</menu>

+ 3 - 0
lib-zxing/.gitignore

@@ -0,0 +1,3 @@
+/build
+!/build/outputs/mapping/release/*
+*.iml

+ 41 - 0
lib-zxing/build.gradle

@@ -0,0 +1,41 @@
+apply plugin: 'com.android.library'
+
+android {
+    compileSdkVersion 22
+    buildToolsVersion "22.0.1"
+
+    defaultConfig {
+        minSdkVersion 8
+        targetSdkVersion 22
+        versionCode 1
+        versionName "1.0"
+
+        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+
+    }
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+        }
+    }
+}
+
+dependencies {
+    compile fileTree(include: ['*.jar'], dir: 'libs')
+    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
+        exclude group: 'com.android.support', module: 'support-annotations'
+    })
+    compile files('libs/zxing.jar')
+    compile 'com.android.support:appcompat-v7:22+'
+    compile 'com.android.support:support-v4:22+'
+    testCompile 'junit:junit:4.12'
+}
+
+ext {
+    PUBLISH_GROUP_ID = 'cn.yipianfengye.android'
+    PUBLISH_ARTIFACT_ID = 'zxing-library'
+    PUBLISH_VERSION = '1.9'
+}
+
+apply from: 'https://raw.githubusercontent.com/blundell/release-android-library/master/android-release-aar.gradle'

BIN
lib-zxing/libs/zxing.jar


+ 17 - 0
lib-zxing/proguard-rules.pro

@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /Users/aaron/document/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 *;
+#}

+ 26 - 0
lib-zxing/src/androidTest/java/com/uuzuche/lib_zxing/ExampleInstrumentedTest.java

@@ -0,0 +1,26 @@
+package com.uuzuche.lib_zxing;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumentation test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+    @Test
+    public void useAppContext() throws Exception {
+        // Context of the app under test.
+        Context appContext = InstrumentationRegistry.getTargetContext();
+
+        assertEquals("com.uuzuche.lib_zxing.test", appContext.getPackageName());
+    }
+}

+ 28 - 0
lib-zxing/src/main/AndroidManifest.xml

@@ -0,0 +1,28 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.uuzuche.lib_zxing">
+
+    <uses-permission android:name="android.permission.CAMERA" />
+    <uses-permission android:name="android.permission.FLASHLIGHT" />
+
+    <uses-feature android:name="android.hardware.camera" />
+    <uses-feature android:name="android.hardware.camera.autofocus" />
+
+    <uses-permission android:name="android.permission.VIBRATE" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.INTERNET" />
+
+    <application
+        android:allowBackup="true"
+        >
+
+        <activity
+            android:configChanges="orientation|keyboardHidden"
+            android:name="com.uuzuche.lib_zxing.activity.CaptureActivity"
+            android:screenOrientation="portrait"
+            android:windowSoftInputMode="stateAlwaysHidden"
+            android:theme="@style/Theme.AppCompat.NoActionBar"
+            ></activity>
+    </application>
+
+</manifest>

+ 36 - 0
lib-zxing/src/main/java/com/uuzuche/lib_zxing/DisplayUtil.java

@@ -0,0 +1,36 @@
+package com.uuzuche.lib_zxing;
+
+import android.content.Context;
+
+/**
+ * Created by aaron on 16/8/3.
+ */
+public class DisplayUtil
+{
+
+    public static int screenWidthPx; //屏幕宽 px
+    public static int screenhightPx; //屏幕高 px
+    public static float density;//屏幕密度
+    public static int densityDPI;//屏幕密度
+    public static float screenWidthDip;//  dp单位
+    public static float screenHightDip;//  dp单位
+
+
+
+    /**
+     * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
+     */
+    public static int dip2px(Context context, float dpValue) {
+        final float scale = context.getResources().getDisplayMetrics().density;
+        return (int) (dpValue * scale + 0.5f);
+    }
+
+    /**
+     * 根据手机的分辨率从 px(像素) 的单位 转成为 dp
+     */
+    public static int px2dip(Context context, float pxValue) {
+        final float scale = context.getResources().getDisplayMetrics().density;
+        return (int) (pxValue / scale + 0.5f);
+    }
+
+}

+ 30 - 0
lib-zxing/src/main/java/com/uuzuche/lib_zxing/ZApplication.java

@@ -0,0 +1,30 @@
+package com.uuzuche.lib_zxing;
+
+import android.app.Application;
+import android.util.DisplayMetrics;
+
+/**
+ * Created by aaron on 16/8/9.
+ */
+
+public class ZApplication extends Application{
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        /**
+         * 初始化尺寸工具类
+         */
+        initDisplayOpinion();
+    }
+
+    private void initDisplayOpinion() {
+        DisplayMetrics dm = getResources().getDisplayMetrics();
+        DisplayUtil.density = dm.density;
+        DisplayUtil.densityDPI = dm.densityDpi;
+        DisplayUtil.screenWidthPx = dm.widthPixels;
+        DisplayUtil.screenhightPx = dm.heightPixels;
+        DisplayUtil.screenWidthDip = DisplayUtil.px2dip(getApplicationContext(), dm.widthPixels);
+        DisplayUtil.screenHightDip = DisplayUtil.px2dip(getApplicationContext(), dm.heightPixels);
+    }
+}

+ 53 - 0
lib-zxing/src/main/java/com/uuzuche/lib_zxing/activity/CaptureActivity.java

@@ -0,0 +1,53 @@
+package com.uuzuche.lib_zxing.activity;
+
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.os.Bundle;
+import android.support.v7.app.AppCompatActivity;
+
+import com.uuzuche.lib_zxing.R;
+
+/**
+ * Initial the camera
+ *
+ * 默认的二维码扫描Activity
+ */
+public class CaptureActivity extends AppCompatActivity {
+
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.camera);
+        CaptureFragment captureFragment = new CaptureFragment();
+        captureFragment.setAnalyzeCallback(analyzeCallback);
+        getSupportFragmentManager().beginTransaction().replace(R.id.fl_zxing_container, captureFragment).commit();
+    }
+
+    /**
+     * 二维码解析回调函数
+     */
+    CodeUtils.AnalyzeCallback analyzeCallback = new CodeUtils.AnalyzeCallback() {
+        @Override
+        public void onAnalyzeSuccess(Bitmap mBitmap, String result)  {
+            Intent resultIntent = new Intent();
+            Bundle bundle = new Bundle();
+            bundle.putInt(CodeUtils.RESULT_TYPE, CodeUtils.RESULT_SUCCESS);
+            bundle.putString(CodeUtils.RESULT_STRING, result);
+            resultIntent.putExtras(bundle);
+            CaptureActivity.this.setResult(RESULT_OK, resultIntent);
+            CaptureActivity.this.finish();
+        }
+
+        @Override
+        public void onAnalyzeFailed() {
+            Intent resultIntent = new Intent();
+            Bundle bundle = new Bundle();
+            bundle.putInt(CodeUtils.RESULT_TYPE, CodeUtils.RESULT_FAILED);
+            bundle.putString(CodeUtils.RESULT_STRING, "");
+            resultIntent.putExtras(bundle);
+            CaptureActivity.this.setResult(RESULT_OK, resultIntent);
+            CaptureActivity.this.finish();
+        }
+    };
+}

+ 261 - 0
lib-zxing/src/main/java/com/uuzuche/lib_zxing/activity/CaptureFragment.java

@@ -0,0 +1,261 @@
+package com.uuzuche.lib_zxing.activity;
+
+import android.content.res.AssetFileDescriptor;
+import android.graphics.Bitmap;
+import android.hardware.Camera;
+import android.media.AudioManager;
+import android.media.MediaPlayer;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Vibrator;
+import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.Result;
+import com.uuzuche.lib_zxing.R;
+import com.uuzuche.lib_zxing.camera.CameraManager;
+import com.uuzuche.lib_zxing.decoding.CaptureActivityHandler;
+import com.uuzuche.lib_zxing.decoding.InactivityTimer;
+import com.uuzuche.lib_zxing.view.ViewfinderView;
+
+import java.io.IOException;
+import java.util.Vector;
+
+/**
+ * 自定义实现的扫描Fragment
+ */
+public class CaptureFragment extends Fragment implements SurfaceHolder.Callback {
+
+    private CaptureActivityHandler handler;
+    private ViewfinderView viewfinderView;
+    private boolean hasSurface;
+    private Vector<BarcodeFormat> decodeFormats;
+    private String characterSet;
+    private InactivityTimer inactivityTimer;
+    private MediaPlayer mediaPlayer;
+    private boolean playBeep;
+    private static final float BEEP_VOLUME = 0.10f;
+    private boolean vibrate;
+    private SurfaceView surfaceView;
+    private SurfaceHolder surfaceHolder;
+    private CodeUtils.AnalyzeCallback analyzeCallback;
+    private Camera camera;
+    private TextView cancleTv;
+    @Override
+    public void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+
+        CameraManager.init(getActivity().getApplication());
+
+        hasSurface = false;
+        inactivityTimer = new InactivityTimer(this.getActivity());
+    }
+
+    @Nullable
+    @Override
+    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+
+        Bundle bundle = getArguments();
+        View view = null;
+        if (bundle != null) {
+            int layoutId = bundle.getInt(CodeUtils.LAYOUT_ID);
+            if (layoutId != -1) {
+                view = inflater.inflate(layoutId, null);
+            }
+        }
+
+        if (view == null) {
+            view = inflater.inflate(R.layout.fragment_capture, null);
+        }
+
+        viewfinderView = (ViewfinderView) view.findViewById(R.id.viewfinder_view);
+        surfaceView = (SurfaceView) view.findViewById(R.id.preview_view);
+        surfaceHolder = surfaceView.getHolder();
+
+        cancleTv = (TextView) view.findViewById(R.id.back_tv);
+        cancleTv.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                getActivity().finish();
+            }
+        });
+        return view;
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        if (hasSurface) {
+            initCamera(surfaceHolder);
+        } else {
+            surfaceHolder.addCallback(this);
+            surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
+        }
+        decodeFormats = null;
+        characterSet = null;
+
+        playBeep = true;
+        AudioManager audioService = (AudioManager) getActivity().getSystemService(getActivity().AUDIO_SERVICE);
+        if (audioService.getRingerMode() != AudioManager.RINGER_MODE_NORMAL) {
+            playBeep = false;
+        }
+        initBeepSound();
+        vibrate = true;
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        if (handler != null) {
+            handler.quitSynchronously();
+            handler = null;
+        }
+        CameraManager.get().closeDriver();
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        inactivityTimer.shutdown();
+        super.onDestroy();
+    }
+
+
+    /**
+     * Handler scan result
+     *
+     * @param result
+     * @param barcode
+     */
+    public void handleDecode(Result result, Bitmap barcode) {
+        inactivityTimer.onActivity();
+        playBeepSoundAndVibrate();
+
+        if (result == null || TextUtils.isEmpty(result.getText())) {
+            if (analyzeCallback != null) {
+                analyzeCallback.onAnalyzeFailed();
+            }
+        } else {
+            if (analyzeCallback != null) {
+                analyzeCallback.onAnalyzeSuccess(barcode, result.getText());
+            }
+        }
+    }
+
+    private void initCamera(SurfaceHolder surfaceHolder) {
+        try {
+            CameraManager.get().openDriver(surfaceHolder);
+            camera = CameraManager.get().getCamera();
+        } catch (IOException ioe) {
+            return;
+        } catch (RuntimeException e) {
+            return;
+        }
+        if (handler == null) {
+            handler = new CaptureActivityHandler(this, decodeFormats, characterSet, viewfinderView);
+        }
+    }
+
+    @Override
+    public void surfaceChanged(SurfaceHolder holder, int format, int width,
+                               int height) {
+
+    }
+
+    @Override
+    public void surfaceCreated(SurfaceHolder holder) {
+        if (!hasSurface) {
+            hasSurface = true;
+            initCamera(holder);
+        }
+
+    }
+
+    @Override
+    public void surfaceDestroyed(SurfaceHolder holder) {
+        hasSurface = false;
+        if (camera != null) {
+            if (camera != null && CameraManager.get().isPreviewing()) {
+                if (!CameraManager.get().isUseOneShotPreviewCallback()) {
+                    camera.setPreviewCallback(null);
+                }
+                camera.stopPreview();
+                CameraManager.get().getPreviewCallback().setHandler(null, 0);
+                CameraManager.get().getAutoFocusCallback().setHandler(null, 0);
+                CameraManager.get().setPreviewing(false);
+            }
+        }
+    }
+
+    public Handler getHandler() {
+        return handler;
+    }
+
+    public void drawViewfinder() {
+        viewfinderView.drawViewfinder();
+
+    }
+
+    private void initBeepSound() {
+        if (playBeep && mediaPlayer == null) {
+            // The volume on STREAM_SYSTEM is not adjustable, and users found it
+            // too loud,
+            // so we now play on the music stream.
+            getActivity().setVolumeControlStream(AudioManager.STREAM_MUSIC);
+            mediaPlayer = new MediaPlayer();
+            mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
+            mediaPlayer.setOnCompletionListener(beepListener);
+
+            AssetFileDescriptor file = getResources().openRawResourceFd(
+                    R.raw.beep);
+            try {
+                mediaPlayer.setDataSource(file.getFileDescriptor(),
+                        file.getStartOffset(), file.getLength());
+                file.close();
+                mediaPlayer.setVolume(BEEP_VOLUME, BEEP_VOLUME);
+                mediaPlayer.prepare();
+            } catch (IOException e) {
+                mediaPlayer = null;
+            }
+        }
+    }
+
+    private static final long VIBRATE_DURATION = 200L;
+
+    private void playBeepSoundAndVibrate() {
+        if (playBeep && mediaPlayer != null) {
+            mediaPlayer.start();
+        }
+        if (vibrate) {
+            Vibrator vibrator = (Vibrator) getActivity().getSystemService(getActivity().VIBRATOR_SERVICE);
+            vibrator.vibrate(VIBRATE_DURATION);
+        }
+    }
+
+    /**
+     * When the beep has finished playing, rewind to queue up another one.
+     */
+    private final MediaPlayer.OnCompletionListener beepListener = new MediaPlayer.OnCompletionListener() {
+        public void onCompletion(MediaPlayer mediaPlayer) {
+            mediaPlayer.seekTo(0);
+        }
+    };
+
+    public CodeUtils.AnalyzeCallback getAnalyzeCallback() {
+        return analyzeCallback;
+    }
+
+    public void setAnalyzeCallback(CodeUtils.AnalyzeCallback analyzeCallback) {
+        this.analyzeCallback = analyzeCallback;
+    }
+
+}

+ 218 - 0
lib-zxing/src/main/java/com/uuzuche/lib_zxing/activity/CodeUtils.java

@@ -0,0 +1,218 @@
+package com.uuzuche.lib_zxing.activity;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.hardware.Camera;
+import android.os.Bundle;
+import android.text.TextUtils;
+
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.BinaryBitmap;
+import com.google.zxing.DecodeHintType;
+import com.google.zxing.EncodeHintType;
+import com.google.zxing.MultiFormatReader;
+import com.google.zxing.Result;
+import com.google.zxing.WriterException;
+import com.google.zxing.common.BitMatrix;
+import com.google.zxing.common.HybridBinarizer;
+import com.google.zxing.qrcode.QRCodeWriter;
+import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
+import com.uuzuche.lib_zxing.camera.BitmapLuminanceSource;
+import com.uuzuche.lib_zxing.camera.CameraManager;
+import com.uuzuche.lib_zxing.decoding.DecodeFormatManager;
+
+import java.util.Hashtable;
+import java.util.Objects;
+import java.util.Vector;
+
+/**
+ * Created by aaron on 16/7/27.
+ * 二维码扫描工具类
+ */
+public class CodeUtils {
+
+    public static final String RESULT_TYPE = "result_type";
+    public static final String RESULT_STRING = "result_string";
+    public static final int RESULT_SUCCESS = 1;
+    public static final int RESULT_FAILED = 2;
+
+    public static final String LAYOUT_ID = "layout_id";
+
+
+
+    /**
+     * 解析二维码图片工具类
+     * @param analyzeCallback
+     */
+    public static void analyzeBitmap(String path, AnalyzeCallback analyzeCallback) {
+
+        /**
+         * 首先判断图片的大小,若图片过大,则执行图片的裁剪操作,防止OOM
+         */
+        BitmapFactory.Options options = new BitmapFactory.Options();
+        options.inJustDecodeBounds = true; // 先获取原大小
+        Bitmap mBitmap = BitmapFactory.decodeFile(path, options);
+        options.inJustDecodeBounds = false; // 获取新的大小
+
+        int sampleSize = (int) (options.outHeight / (float) 400);
+
+        if (sampleSize <= 0)
+            sampleSize = 1;
+        options.inSampleSize = sampleSize;
+        mBitmap = BitmapFactory.decodeFile(path, options);
+
+        MultiFormatReader multiFormatReader = new MultiFormatReader();
+
+        // 解码的参数
+        Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>(2);
+        // 可以解析的编码类型
+        Vector<BarcodeFormat> decodeFormats = new Vector<BarcodeFormat>();
+        if (decodeFormats == null || decodeFormats.isEmpty()) {
+            decodeFormats = new Vector<BarcodeFormat>();
+
+            // 这里设置可扫描的类型,我这里选择了都支持
+            decodeFormats.addAll(DecodeFormatManager.ONE_D_FORMATS);
+            decodeFormats.addAll(DecodeFormatManager.QR_CODE_FORMATS);
+            decodeFormats.addAll(DecodeFormatManager.DATA_MATRIX_FORMATS);
+        }
+        hints.put(DecodeHintType.POSSIBLE_FORMATS, decodeFormats);
+        // 设置继续的字符编码格式为UTF8
+        // hints.put(DecodeHintType.CHARACTER_SET, "UTF8");
+        // 设置解析配置参数
+        multiFormatReader.setHints(hints);
+
+        // 开始对图像资源解码
+        Result rawResult = null;
+        try {
+            rawResult = multiFormatReader.decodeWithState(new BinaryBitmap(new HybridBinarizer(new BitmapLuminanceSource(mBitmap))));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        if (rawResult != null) {
+            if (analyzeCallback != null) {
+                analyzeCallback.onAnalyzeSuccess(mBitmap, rawResult.getText());
+            }
+        } else {
+            if (analyzeCallback != null) {
+                analyzeCallback.onAnalyzeFailed();
+            }
+        }
+    }
+
+    /**
+     * 生成二维码图片
+     * @param text
+     * @param w
+     * @param h
+     * @param logo
+     * @return
+     */
+    public static Bitmap createImage(String text,int w,int h,Bitmap logo) {
+        if (TextUtils.isEmpty(text)) {
+            return null;
+        }
+        try {
+            Bitmap scaleLogo = getScaleLogo(logo,w,h);
+
+            int offsetX = w / 2;
+            int offsetY = h / 2;
+
+            int scaleWidth = 0;
+            int scaleHeight = 0;
+            if (scaleLogo != null) {
+                scaleWidth = scaleLogo.getWidth();
+                scaleHeight = scaleLogo.getHeight();
+                offsetX = (w - scaleWidth) / 2;
+                offsetY = (h - scaleHeight) / 2;
+            }
+            Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
+            hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
+            //容错级别
+            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
+            //设置空白边距的宽度
+            hints.put(EncodeHintType.MARGIN, 0);
+            BitMatrix bitMatrix = new QRCodeWriter().encode(text, BarcodeFormat.QR_CODE, w, h, hints);
+            int[] pixels = new int[w * h];
+            for (int y = 0; y < h; y++) {
+                for (int x = 0; x < w; x++) {
+                    if(x >= offsetX && x < offsetX + scaleWidth && y>= offsetY && y < offsetY + scaleHeight){
+                        int pixel = scaleLogo.getPixel(x-offsetX,y-offsetY);
+                        if(pixel == 0){
+                            if(bitMatrix.get(x, y)){
+                                pixel = 0xff000000;
+                            }else{
+                                pixel = 0xffffffff;
+                            }
+                        }
+                        pixels[y * w + x] = pixel;
+                    }else{
+                        if (bitMatrix.get(x, y)) {
+                            pixels[y * w + x] = 0xff000000;
+                        } else {
+                            pixels[y * w + x] = 0xffffffff;
+                        }
+                    }
+                }
+            }
+            Bitmap bitmap = Bitmap.createBitmap(w, h,
+                    Bitmap.Config.ARGB_8888);
+            bitmap.setPixels(pixels, 0, w, 0, 0, w, h);
+            return bitmap;
+        } catch (WriterException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    private static Bitmap getScaleLogo(Bitmap logo,int w,int h){
+        if(logo == null)return null;
+        Matrix matrix = new Matrix();
+        float scaleFactor = Math.min(w * 1.0f / 5 / logo.getWidth(), h * 1.0f / 5 /logo.getHeight());
+        matrix.postScale(scaleFactor,scaleFactor);
+        Bitmap result = Bitmap.createBitmap(logo, 0, 0, logo.getWidth(),   logo.getHeight(), matrix, true);
+        return result;
+    }
+
+    /**
+     * 解析二维码结果
+     */
+    public interface AnalyzeCallback{
+
+        public void onAnalyzeSuccess(Bitmap mBitmap, String result);
+
+        public void onAnalyzeFailed();
+    }
+
+
+    /**
+     * 为CaptureFragment设置layout参数
+     * @param captureFragment
+     * @param layoutId
+     */
+    public static void setFragmentArgs(CaptureFragment captureFragment, int layoutId) {
+        if (captureFragment == null || layoutId == -1) {
+            return;
+        }
+
+        Bundle bundle = new Bundle();
+        bundle.putInt(LAYOUT_ID, layoutId);
+        captureFragment.setArguments(bundle);
+    }
+
+    public static void isLightEnable(boolean isEnable) {
+        if (isEnable) {
+            Camera camera = CameraManager.get().getCamera();
+            Camera.Parameters parameter = camera.getParameters();
+            parameter.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
+            camera.setParameters(parameter);
+        } else {
+            Camera camera = CameraManager.get().getCamera();
+            Camera.Parameters parameter = camera.getParameters();
+            parameter.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
+            camera.setParameters(parameter);
+        }
+    }
+}

+ 26 - 0
lib-zxing/src/main/java/com/uuzuche/lib_zxing/activity/ZXingLibrary.java

@@ -0,0 +1,26 @@
+package com.uuzuche.lib_zxing.activity;
+
+import android.content.Context;
+import android.util.DisplayMetrics;
+
+import com.uuzuche.lib_zxing.DisplayUtil;
+
+/**
+ * Created by aaron on 16/9/7.
+ */
+
+public class ZXingLibrary {
+
+    public static void initDisplayOpinion(Context context) {
+        if (context == null) {
+            return;
+        }
+        DisplayMetrics dm = context.getResources().getDisplayMetrics();
+        DisplayUtil.density = dm.density;
+        DisplayUtil.densityDPI = dm.densityDpi;
+        DisplayUtil.screenWidthPx = dm.widthPixels;
+        DisplayUtil.screenhightPx = dm.heightPixels;
+        DisplayUtil.screenWidthDip = DisplayUtil.px2dip(context, dm.widthPixels);
+        DisplayUtil.screenHightDip = DisplayUtil.px2dip(context, dm.heightPixels);
+    }
+}

+ 48 - 0
lib-zxing/src/main/java/com/uuzuche/lib_zxing/camera/AutoFocusCallback.java

@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2010 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.uuzuche.lib_zxing.camera;
+
+import android.hardware.Camera;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+
+public final class AutoFocusCallback implements Camera.AutoFocusCallback {
+
+    private static final String TAG = AutoFocusCallback.class.getSimpleName();
+
+    private static final long AUTOFOCUS_INTERVAL_MS = 1500L;
+
+    private Handler autoFocusHandler;
+    private int autoFocusMessage;
+
+    public void setHandler(Handler autoFocusHandler, int autoFocusMessage) {
+        this.autoFocusHandler = autoFocusHandler;
+        this.autoFocusMessage = autoFocusMessage;
+    }
+
+    public void onAutoFocus(boolean success, Camera camera) {
+        if (autoFocusHandler != null) {
+            Message message = autoFocusHandler.obtainMessage(autoFocusMessage, success);
+            autoFocusHandler.sendMessageDelayed(message, AUTOFOCUS_INTERVAL_MS);
+            autoFocusHandler = null;
+        } else {
+            Log.d(TAG, "Got auto-focus callback, but no handler for it");
+        }
+    }
+
+}

+ 41 - 0
lib-zxing/src/main/java/com/uuzuche/lib_zxing/camera/BitmapLuminanceSource.java

@@ -0,0 +1,41 @@
+package com.uuzuche.lib_zxing.camera;
+
+import android.graphics.Bitmap;
+
+import com.google.zxing.LuminanceSource;
+
+/**
+ * Created by aaron on 16/7/27.
+ * 自定义解析Bitmap LuminanceSource
+ */
+public class BitmapLuminanceSource extends LuminanceSource {
+
+    private byte bitmapPixels[];
+
+    public BitmapLuminanceSource(Bitmap bitmap) {
+        super(bitmap.getWidth(), bitmap.getHeight());
+
+        // 首先,要取得该图片的像素数组内容
+        int[] data = new int[bitmap.getWidth() * bitmap.getHeight()];
+        this.bitmapPixels = new byte[bitmap.getWidth() * bitmap.getHeight()];
+        bitmap.getPixels(data, 0, getWidth(), 0, 0, getWidth(), getHeight());
+
+        // 将int数组转换为byte数组,也就是取像素值中蓝色值部分作为辨析内容
+        for (int i = 0; i < data.length; i++) {
+            this.bitmapPixels[i] = (byte) data[i];
+        }
+    }
+
+    @Override
+    public byte[] getMatrix() {
+        // 返回我们生成好的像素数据
+        return bitmapPixels;
+    }
+
+    @Override
+    public byte[] getRow(int y, byte[] row) {
+        // 这里要得到指定行的像素数据
+        System.arraycopy(bitmapPixels, y * getWidth(), row, 0, getWidth());
+        return row;
+    }
+}

+ 278 - 0
lib-zxing/src/main/java/com/uuzuche/lib_zxing/camera/CameraConfigurationManager.java

@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2010 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.uuzuche.lib_zxing.camera;
+
+import android.content.Context;
+import android.graphics.Point;
+import android.hardware.Camera;
+import android.os.Build;
+import android.util.Log;
+import android.view.Display;
+import android.view.WindowManager;
+
+import java.util.regex.Pattern;
+
+final class CameraConfigurationManager {
+
+    private static final String TAG = CameraConfigurationManager.class.getSimpleName();
+
+    private static final int TEN_DESIRED_ZOOM = 27;
+    private static final int DESIRED_SHARPNESS = 30;
+
+    private static final Pattern COMMA_PATTERN = Pattern.compile(",");
+
+    private final Context context;
+    private Point screenResolution;
+    private Point cameraResolution;
+    private int previewFormat;
+    private String previewFormatString;
+
+    CameraConfigurationManager(Context context) {
+        this.context = context;
+    }
+
+    /**
+     * Reads, one time, values from the camera that are needed by the app.
+     */
+    void initFromCameraParameters(Camera camera) {
+        Camera.Parameters parameters = camera.getParameters();
+        previewFormat = parameters.getPreviewFormat();
+        previewFormatString = parameters.get("preview-format");
+        Log.d(TAG, "Default preview format: " + previewFormat + '/' + previewFormatString);
+        WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+        Display display = manager.getDefaultDisplay();
+        screenResolution = new Point(display.getWidth(), display.getHeight());
+        Log.d(TAG, "Screen resolution: " + screenResolution);
+
+        Point screenResolutionForCamera = new Point();
+        screenResolutionForCamera.x = screenResolution.x;
+        screenResolutionForCamera.y = screenResolution.y;
+        // preview size is always something like 480*320, other 320*480
+        if (screenResolution.x < screenResolution.y) {
+            screenResolutionForCamera.x = screenResolution.y;
+            screenResolutionForCamera.y = screenResolution.x;
+        }
+        Log.i("#########", "screenX:" + screenResolutionForCamera.x + "   screenY:" + screenResolutionForCamera.y);
+        cameraResolution = getCameraResolution(parameters, screenResolutionForCamera);
+
+        // cameraResolution = getCameraResolution(parameters, screenResolution);
+        Log.d(TAG, "Camera resolution: " + screenResolution);
+    }
+
+    /**
+     * Sets the camera up to take preview images which are used for both preview and decoding.
+     * We detect the preview format here so that buildLuminanceSource() can build an appropriate
+     * LuminanceSource subclass. In the future we may want to force YUV420SP as it's the smallest,
+     * and the planar Y can be used for barcode scanning without a copy in some cases.
+     */
+    void setDesiredCameraParameters(Camera camera) {
+        Camera.Parameters parameters = camera.getParameters();
+        Log.d(TAG, "Setting preview size: " + cameraResolution);
+        parameters.setPreviewSize(cameraResolution.x, cameraResolution.y);
+        setFlash(parameters);
+        setZoom(parameters);
+        //setSharpness(parameters);
+        //modify here
+        camera.setDisplayOrientation(90);
+        camera.setParameters(parameters);
+    }
+
+    Point getCameraResolution() {
+        return cameraResolution;
+    }
+
+    Point getScreenResolution() {
+        return screenResolution;
+    }
+
+    int getPreviewFormat() {
+        return previewFormat;
+    }
+
+    String getPreviewFormatString() {
+        return previewFormatString;
+    }
+
+    private static Point getCameraResolution(Camera.Parameters parameters, Point screenResolution) {
+
+        String previewSizeValueString = parameters.get("preview-size-values");
+        // saw this on Xperia
+        if (previewSizeValueString == null) {
+            previewSizeValueString = parameters.get("preview-size-value");
+        }
+
+        Point cameraResolution = null;
+
+        if (previewSizeValueString != null) {
+            Log.d(TAG, "preview-size-values parameter: " + previewSizeValueString);
+            cameraResolution = findBestPreviewSizeValue(previewSizeValueString, screenResolution);
+        }
+
+        if (cameraResolution == null) {
+            // Ensure that the camera resolution is a multiple of 8, as the screen may not be.
+            cameraResolution = new Point(
+                    (screenResolution.x >> 3) << 3,
+                    (screenResolution.y >> 3) << 3);
+        }
+
+        return cameraResolution;
+    }
+
+    private static Point findBestPreviewSizeValue(CharSequence previewSizeValueString, Point screenResolution) {
+        int bestX = 0;
+        int bestY = 0;
+        int diff = Integer.MAX_VALUE;
+        for (String previewSize : COMMA_PATTERN.split(previewSizeValueString)) {
+
+            previewSize = previewSize.trim();
+            int dimPosition = previewSize.indexOf('x');
+            if (dimPosition < 0) {
+                Log.w(TAG, "Bad preview-size: " + previewSize);
+                continue;
+            }
+
+            int newX;
+            int newY;
+            try {
+                newX = Integer.parseInt(previewSize.substring(0, dimPosition));
+                newY = Integer.parseInt(previewSize.substring(dimPosition + 1));
+            } catch (NumberFormatException nfe) {
+                Log.w(TAG, "Bad preview-size: " + previewSize);
+                continue;
+            }
+
+            int newDiff = Math.abs(newX - screenResolution.x) + Math.abs(newY - screenResolution.y);
+            if (newDiff == 0) {
+                bestX = newX;
+                bestY = newY;
+                break;
+            } else if (newDiff < diff) {
+                bestX = newX;
+                bestY = newY;
+                diff = newDiff;
+            }
+
+        }
+
+        if (bestX > 0 && bestY > 0) {
+            return new Point(bestX, bestY);
+        }
+        return null;
+    }
+
+    private static int findBestMotZoomValue(CharSequence stringValues, int tenDesiredZoom) {
+        int tenBestValue = 0;
+        for (String stringValue : COMMA_PATTERN.split(stringValues)) {
+            stringValue = stringValue.trim();
+            double value;
+            try {
+                value = Double.parseDouble(stringValue);
+            } catch (NumberFormatException nfe) {
+                return tenDesiredZoom;
+            }
+            int tenValue = (int) (10.0 * value);
+            if (Math.abs(tenDesiredZoom - value) < Math.abs(tenDesiredZoom - tenBestValue)) {
+                tenBestValue = tenValue;
+            }
+        }
+        return tenBestValue;
+    }
+
+    private void setFlash(Camera.Parameters parameters) {
+        // FIXME: This is a hack to turn the flash off on the Samsung Galaxy.
+        // And this is a hack-hack to work around a different value on the Behold II
+        // Restrict Behold II check to Cupcake, per Samsung's advice
+        //if (Build.MODEL.contains("Behold II") &&
+        //    CameraManager.SDK_INT == Build.VERSION_CODES.CUPCAKE) {
+        if (Build.MODEL.contains("Behold II") && CameraManager.SDK_INT == 3) { // 3 = Cupcake
+            parameters.set("flash-value", 1);
+        } else {
+            parameters.set("flash-value", 2);
+        }
+        // This is the standard setting to turn the flash off that all devices should honor.
+        parameters.set("flash-mode", "off");
+    }
+
+    private void setZoom(Camera.Parameters parameters) {
+
+        String zoomSupportedString = parameters.get("zoom-supported");
+        if (zoomSupportedString != null && !Boolean.parseBoolean(zoomSupportedString)) {
+            return;
+        }
+
+        int tenDesiredZoom = TEN_DESIRED_ZOOM;
+
+        String maxZoomString = parameters.get("max-zoom");
+        if (maxZoomString != null) {
+            try {
+                int tenMaxZoom = (int) (10.0 * Double.parseDouble(maxZoomString));
+                if (tenDesiredZoom > tenMaxZoom) {
+                    tenDesiredZoom = tenMaxZoom;
+                }
+            } catch (NumberFormatException nfe) {
+                Log.w(TAG, "Bad max-zoom: " + maxZoomString);
+            }
+        }
+
+        String takingPictureZoomMaxString = parameters.get("taking-picture-zoom-max");
+        if (takingPictureZoomMaxString != null) {
+            try {
+                int tenMaxZoom = Integer.parseInt(takingPictureZoomMaxString);
+                if (tenDesiredZoom > tenMaxZoom) {
+                    tenDesiredZoom = tenMaxZoom;
+                }
+            } catch (NumberFormatException nfe) {
+                Log.w(TAG, "Bad taking-picture-zoom-max: " + takingPictureZoomMaxString);
+            }
+        }
+
+        String motZoomValuesString = parameters.get("mot-zoom-values");
+        if (motZoomValuesString != null) {
+            tenDesiredZoom = findBestMotZoomValue(motZoomValuesString, tenDesiredZoom);
+        }
+
+        String motZoomStepString = parameters.get("mot-zoom-step");
+        if (motZoomStepString != null) {
+            try {
+                double motZoomStep = Double.parseDouble(motZoomStepString.trim());
+                int tenZoomStep = (int) (10.0 * motZoomStep);
+                if (tenZoomStep > 1) {
+                    tenDesiredZoom -= tenDesiredZoom % tenZoomStep;
+                }
+            } catch (NumberFormatException nfe) {
+                // continue
+            }
+        }
+
+        // Set zoom. This helps encourage the user to pull back.
+        // Some devices like the Behold have a zoom parameter
+        if (maxZoomString != null || motZoomValuesString != null) {
+            parameters.set("zoom", String.valueOf(tenDesiredZoom / 10.0));
+        }
+
+        // Most devices, like the Hero, appear to expose this zoom parameter.
+        // It takes on values like "27" which appears to mean 2.7x zoom
+        if (takingPictureZoomMaxString != null) {
+            parameters.set("taking-picture-zoom", tenDesiredZoom);
+        }
+    }
+
+    public static int getDesiredSharpness() {
+        return DESIRED_SHARPNESS;
+    }
+
+}

+ 348 - 0
lib-zxing/src/main/java/com/uuzuche/lib_zxing/camera/CameraManager.java

@@ -0,0 +1,348 @@
+/*
+ * Copyright (C) 2008 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.uuzuche.lib_zxing.camera;
+
+import android.content.Context;
+import android.graphics.PixelFormat;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.hardware.Camera;
+import android.os.Build;
+import android.os.Handler;
+import android.util.Log;
+import android.view.SurfaceHolder;
+import android.view.Window;
+
+import java.io.IOException;
+
+import static android.R.attr.top;
+import static android.R.attr.width;
+
+/**
+ * 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 final class CameraManager {
+
+    private static final String TAG = CameraManager.class.getSimpleName();
+
+    public static int FRAME_WIDTH = -1;
+    public static int FRAME_HEIGHT = -1;
+    public static int FRAME_MARGINTOP = -1;
+
+    private static CameraManager cameraManager;
+
+    static final int SDK_INT; // Later we can use Build.VERSION.SDK_INT
+
+    static {
+        int sdkInt;
+        try {
+            sdkInt = Integer.parseInt(Build.VERSION.SDK);
+        } catch (NumberFormatException nfe) {
+            // Just to be safe
+            sdkInt = 10000;
+        }
+        SDK_INT = sdkInt;
+    }
+
+    private final Context context;
+    private final CameraConfigurationManager configManager;
+    private Camera camera;
+    private Rect framingRect;
+    private Rect framingRectInPreview;
+    private boolean initialized;
+    private boolean previewing;
+    private final boolean useOneShotPreviewCallback;
+    /**
+     * 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;
+    /**
+     * Autofocus callbacks arrive here, and are dispatched to the Handler which requested them.
+     */
+    private final AutoFocusCallback autoFocusCallback;
+
+    /**
+     * Initializes this static object with the Context of the calling Activity.
+     *
+     * @param context The Activity which wants to use the camera.
+     */
+    public static void init(Context context) {
+        if (cameraManager == null) {
+            cameraManager = new CameraManager(context);
+        }
+    }
+
+    /**
+     * Gets the CameraManager singleton instance.
+     *
+     * @return A reference to the CameraManager singleton.
+     */
+    public static CameraManager get() {
+        return cameraManager;
+    }
+
+    private CameraManager(Context context) {
+
+        this.context = context;
+        this.configManager = new CameraConfigurationManager(context);
+
+        // Camera.setOneShotPreviewCallback() has a race condition in Cupcake, so we use the older
+        // Camera.setPreviewCallback() on 1.5 and earlier. For Donut and later, we need to use
+        // the more efficient one shot callback, as the older one can swamp the system and cause it
+        // to run out of memory. We can't use SDK_INT because it was introduced in the Donut SDK.
+        //useOneShotPreviewCallback = Integer.parseInt(Build.VERSION.SDK) > Build.VERSION_CODES.CUPCAKE;
+        useOneShotPreviewCallback = Integer.parseInt(Build.VERSION.SDK) > 3; // 3 = Cupcake
+
+        previewCallback = new PreviewCallback(configManager, useOneShotPreviewCallback);
+        autoFocusCallback = new AutoFocusCallback();
+    }
+
+    /**
+     * 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 void openDriver(SurfaceHolder holder) throws IOException {
+        if (camera == null) {
+            camera = Camera.open();
+            if (camera == null) {
+                throw new IOException();
+            }
+            camera.setPreviewDisplay(holder);
+
+            if (!initialized) {
+                initialized = true;
+                configManager.initFromCameraParameters(camera);
+            }
+            configManager.setDesiredCameraParameters(camera);
+
+            //FIXME
+            //     SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+            //�Ƿ�ʹ��ǰ��
+//      if (prefs.getBoolean(PreferencesActivity.KEY_FRONT_LIGHT, false)) {
+//        FlashlightManager.enableFlashlight();
+//      }
+            FlashlightManager.enableFlashlight();
+        }
+    }
+
+    /**
+     * Closes the camera driver if still in use.
+     */
+    public void closeDriver() {
+        if (camera != null) {
+            FlashlightManager.disableFlashlight();
+            camera.release();
+            camera = null;
+        }
+    }
+
+    /**
+     * Asks the camera hardware to begin drawing preview frames to the screen.
+     */
+    public void startPreview() {
+        if (camera != null && !previewing) {
+            camera.startPreview();
+            previewing = true;
+        }
+    }
+
+    /**
+     * Tells the camera to stop drawing preview frames.
+     */
+    public void stopPreview() {
+        if (camera != null && previewing) {
+            if (!useOneShotPreviewCallback) {
+                camera.setPreviewCallback(null);
+            }
+            camera.stopPreview();
+            previewCallback.setHandler(null, 0);
+            autoFocusCallback.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 void requestPreviewFrame(Handler handler, int message) {
+        if (camera != null && previewing) {
+            previewCallback.setHandler(handler, message);
+            if (useOneShotPreviewCallback) {
+                camera.setOneShotPreviewCallback(previewCallback);
+            } else {
+                camera.setPreviewCallback(previewCallback);
+            }
+        }
+    }
+
+    /**
+     * Asks the camera hardware to perform an autofocus.
+     *
+     * @param handler The Handler to notify when the autofocus completes.
+     * @param message The message to deliver.
+     */
+    public void requestAutoFocus(Handler handler, int message) {
+        if (camera != null && previewing) {
+            autoFocusCallback.setHandler(handler, message);
+            //Log.d(TAG, "Requesting auto-focus callback");
+            camera.autoFocus(autoFocusCallback);
+        }
+    }
+
+    /**
+     * Calculates the framing rect which the UI should draw to show the user where to place the
+     * barcode. This target helps with alignment as well as forces the user to hold the device
+     * far enough away to ensure the image will be in focus.
+     *
+     * @return The rectangle to draw on screen in window coordinates.
+     */
+    public Rect getFramingRect() {
+        Point screenResolution = configManager.getScreenResolution();
+        // if (framingRect == null) {
+            if (camera == null) {
+                return null;
+            }
+
+            int leftOffset = (screenResolution.x - FRAME_WIDTH) / 2;
+
+            int topOffset = 0;
+            if (FRAME_MARGINTOP != -1) {
+                topOffset = FRAME_MARGINTOP;
+            } else {
+                topOffset = (screenResolution.y - FRAME_HEIGHT) / 2;
+            }
+            framingRect = new Rect(leftOffset, topOffset, leftOffset + FRAME_WIDTH, topOffset + FRAME_HEIGHT);
+        // }
+        return framingRect;
+    }
+
+    /**
+     * Like {@link #getFramingRect} but coordinates are in terms of the preview frame,
+     * not UI / screen.
+     */
+    public Rect getFramingRectInPreview() {
+        if (framingRectInPreview == null) {
+            Rect rect = new Rect(getFramingRect());
+            Point cameraResolution = configManager.getCameraResolution();
+            Point screenResolution = configManager.getScreenResolution();
+            //modify here
+//      rect.left = rect.left * cameraResolution.x / screenResolution.x;
+//      rect.right = rect.right * cameraResolution.x / screenResolution.x;
+//      rect.top = rect.top * cameraResolution.y / screenResolution.y;
+//      rect.bottom = rect.bottom * cameraResolution.y / screenResolution.y;
+            rect.left = rect.left * cameraResolution.y / screenResolution.x;
+            rect.right = rect.right * cameraResolution.y / screenResolution.x;
+            rect.top = rect.top * cameraResolution.x / screenResolution.y;
+            rect.bottom = rect.bottom * cameraResolution.x / screenResolution.y;
+            framingRectInPreview = rect;
+        }
+        return framingRectInPreview;
+    }
+
+    /**
+     * Converts the result points from still resolution coordinates to screen coordinates.
+     *
+     * @param points The points returned by the Reader subclass through Result.getResultPoints().
+     * @return An array of Points scaled to the size of the framing rect and offset appropriately
+     *         so they can be drawn in screen coordinates.
+     */
+  /*
+  public Point[] convertResultPoints(ResultPoint[] points) {
+    Rect frame = getFramingRectInPreview();
+    int count = points.length;
+    Point[] output = new Point[count];
+    for (int x = 0; x < count; x++) {
+      output[x] = new Point();
+      output[x].x = frame.left + (int) (points[x].getX() + 0.5f);
+      output[x].y = frame.top + (int) (points[x].getY() + 0.5f);
+    }
+    return output;
+  }
+   */
+
+    /**
+     * 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 = getFramingRectInPreview();
+        int previewFormat = configManager.getPreviewFormat();
+        String previewFormatString = configManager.getPreviewFormatString();
+        switch (previewFormat) {
+            // This is the standard Android format which all devices are REQUIRED to support.
+            // In theory, it's the only one we should ever care about.
+            case PixelFormat.YCbCr_420_SP:
+                // This format has never been seen in the wild, but is compatible as we only care
+                // about the Y channel, so allow it.
+            case PixelFormat.YCbCr_422_SP:
+                return new PlanarYUVLuminanceSource(data, width, height, rect.left, rect.top,
+                        rect.width(), rect.height());
+            default:
+                // The Samsung Moment incorrectly uses this variant instead of the 'sp' version.
+                // Fortunately, it too has all the Y data up front, so we can read it.
+                if ("yuv420p".equals(previewFormatString)) {
+                    return new PlanarYUVLuminanceSource(data, width, height, rect.left, rect.top,
+                            rect.width(), rect.height());
+                }
+        }
+        throw new IllegalArgumentException("Unsupported picture format: " +
+                previewFormat + '/' + previewFormatString);
+    }
+
+    public Context getContext() {
+        return context;
+    }
+
+    public Camera getCamera() {
+        return camera;
+    }
+
+    public boolean isPreviewing() {
+        return previewing;
+    }
+
+    public boolean isUseOneShotPreviewCallback() {
+        return useOneShotPreviewCallback;
+    }
+
+    public PreviewCallback getPreviewCallback() {
+        return previewCallback;
+    }
+
+    public AutoFocusCallback getAutoFocusCallback() {
+        return autoFocusCallback;
+    }
+
+    public void setPreviewing(boolean previewing) {
+        this.previewing = previewing;
+    }
+}

+ 151 - 0
lib-zxing/src/main/java/com/uuzuche/lib_zxing/camera/FlashlightManager.java

@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2010 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.uuzuche.lib_zxing.camera;
+
+import android.os.IBinder;
+import android.util.Log;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * This class is used to activate the weak light on some camera phones (not flash)
+ * in order to illuminate surfaces for scanning. There is no official way to do this,
+ * but, classes which allow access to this function still exist on some devices.
+ * This therefore proceeds through a great deal of reflection.
+ * <p>
+ * See <a href="http://almondmendoza.com/2009/01/05/changing-the-screen-brightness-programatically/">
+ * http://almondmendoza.com/2009/01/05/changing-the-screen-brightness-programatically/</a> and
+ * <a href="http://code.google.com/p/droidled/source/browse/trunk/src/com/droidled/demo/DroidLED.java">
+ * http://code.google.com/p/droidled/source/browse/trunk/src/com/droidled/demo/DroidLED.java</a>.
+ * Thanks to Ryan Alford for pointing out the availability of this class.
+ */
+final class FlashlightManager {
+
+    private static final String TAG = FlashlightManager.class.getSimpleName();
+
+    private static final Object iHardwareService;
+    private static final Method setFlashEnabledMethod;
+
+    static {
+        iHardwareService = getHardwareService();
+        setFlashEnabledMethod = getSetFlashEnabledMethod(iHardwareService);
+        if (iHardwareService == null) {
+            Log.v(TAG, "This device does supports control of a flashlight");
+        } else {
+            Log.v(TAG, "This device does not support control of a flashlight");
+        }
+    }
+
+    private FlashlightManager() {
+    }
+
+    /**
+     * �����������ƿ���
+     */
+    //FIXME
+    static void enableFlashlight() {
+        setFlashlight(false);
+    }
+
+    static void disableFlashlight() {
+        setFlashlight(false);
+    }
+
+    private static Object getHardwareService() {
+        Class<?> serviceManagerClass = maybeForName("android.os.ServiceManager");
+        if (serviceManagerClass == null) {
+            return null;
+        }
+
+        Method getServiceMethod = maybeGetMethod(serviceManagerClass, "getService", String.class);
+        if (getServiceMethod == null) {
+            return null;
+        }
+
+        Object hardwareService = invoke(getServiceMethod, null, "hardware");
+        if (hardwareService == null) {
+            return null;
+        }
+
+        Class<?> iHardwareServiceStubClass = maybeForName("android.os.IHardwareService$Stub");
+        if (iHardwareServiceStubClass == null) {
+            return null;
+        }
+
+        Method asInterfaceMethod = maybeGetMethod(iHardwareServiceStubClass, "asInterface", IBinder.class);
+        if (asInterfaceMethod == null) {
+            return null;
+        }
+
+        return invoke(asInterfaceMethod, null, hardwareService);
+    }
+
+    private static Method getSetFlashEnabledMethod(Object iHardwareService) {
+        if (iHardwareService == null) {
+            return null;
+        }
+        Class<?> proxyClass = iHardwareService.getClass();
+        return maybeGetMethod(proxyClass, "setFlashlightEnabled", boolean.class);
+    }
+
+    private static Class<?> maybeForName(String name) {
+        try {
+            return Class.forName(name);
+        } catch (ClassNotFoundException cnfe) {
+            // OK
+            return null;
+        } catch (RuntimeException re) {
+            Log.w(TAG, "Unexpected error while finding class " + name, re);
+            return null;
+        }
+    }
+
+    private static Method maybeGetMethod(Class<?> clazz, String name, Class<?>... argClasses) {
+        try {
+            return clazz.getMethod(name, argClasses);
+        } catch (NoSuchMethodException nsme) {
+            // OK
+            return null;
+        } catch (RuntimeException re) {
+            Log.w(TAG, "Unexpected error while finding method " + name, re);
+            return null;
+        }
+    }
+
+    private static Object invoke(Method method, Object instance, Object... args) {
+        try {
+            return method.invoke(instance, args);
+        } catch (IllegalAccessException e) {
+            Log.w(TAG, "Unexpected error while invoking " + method, e);
+            return null;
+        } catch (InvocationTargetException e) {
+            Log.w(TAG, "Unexpected error while invoking " + method, e.getCause());
+            return null;
+        } catch (RuntimeException re) {
+            Log.w(TAG, "Unexpected error while invoking " + method, re);
+            return null;
+        }
+    }
+
+    private static void setFlashlight(boolean active) {
+        if (iHardwareService != null) {
+            invoke(setFlashEnabledMethod, iHardwareService, active);
+        }
+    }
+
+}

+ 133 - 0
lib-zxing/src/main/java/com/uuzuche/lib_zxing/camera/PlanarYUVLuminanceSource.java

@@ -0,0 +1,133 @@
+/*
+ * Copyright 2009 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.uuzuche.lib_zxing.camera;
+
+import android.graphics.Bitmap;
+
+import com.google.zxing.LuminanceSource;
+
+/**
+ * This object extends LuminanceSource around an array of YUV data returned from the camera driver,
+ * with the option to crop to a rectangle within the full data. This can be used to exclude
+ * superfluous pixels around the perimeter and speed up decoding.
+ * <p>
+ * It works for any pixel format where the Y channel is planar and appears first, including
+ * YCbCr_420_SP and YCbCr_422_SP.
+ *
+ * @author dswitkin@google.com (Daniel Switkin)
+ */
+public final class PlanarYUVLuminanceSource extends LuminanceSource {
+    private final byte[] yuvData;
+    private final int dataWidth;
+    private final int dataHeight;
+    private final int left;
+    private final int top;
+
+    public PlanarYUVLuminanceSource(byte[] yuvData, int dataWidth, int dataHeight, int left, int top,
+                                    int width, int height) {
+        super(width, height);
+
+        if (left + width > dataWidth || top + height > dataHeight) {
+            throw new IllegalArgumentException("Crop rectangle does not fit within image data.");
+        }
+
+        this.yuvData = yuvData;
+        this.dataWidth = dataWidth;
+        this.dataHeight = dataHeight;
+        this.left = left;
+        this.top = top;
+    }
+
+    @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];
+        }
+        int offset = (y + top) * dataWidth + left;
+        System.arraycopy(yuvData, offset, row, 0, width);
+        return row;
+    }
+
+    @Override
+    public byte[] getMatrix() {
+        int width = getWidth();
+        int height = getHeight();
+
+        // If the caller asks for the entire underlying image, save the copy and give them the
+        // original data. The docs specifically warn that result.length must be ignored.
+        if (width == dataWidth && height == dataHeight) {
+            return yuvData;
+        }
+
+        int area = width * height;
+        byte[] matrix = new byte[area];
+        int inputOffset = top * dataWidth + left;
+
+        // If the width matches the full width of the underlying data, perform a single copy.
+        if (width == dataWidth) {
+            System.arraycopy(yuvData, inputOffset, matrix, 0, area);
+            return matrix;
+        }
+
+        // Otherwise copy one cropped row at a time.
+        byte[] yuv = yuvData;
+        for (int y = 0; y < height; y++) {
+            int outputOffset = y * width;
+            System.arraycopy(yuv, inputOffset, matrix, outputOffset, width);
+            inputOffset += dataWidth;
+        }
+        return matrix;
+    }
+
+    @Override
+    public boolean isCropSupported() {
+        return true;
+    }
+
+    public int getDataWidth() {
+        return dataWidth;
+    }
+
+    public int getDataHeight() {
+        return dataHeight;
+    }
+
+    public Bitmap renderCroppedGreyscaleBitmap() {
+        int width = getWidth();
+        int height = getHeight();
+        int[] pixels = new int[width * height];
+        byte[] yuv = yuvData;
+        int inputOffset = top * dataWidth + left;
+
+        for (int y = 0; y < height; y++) {
+            int outputOffset = y * width;
+            for (int x = 0; x < width; x++) {
+                int grey = yuv[inputOffset + x] & 0xff;
+                pixels[outputOffset + x] = 0xFF000000 | (grey * 0x00010101);
+            }
+            inputOffset += dataWidth;
+        }
+
+        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+        bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
+        return bitmap;
+    }
+}

+ 59 - 0
lib-zxing/src/main/java/com/uuzuche/lib_zxing/camera/PreviewCallback.java

@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2010 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.uuzuche.lib_zxing.camera;
+
+import android.graphics.Point;
+import android.hardware.Camera;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+
+public final class PreviewCallback implements Camera.PreviewCallback {
+
+    private static final String TAG = PreviewCallback.class.getSimpleName();
+
+    private final CameraConfigurationManager configManager;
+    private final boolean useOneShotPreviewCallback;
+    private Handler previewHandler;
+    private int previewMessage;
+
+    PreviewCallback(CameraConfigurationManager configManager, boolean useOneShotPreviewCallback) {
+        this.configManager = configManager;
+        this.useOneShotPreviewCallback = useOneShotPreviewCallback;
+    }
+
+    public void setHandler(Handler previewHandler, int previewMessage) {
+        this.previewHandler = previewHandler;
+        this.previewMessage = previewMessage;
+    }
+
+    public void onPreviewFrame(byte[] data, Camera camera) {
+        Point cameraResolution = configManager.getCameraResolution();
+        if (!useOneShotPreviewCallback) {
+            camera.setPreviewCallback(null);
+        }
+        if (previewHandler != null) {
+            Message message = previewHandler.obtainMessage(previewMessage, cameraResolution.x,
+                    cameraResolution.y, data);
+            message.sendToTarget();
+            previewHandler = null;
+        } else {
+            Log.d(TAG, "Got preview callback, but no handler for it");
+        }
+    }
+
+}

+ 133 - 0
lib-zxing/src/main/java/com/uuzuche/lib_zxing/decoding/CaptureActivityHandler.java

@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2008 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.uuzuche.lib_zxing.decoding;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.Result;
+import com.uuzuche.lib_zxing.R;
+import com.uuzuche.lib_zxing.activity.CaptureActivity;
+import com.uuzuche.lib_zxing.activity.CaptureFragment;
+import com.uuzuche.lib_zxing.camera.CameraManager;
+import com.uuzuche.lib_zxing.view.ViewfinderResultPointCallback;
+import com.uuzuche.lib_zxing.view.ViewfinderView;
+
+import java.util.Vector;
+
+/**
+ * This class handles all the messaging which comprises the state machine for capture.
+ */
+public final class CaptureActivityHandler extends Handler {
+
+    private static final String TAG = CaptureActivityHandler.class.getSimpleName();
+
+    private final CaptureFragment fragment;
+    private final DecodeThread decodeThread;
+    private State state;
+
+    private enum State {
+        PREVIEW,
+        SUCCESS,
+        DONE
+    }
+
+    public CaptureActivityHandler(CaptureFragment fragment, Vector<BarcodeFormat> decodeFormats,
+                                  String characterSet, ViewfinderView viewfinderView) {
+        this.fragment = fragment;
+        decodeThread = new DecodeThread(fragment, decodeFormats, characterSet,
+                new ViewfinderResultPointCallback(viewfinderView));
+        decodeThread.start();
+        state = State.SUCCESS;
+        // Start ourselves capturing previews and decoding.
+        CameraManager.get().startPreview();
+        restartPreviewAndDecode();
+    }
+
+    @Override
+    public void handleMessage(Message message) {
+        if (message.what == R.id.auto_focus) {
+            //Log.d(TAG, "Got auto-focus message");
+            // When one auto focus pass finishes, start another. This is the closest thing to
+            // continuous AF. It does seem to hunt a bit, but I'm not sure what else to do.
+            if (state == State.PREVIEW) {
+                CameraManager.get().requestAutoFocus(this, R.id.auto_focus);
+            }
+        } else if (message.what == R.id.restart_preview) {
+            Log.d(TAG, "Got restart preview message");
+            restartPreviewAndDecode();
+        } else if (message.what == R.id.decode_succeeded) {
+            Log.d(TAG, "Got decode succeeded message");
+            state = State.SUCCESS;
+            Bundle bundle = message.getData();
+
+            /***********************************************************************/
+            Bitmap barcode = bundle == null ? null :
+                    (Bitmap) bundle.getParcelable(DecodeThread.BARCODE_BITMAP);//���ñ����߳�
+
+            fragment.handleDecode((Result) message.obj, barcode);//���ؽ��
+            /***********************************************************************/
+        } 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.get().requestPreviewFrame(decodeThread.getHandler(), R.id.decode);
+        } else if (message.what == R.id.return_scan_result) {
+            Log.d(TAG, "Got return scan result message");
+            fragment.getActivity().setResult(Activity.RESULT_OK, (Intent) message.obj);
+            fragment.getActivity().finish();
+        } else if (message.what == R.id.launch_product_query) {
+            Log.d(TAG, "Got product query message");
+            String url = (String) message.obj;
+            Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
+            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
+            fragment.getActivity().startActivity(intent);
+        }
+    }
+
+    public void quitSynchronously() {
+        state = State.DONE;
+        CameraManager.get().stopPreview();
+        Message quit = Message.obtain(decodeThread.getHandler(), R.id.quit);
+        quit.sendToTarget();
+        try {
+            decodeThread.join();
+        } 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.get().requestPreviewFrame(decodeThread.getHandler(), R.id.decode);
+            CameraManager.get().requestAutoFocus(this, R.id.auto_focus);
+            fragment.drawViewfinder();
+        }
+    }
+
+}

+ 107 - 0
lib-zxing/src/main/java/com/uuzuche/lib_zxing/decoding/DecodeFormatManager.java

@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2010 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.uuzuche.lib_zxing.decoding;
+
+import android.content.Intent;
+import android.net.Uri;
+
+import com.google.zxing.BarcodeFormat;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Vector;
+import java.util.regex.Pattern;
+
+public class DecodeFormatManager {
+
+    private static final Pattern COMMA_PATTERN = Pattern.compile(",");
+
+    public static final Vector<BarcodeFormat> PRODUCT_FORMATS;
+    public static final Vector<BarcodeFormat> ONE_D_FORMATS;
+    public static final Vector<BarcodeFormat> QR_CODE_FORMATS;
+    public static final Vector<BarcodeFormat> DATA_MATRIX_FORMATS;
+
+    static {
+        PRODUCT_FORMATS = new Vector<BarcodeFormat>(5);
+        PRODUCT_FORMATS.add(BarcodeFormat.UPC_A);
+        PRODUCT_FORMATS.add(BarcodeFormat.UPC_E);
+        PRODUCT_FORMATS.add(BarcodeFormat.EAN_13);
+        PRODUCT_FORMATS.add(BarcodeFormat.EAN_8);
+        // PRODUCT_FORMATS.add(BarcodeFormat.RSS14);
+        ONE_D_FORMATS = new Vector<BarcodeFormat>(PRODUCT_FORMATS.size() + 4);
+        ONE_D_FORMATS.addAll(PRODUCT_FORMATS);
+        ONE_D_FORMATS.add(BarcodeFormat.CODE_39);
+        ONE_D_FORMATS.add(BarcodeFormat.CODE_93);
+        ONE_D_FORMATS.add(BarcodeFormat.CODE_128);
+        ONE_D_FORMATS.add(BarcodeFormat.ITF);
+        QR_CODE_FORMATS = new Vector<BarcodeFormat>(1);
+        QR_CODE_FORMATS.add(BarcodeFormat.QR_CODE);
+        DATA_MATRIX_FORMATS = new Vector<BarcodeFormat>(1);
+        DATA_MATRIX_FORMATS.add(BarcodeFormat.DATA_MATRIX);
+    }
+
+    private DecodeFormatManager() {
+    }
+
+    static Vector<BarcodeFormat> parseDecodeFormats(Intent intent) {
+        List<String> scanFormats = null;
+        String scanFormatsString = intent.getStringExtra(Intents.Scan.SCAN_FORMATS);
+        if (scanFormatsString != null) {
+            scanFormats = Arrays.asList(COMMA_PATTERN.split(scanFormatsString));
+        }
+        return parseDecodeFormats(scanFormats, intent.getStringExtra(Intents.Scan.MODE));
+    }
+
+    static Vector<BarcodeFormat> parseDecodeFormats(Uri inputUri) {
+        List<String> formats = inputUri.getQueryParameters(Intents.Scan.SCAN_FORMATS);
+        if (formats != null && formats.size() == 1 && formats.get(0) != null) {
+            formats = Arrays.asList(COMMA_PATTERN.split(formats.get(0)));
+        }
+        return parseDecodeFormats(formats, inputUri.getQueryParameter(Intents.Scan.MODE));
+    }
+
+    private static Vector<BarcodeFormat> parseDecodeFormats(Iterable<String> scanFormats,
+                                                            String decodeMode) {
+        if (scanFormats != null) {
+            Vector<BarcodeFormat> formats = new Vector<BarcodeFormat>();
+            try {
+                for (String format : scanFormats) {
+                    formats.add(BarcodeFormat.valueOf(format));
+                }
+                return formats;
+            } catch (IllegalArgumentException iae) {
+                // ignore it then
+            }
+        }
+        if (decodeMode != null) {
+            if (Intents.Scan.PRODUCT_MODE.equals(decodeMode)) {
+                return PRODUCT_FORMATS;
+            }
+            if (Intents.Scan.QR_CODE_MODE.equals(decodeMode)) {
+                return QR_CODE_FORMATS;
+            }
+            if (Intents.Scan.DATA_MATRIX_MODE.equals(decodeMode)) {
+                return DATA_MATRIX_FORMATS;
+            }
+            if (Intents.Scan.ONE_D_MODE.equals(decodeMode)) {
+                return ONE_D_FORMATS;
+            }
+        }
+        return null;
+    }
+
+}

+ 108 - 0
lib-zxing/src/main/java/com/uuzuche/lib_zxing/decoding/DecodeHandler.java

@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2010 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.uuzuche.lib_zxing.decoding;
+
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.util.Log;
+
+import com.google.zxing.BinaryBitmap;
+import com.google.zxing.DecodeHintType;
+import com.google.zxing.MultiFormatReader;
+import com.google.zxing.ReaderException;
+import com.google.zxing.Result;
+import com.google.zxing.common.HybridBinarizer;
+import com.uuzuche.lib_zxing.R;
+import com.uuzuche.lib_zxing.activity.CaptureActivity;
+import com.uuzuche.lib_zxing.activity.CaptureFragment;
+import com.uuzuche.lib_zxing.camera.CameraManager;
+import com.uuzuche.lib_zxing.camera.PlanarYUVLuminanceSource;
+
+import java.util.Hashtable;
+
+final class DecodeHandler extends Handler {
+
+    private static final String TAG = DecodeHandler.class.getSimpleName();
+
+    private final CaptureFragment fragment;
+    private final MultiFormatReader multiFormatReader;
+
+    DecodeHandler(CaptureFragment fragment, Hashtable<DecodeHintType, Object> hints) {
+        multiFormatReader = new MultiFormatReader();
+        multiFormatReader.setHints(hints);
+        this.fragment = fragment;
+    }
+
+    @Override
+    public void handleMessage(Message message) {
+        if (message.what == R.id.decode) {
+            decode((byte[]) message.obj, message.arg1, message.arg2);
+        } else if (message.what == R.id.quit) {
+            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) {
+        long start = System.currentTimeMillis();
+        Result rawResult = null;
+
+        //modify here
+        byte[] rotatedData = new byte[data.length];
+        for (int y = 0; y < height; y++) {
+            for (int x = 0; x < width; x++)
+                rotatedData[x * height + height - y - 1] = data[x + y * width];
+        }
+        int tmp = width; // Here we are swapping, that's the difference to #11
+        width = height;
+        height = tmp;
+
+        PlanarYUVLuminanceSource source = CameraManager.get().buildLuminanceSource(rotatedData, width, height);
+        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
+        try {
+            rawResult = multiFormatReader.decodeWithState(bitmap);
+        } catch (ReaderException re) {
+            // continue
+        } finally {
+            multiFormatReader.reset();
+        }
+
+        if (rawResult != null) {
+            long end = System.currentTimeMillis();
+            Log.d(TAG, "Found barcode (" + (end - start) + " ms):\n" + rawResult.toString());
+            Message message = Message.obtain(fragment.getHandler(), R.id.decode_succeeded, rawResult);
+            Bundle bundle = new Bundle();
+            bundle.putParcelable(DecodeThread.BARCODE_BITMAP, source.renderCroppedGreyscaleBitmap());
+            message.setData(bundle);
+            //Log.d(TAG, "Sending decode succeeded message...");
+            message.sendToTarget();
+        } else {
+            Message message = Message.obtain(fragment.getHandler(), R.id.decode_failed);
+            message.sendToTarget();
+        }
+    }
+
+}

+ 86 - 0
lib-zxing/src/main/java/com/uuzuche/lib_zxing/decoding/DecodeThread.java

@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2008 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.uuzuche.lib_zxing.decoding;
+
+import android.os.Handler;
+import android.os.Looper;
+
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.DecodeHintType;
+import com.google.zxing.ResultPointCallback;
+import com.uuzuche.lib_zxing.activity.CaptureFragment;
+
+import java.util.Hashtable;
+import java.util.Vector;
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * This thread does all the heavy lifting of decoding the images.
+ * �����߳�
+ */
+final class DecodeThread extends Thread {
+
+    public static final String BARCODE_BITMAP = "barcode_bitmap";
+    private final CaptureFragment fragment;
+    private final Hashtable<DecodeHintType, Object> hints;
+    private Handler handler;
+    private final CountDownLatch handlerInitLatch;
+
+    DecodeThread(CaptureFragment fragment,
+                 Vector<BarcodeFormat> decodeFormats,
+                 String characterSet,
+                 ResultPointCallback resultPointCallback) {
+
+        this.fragment = fragment;
+        handlerInitLatch = new CountDownLatch(1);
+
+        hints = new Hashtable<DecodeHintType, Object>(3);
+
+        if (decodeFormats == null || decodeFormats.isEmpty()) {
+            decodeFormats = new Vector<BarcodeFormat>();
+            decodeFormats.addAll(DecodeFormatManager.ONE_D_FORMATS);
+            decodeFormats.addAll(DecodeFormatManager.QR_CODE_FORMATS);
+            decodeFormats.addAll(DecodeFormatManager.DATA_MATRIX_FORMATS);
+        }
+
+        hints.put(DecodeHintType.POSSIBLE_FORMATS, decodeFormats);
+
+        if (characterSet != null) {
+            hints.put(DecodeHintType.CHARACTER_SET, characterSet);
+        }
+
+        hints.put(DecodeHintType.NEED_RESULT_POINT_CALLBACK, resultPointCallback);
+    }
+
+    Handler getHandler() {
+        try {
+            handlerInitLatch.await();
+        } catch (InterruptedException ie) {
+            // continue?
+        }
+        return handler;
+    }
+
+    @Override
+    public void run() {
+        Looper.prepare();
+        handler = new DecodeHandler(fragment, hints);
+        handlerInitLatch.countDown();
+        Looper.loop();
+    }
+
+}

+ 46 - 0
lib-zxing/src/main/java/com/uuzuche/lib_zxing/decoding/FinishListener.java

@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2010 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.uuzuche.lib_zxing.decoding;
+
+import android.app.Activity;
+import android.content.DialogInterface;
+
+/**
+ * Simple listener used to exit the app in a few cases.
+ */
+public final class FinishListener
+        implements DialogInterface.OnClickListener, DialogInterface.OnCancelListener, Runnable {
+
+    private final Activity activityToFinish;
+
+    public FinishListener(Activity activityToFinish) {
+        this.activityToFinish = activityToFinish;
+    }
+
+    public void onCancel(DialogInterface dialogInterface) {
+        run();
+    }
+
+    public void onClick(DialogInterface dialogInterface, int i) {
+        run();
+    }
+
+    public void run() {
+        activityToFinish.finish();
+    }
+
+}

+ 71 - 0
lib-zxing/src/main/java/com/uuzuche/lib_zxing/decoding/InactivityTimer.java

@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2010 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.uuzuche.lib_zxing.decoding;
+
+import android.app.Activity;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Finishes an activity after a period of inactivity.
+ */
+public final class InactivityTimer {
+
+    private static final int INACTIVITY_DELAY_SECONDS = 5 * 60;
+
+    private final ScheduledExecutorService inactivityTimer =
+            Executors.newSingleThreadScheduledExecutor(new DaemonThreadFactory());
+    private final Activity activity;
+    private ScheduledFuture<?> inactivityFuture = null;
+
+    public InactivityTimer(Activity activity) {
+        this.activity = activity;
+        onActivity();
+    }
+
+    public void onActivity() {
+        cancel();
+        inactivityFuture = inactivityTimer.schedule(new FinishListener(activity),
+                INACTIVITY_DELAY_SECONDS,
+                TimeUnit.SECONDS);
+    }
+
+    private void cancel() {
+        if (inactivityFuture != null) {
+            inactivityFuture.cancel(true);
+            inactivityFuture = null;
+        }
+    }
+
+    public void shutdown() {
+        cancel();
+        inactivityTimer.shutdown();
+    }
+
+    private static final class DaemonThreadFactory implements ThreadFactory {
+        public Thread newThread(Runnable runnable) {
+            Thread thread = new Thread(runnable);
+            thread.setDaemon(true);
+            return thread;
+        }
+    }
+
+}

+ 190 - 0
lib-zxing/src/main/java/com/uuzuche/lib_zxing/decoding/Intents.java

@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2008 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.uuzuche.lib_zxing.decoding;
+
+/**
+ * This class provides the constants to use when sending an Intent to Barcode Scanner.
+ * These strings are effectively API and cannot be changed.
+ */
+public final class Intents {
+    private Intents() {
+    }
+
+    public static final class Scan {
+        /**
+         * Send this intent to open the Barcodes app in scanning mode, find a barcode, and return
+         * the results.
+         */
+        public static final String ACTION = "com.google.zxing.client.android.SCAN";
+
+        /**
+         * By default, sending Scan.ACTION will decode all barcodes that we understand. However it
+         * may be useful to limit scanning to certain formats. Use Intent.putExtra(MODE, value) with
+         * one of the values below ({@link #PRODUCT_MODE}, {@link #ONE_D_MODE}, {@link #QR_CODE_MODE}).
+         * Optional.
+         * <p>
+         * Setting this is effectively shorthnad for setting explicit formats with {@link #SCAN_FORMATS}.
+         * It is overridden by that setting.
+         */
+        public static final String MODE = "SCAN_MODE";
+
+        /**
+         * Comma-separated list of formats to scan for. The values must match the names of
+         * {@link com.google.zxing.BarcodeFormat}s, such as {@link com.google.zxing.BarcodeFormat#EAN_13}.
+         * Example: "EAN_13,EAN_8,QR_CODE"
+         * <p>
+         * This overrides {@link #MODE}.
+         */
+        public static final String SCAN_FORMATS = "SCAN_FORMATS";
+
+        /**
+         * @see com.google.zxing.DecodeHintType#CHARACTER_SET
+         */
+        public static final String CHARACTER_SET = "CHARACTER_SET";
+
+        /**
+         * Decode only UPC and EAN barcodes. This is the right choice for shopping apps which get
+         * prices, reviews, etc. for products.
+         */
+        public static final String PRODUCT_MODE = "PRODUCT_MODE";
+
+        /**
+         * Decode only 1D barcodes (currently UPC, EAN, Code 39, and Code 128).
+         */
+        public static final String ONE_D_MODE = "ONE_D_MODE";
+
+        /**
+         * Decode only QR codes.
+         */
+        public static final String QR_CODE_MODE = "QR_CODE_MODE";
+
+        /**
+         * Decode only Data Matrix codes.
+         */
+        public static final String DATA_MATRIX_MODE = "DATA_MATRIX_MODE";
+
+        /**
+         * If a barcode is found, Barcodes returns RESULT_OK to onActivityResult() of the app which
+         * requested the scan via startSubActivity(). The barcodes contents can be retrieved with
+         * intent.getStringExtra(RESULT). If the user presses Back, the result code will be
+         * RESULT_CANCELED.
+         */
+        public static final String RESULT = "SCAN_RESULT";
+
+        /**
+         * Call intent.getStringExtra(RESULT_FORMAT) to determine which barcode format was found.
+         * See Contents.Format for possible values.
+         */
+        public static final String RESULT_FORMAT = "SCAN_RESULT_FORMAT";
+
+        /**
+         * Setting this to false will not save scanned codes in the history.
+         */
+        public static final String SAVE_HISTORY = "SAVE_HISTORY";
+
+        private Scan() {
+        }
+    }
+
+    public static final class Encode {
+        /**
+         * Send this intent to encode a piece of data as a QR code and display it full screen, so
+         * that another person can scan the barcode from your screen.
+         */
+        public static final String ACTION = "com.google.zxing.client.android.ENCODE";
+
+        /**
+         * The data to encode. Use Intent.putExtra(DATA, data) where data is either a String or a
+         * Bundle, depending on the type and format specified. Non-QR Code formats should
+         * just use a String here. For QR Code, see Contents for details.
+         */
+        public static final String DATA = "ENCODE_DATA";
+
+        /**
+         * The type of data being supplied if the format is QR Code. Use
+         * Intent.putExtra(TYPE, type) with one of Contents.Type.
+         */
+        public static final String TYPE = "ENCODE_TYPE";
+
+        /**
+         * The barcode format to be displayed. If this isn't specified or is blank,
+         * it defaults to QR Code. Use Intent.putExtra(FORMAT, format), where
+         * format is one of Contents.Format.
+         */
+        public static final String FORMAT = "ENCODE_FORMAT";
+
+        private Encode() {
+        }
+    }
+
+    public static final class SearchBookContents {
+        /**
+         * Use Google Book Search to search the contents of the book provided.
+         */
+        public static final String ACTION = "com.google.zxing.client.android.SEARCH_BOOK_CONTENTS";
+
+        /**
+         * The book to search, identified by ISBN number.
+         */
+        public static final String ISBN = "ISBN";
+
+        /**
+         * An optional field which is the text to search for.
+         */
+        public static final String QUERY = "QUERY";
+
+        private SearchBookContents() {
+        }
+    }
+
+    public static final class WifiConnect {
+        /**
+         * Internal intent used to trigger connection to a wi-fi network.
+         */
+        public static final String ACTION = "com.google.zxing.client.android.WIFI_CONNECT";
+
+        /**
+         * The network to connect to, all the configuration provided here.
+         */
+        public static final String SSID = "SSID";
+
+        /**
+         * The network to connect to, all the configuration provided here.
+         */
+        public static final String TYPE = "TYPE";
+
+        /**
+         * The network to connect to, all the configuration provided here.
+         */
+        public static final String PASSWORD = "PASSWORD";
+
+        private WifiConnect() {
+        }
+    }
+
+
+    public static final class Share {
+        /**
+         * Give the user a choice of items to encode as a barcode, then render it as a QR Code and
+         * display onscreen for a friend to scan with their phone.
+         */
+        public static final String ACTION = "com.google.zxing.client.android.SHARE";
+
+        private Share() {
+        }
+    }
+}

+ 40 - 0
lib-zxing/src/main/java/com/uuzuche/lib_zxing/encoding/EncodingHandler.java

@@ -0,0 +1,40 @@
+package com.uuzuche.lib_zxing.encoding;
+
+import android.graphics.Bitmap;
+
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.EncodeHintType;
+import com.google.zxing.MultiFormatWriter;
+import com.google.zxing.WriterException;
+import com.google.zxing.common.BitMatrix;
+
+import java.util.Hashtable;
+
+/**
+ * @author Ryan Tang
+ */
+public final class EncodingHandler {
+    private static final int BLACK = 0xff000000;
+
+    public static Bitmap createQRCode(String str, int widthAndHeight) throws WriterException {
+        Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>();
+        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
+        BitMatrix matrix = new MultiFormatWriter().encode(str,
+                BarcodeFormat.QR_CODE, widthAndHeight, widthAndHeight);
+        int width = matrix.getWidth();
+        int height = matrix.getHeight();
+        int[] pixels = new int[width * height];
+
+        for (int y = 0; y < height; y++) {
+            for (int x = 0; x < width; x++) {
+                if (matrix.get(x, y)) {
+                    pixels[y * width + x] = BLACK;
+                }
+            }
+        }
+        Bitmap bitmap = Bitmap.createBitmap(width, height,
+                Bitmap.Config.ARGB_8888);
+        bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
+        return bitmap;
+    }
+}

+ 34 - 0
lib-zxing/src/main/java/com/uuzuche/lib_zxing/view/ViewfinderResultPointCallback.java

@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2009 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.uuzuche.lib_zxing.view;
+
+import com.google.zxing.ResultPoint;
+import com.google.zxing.ResultPointCallback;
+
+public final class ViewfinderResultPointCallback implements ResultPointCallback {
+
+    private final ViewfinderView viewfinderView;
+
+    public ViewfinderResultPointCallback(ViewfinderView viewfinderView) {
+        this.viewfinderView = viewfinderView;
+    }
+
+    public void foundPossibleResultPoint(ResultPoint point) {
+        viewfinderView.addPossibleResultPoint(point);
+    }
+
+}

+ 262 - 0
lib-zxing/src/main/java/com/uuzuche/lib_zxing/view/ViewfinderView.java

@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2008 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.uuzuche.lib_zxing.view;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.View;
+
+import com.google.zxing.ResultPoint;
+import com.uuzuche.lib_zxing.DisplayUtil;
+import com.uuzuche.lib_zxing.R;
+import com.uuzuche.lib_zxing.camera.CameraManager;
+
+import java.util.Collection;
+import java.util.HashSet;
+
+/**
+ * 自定义组件实现,扫描功能
+ */
+public final class ViewfinderView extends View {
+
+    private static final long ANIMATION_DELAY = 100L;
+    private static final int OPAQUE = 0xFF;
+
+    private final Paint paint;
+    private Bitmap resultBitmap;
+    private final int maskColor;
+    private final int resultColor;
+    private final int resultPointColor;
+    private Collection<ResultPoint> possibleResultPoints;
+    private Collection<ResultPoint> lastPossibleResultPoints;
+
+    public ViewfinderView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+
+        paint = new Paint();
+        Resources resources = getResources();
+        maskColor = resources.getColor(R.color.viewfinder_mask);
+        resultColor = resources.getColor(R.color.result_view);
+        resultPointColor = resources.getColor(R.color.possible_result_points);
+        possibleResultPoints = new HashSet<ResultPoint>(5);
+
+        scanLight = BitmapFactory.decodeResource(resources,
+                R.drawable.scan_light);
+
+        initInnerRect(context, attrs);
+    }
+
+    /**
+     * 初始化内部框的大小
+     * @param context
+     * @param attrs
+     */
+    private void initInnerRect(Context context, AttributeSet attrs) {
+        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.innerrect);
+
+        // 扫描框距离顶部
+        float innerMarginTop = ta.getDimension(R.styleable.innerrect_inner_margintop, -1);
+        if (innerMarginTop != -1) {
+            CameraManager.FRAME_MARGINTOP = (int) innerMarginTop;
+        }
+
+        // 扫描框的宽度
+        CameraManager.FRAME_WIDTH = (int) ta.getDimension(R.styleable.innerrect_inner_width, DisplayUtil.screenWidthPx / 2);
+
+        // 扫描框的高度
+        CameraManager.FRAME_HEIGHT = (int) ta.getDimension(R.styleable.innerrect_inner_height, DisplayUtil.screenWidthPx / 2);
+
+        // 扫描框边角颜色
+        innercornercolor = ta.getColor(R.styleable.innerrect_inner_corner_color, Color.parseColor("#45DDDD"));
+        // 扫描框边角长度
+        innercornerlength = (int) ta.getDimension(R.styleable.innerrect_inner_corner_length, 65);
+        // 扫描框边角宽度
+        innercornerwidth = (int) ta.getDimension(R.styleable.innerrect_inner_corner_width, 15);
+
+        // 扫描bitmap
+        Drawable drawable = ta.getDrawable(R.styleable.innerrect_inner_scan_bitmap);
+        if (drawable != null) {
+        }
+
+        // 扫描控件
+        scanLight = BitmapFactory.decodeResource(getResources(), ta.getResourceId(R.styleable.innerrect_inner_scan_bitmap, R.drawable.scan_light));
+        // 扫描速度
+        SCAN_VELOCITY = ta.getInt(R.styleable.innerrect_inner_scan_speed, 5);
+
+        ta.recycle();
+    }
+
+    @Override
+    public void onDraw(Canvas canvas) {
+        Rect frame = CameraManager.get().getFramingRect();
+        if (frame == null) {
+            return;
+        }
+        int width = canvas.getWidth();
+        int height = canvas.getHeight();
+
+        // Draw the exterior (i.e. outside the framing rect) darkened
+        paint.setColor(resultBitmap != null ? resultColor : maskColor);
+        canvas.drawRect(0, 0, width, frame.top, paint);
+        canvas.drawRect(0, frame.top, frame.left, frame.bottom + 1, paint);
+        canvas.drawRect(frame.right + 1, frame.top, width, frame.bottom + 1, paint);
+        canvas.drawRect(0, frame.bottom + 1, width, height, paint);
+
+        if (resultBitmap != null) {
+            // Draw the opaque result bitmap over the scanning rectangle
+            paint.setAlpha(OPAQUE);
+            canvas.drawBitmap(resultBitmap, frame.left, frame.top, paint);
+        } else {
+
+            drawFrameBounds(canvas, frame);
+
+            drawScanLight(canvas, frame);
+
+            Collection<ResultPoint> currentPossible = possibleResultPoints;
+            Collection<ResultPoint> currentLast = lastPossibleResultPoints;
+            if (currentPossible.isEmpty()) {
+                lastPossibleResultPoints = null;
+            } else {
+                possibleResultPoints = new HashSet<ResultPoint>(5);
+                lastPossibleResultPoints = currentPossible;
+                paint.setAlpha(OPAQUE);
+                paint.setColor(resultPointColor);
+                for (ResultPoint point : currentPossible) {
+                    canvas.drawCircle(frame.left + point.getX(), frame.top + point.getY(), 6.0f, paint);
+                }
+            }
+            if (currentLast != null) {
+                paint.setAlpha(OPAQUE / 2);
+                paint.setColor(resultPointColor);
+                for (ResultPoint point : currentLast) {
+                    canvas.drawCircle(frame.left + point.getX(), frame.top + point.getY(), 3.0f, paint);
+                }
+            }
+
+            postInvalidateDelayed(ANIMATION_DELAY, frame.left, frame.top, frame.right, frame.bottom);
+        }
+    }
+
+    // 扫描线移动的y
+    private int scanLineTop;
+    // 扫描线移动速度
+    private int SCAN_VELOCITY;
+    // 扫描线
+    Bitmap scanLight;
+
+    /**
+     * 绘制移动扫描线
+     *
+     * @param canvas
+     * @param frame
+     */
+    private void drawScanLight(Canvas canvas, Rect frame) {
+
+        if (scanLineTop == 0) {
+            scanLineTop = frame.top;
+        }
+
+        if (scanLineTop >= frame.bottom - 30) {
+            scanLineTop = frame.top;
+        } else {
+            scanLineTop += SCAN_VELOCITY;
+        }
+        Rect scanRect = new Rect(frame.left, scanLineTop, frame.right,
+                scanLineTop + 30);
+        canvas.drawBitmap(scanLight, null, scanRect, paint);
+    }
+
+
+    // 扫描框边角颜色
+    private int innercornercolor;
+    // 扫描框边角长度
+    private int innercornerlength;
+    // 扫描框边角宽度
+    private int innercornerwidth;
+
+    /**
+     * 绘制取景框边框
+     *
+     * @param canvas
+     * @param frame
+     */
+    private void drawFrameBounds(Canvas canvas, Rect frame) {
+
+        /*paint.setColor(Color.WHITE);
+        paint.setStrokeWidth(2);
+        paint.setStyle(Paint.Style.STROKE);
+
+        canvas.drawRect(frame, paint);*/
+
+        paint.setColor(innercornercolor);
+        paint.setStyle(Paint.Style.FILL);
+
+        int corWidth = innercornerwidth;
+        int corLength = innercornerlength;
+
+        // 左上角
+        canvas.drawRect(frame.left, frame.top, frame.left + corWidth, frame.top
+                + corLength, paint);
+        canvas.drawRect(frame.left, frame.top, frame.left
+                + corLength, frame.top + corWidth, paint);
+        // 右上角
+        canvas.drawRect(frame.right - corWidth, frame.top, frame.right,
+                frame.top + corLength, paint);
+        canvas.drawRect(frame.right - corLength, frame.top,
+                frame.right, frame.top + corWidth, paint);
+        // 左下角
+        canvas.drawRect(frame.left, frame.bottom - corLength,
+                frame.left + corWidth, frame.bottom, paint);
+        canvas.drawRect(frame.left, frame.bottom - corWidth, frame.left
+                + corLength, frame.bottom, paint);
+        // 右下角
+        canvas.drawRect(frame.right - corWidth, frame.bottom - corLength,
+                frame.right, frame.bottom, paint);
+        canvas.drawRect(frame.right - corLength, frame.bottom - corWidth,
+                frame.right, frame.bottom, paint);
+    }
+
+
+    public void drawViewfinder() {
+        resultBitmap = null;
+        invalidate();
+    }
+
+    public void addPossibleResultPoint(ResultPoint point) {
+        possibleResultPoints.add(point);
+    }
+
+
+    /**
+     * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
+     */
+    public static int dip2px(Context context, float dpValue) {
+        final float scale = context.getResources().getDisplayMetrics().density;
+        return (int) (dpValue * scale + 0.5f);
+    }
+
+
+}

BIN
lib-zxing/src/main/res/drawable/scan_light.png


+ 11 - 0
lib-zxing/src/main/res/layout/camera.xml

@@ -0,0 +1,11 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <FrameLayout
+        android:id="@+id/fl_zxing_container"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+
+</RelativeLayout>

+ 61 - 0
lib-zxing/src/main/res/layout/fragment_capture.xml

@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:innerrect="http://schemas.android.com/apk/res-auto"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    >
+
+    <FrameLayout
+        android:id="@+id/scan_fl"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerInParent="true">
+        <SurfaceView
+            android:id="@+id/preview_view"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"/>
+
+        <com.uuzuche.lib_zxing.view.ViewfinderView
+            android:id="@+id/viewfinder_view"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            innerrect:inner_width="230dp"
+            innerrect:inner_height="230dp"
+            innerrect:inner_scan_speed="20"/>
+    </FrameLayout>
+<!--
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/scan_fl"
+        android:text="将二维码/条码置于扫描框内,即可自动扫描"
+        android:textSize="18sp"
+        android:layout_centerHorizontal="true"
+        android:textColor="#ffffff"/>-->
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="60dp"
+        android:background="@color/transparent"
+        android:padding="10dp">
+        <TextView
+            android:id="@+id/back_tv"
+            android:layout_width="wrap_content"
+            android:layout_height="40dp"
+            android:text="取消"
+            android:textSize="20sp"
+            android:layout_marginLeft="5dp"
+            android:textColor="#FF8200"
+            android:gravity="center"/>
+        <!--<ImageView
+            android:id="@+id/qrcode_iv"
+            android:layout_width="30dp"
+            android:layout_height="30dp"
+            android:layout_alignParentRight="true"
+            android:src="@drawable/scan_light"
+            android:layout_marginRight="5dp"/>-->
+
+    </RelativeLayout>
+
+</RelativeLayout>

BIN
lib-zxing/src/main/res/raw/beep.ogg


+ 15 - 0
lib-zxing/src/main/res/values/attrs.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <declare-styleable name="innerrect">
+        <attr name="inner_width" format="dimension"/>
+        <attr name="inner_height" format="dimension"/>
+        <attr name="inner_margintop" format="dimension" />
+        <attr name="inner_corner_color" format="color" />
+        <attr name="inner_corner_length" format="dimension" />
+        <attr name="inner_corner_width" format="dimension" />
+        <attr name="inner_scan_bitmap" format="reference" />
+        <attr name="inner_scan_speed" format="integer" />
+    </declare-styleable>
+
+</resources>

+ 33 - 0
lib-zxing/src/main/res/values/colors.xml

@@ -0,0 +1,33 @@
+<resources>
+
+    <color name="cc">#59a9ff</color>
+
+    <color name="bg_color">#EDEDED</color>
+    <color name="contents_text">#ff000000</color>
+    <color name="encode_view">#ffffffff</color>
+    <color name="help_button_view">#ffcccccc</color>
+    <color name="help_view">#ff404040</color>
+    <color name="possible_result_points">#c0ffff00</color>
+    <color name="result_image_border">#ffffffff</color>
+    <color name="result_minor_text">#ffc0c0c0</color>
+    <color name="result_points">#c000ff00</color>
+    <color name="result_text">#ffffffff</color>
+    <color name="result_view">#b0000000</color>
+    <color name="sbc_header_text">#ff808080</color>
+    <color name="sbc_header_view">#ffffffff</color>
+    <color name="sbc_list_item">#fffff0e0</color>
+    <color name="sbc_layout_view">#ffffffff</color>
+    <color name="sbc_page_number_text">#ff000000</color>
+    <color name="sbc_snippet_text">#ff4b4b4b</color>
+    <color name="share_text">#ff000000</color>
+    <color name="share_view">#ffffffff</color>
+    <color name="status_view">#50000000</color>
+    <color name="status_text">#ffffffff</color>
+    <color name="transparent">#00000000</color>
+    <color name="viewfinder_frame">#ff000000</color>
+    <color name="viewfinder_laser">#ffff0000</color>
+    <color name="viewfinder_mask">#60000000</color>
+    <color name="header">#58567D</color>
+    <color name="grgray">#686868</color>
+
+</resources>

+ 31 - 0
lib-zxing/src/main/res/values/ids.xml

@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2008 ZXing authors
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<resources>
+  <!-- Messages IDs -->
+  <item type="id" name="auto_focus"/>
+  <item type="id" name="decode"/>
+  <item type="id" name="decode_failed"/>
+  <item type="id" name="decode_succeeded"/>
+  <item type="id" name="encode_failed"/>
+  <item type="id" name="encode_succeeded"/>
+  <item type="id" name="launch_product_query"/>
+  <item type="id" name="quit"/>
+  <item type="id" name="restart_preview"/>
+  <item type="id" name="return_scan_result"/>
+  <item type="id" name="search_book_contents_failed"/>
+  <item type="id" name="search_book_contents_succeeded"/>
+</resources>

+ 6 - 0
lib-zxing/src/main/res/values/strings.xml

@@ -0,0 +1,6 @@
+<resources>
+    <string name="app_name">Lib-zxing</string>
+
+    <!-- TODO: Remove or change this placeholder text -->
+    <string name="hello_blank_fragment">Hello blank fragment</string>
+</resources>

+ 17 - 0
lib-zxing/src/main/res/values/styles.xml

@@ -0,0 +1,17 @@
+<resources xmlns:tools="http://schemas.android.com/tools">
+
+    <!-- Base application theme. -->
+    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
+        <!-- Customize your theme here. -->
+    </style>
+
+    <style name="AppBaseTheme" parent="Theme.AppCompat.Light">
+        <!-- API 14 theme customizations can go here. -->
+        <item name="android:actionBarStyle">@style/my_actionbar_style</item>
+    </style>
+
+    <style name="my_actionbar_style" parent="@android:style/Widget.Holo.Light.ActionBar">
+        <item name="android:background">#FFFFFF</item>
+    </style>
+
+</resources>

+ 17 - 0
lib-zxing/src/test/java/com/uuzuche/lib_zxing/ExampleUnitTest.java

@@ -0,0 +1,17 @@
+package com.uuzuche.lib_zxing;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+public class ExampleUnitTest {
+    @Test
+    public void addition_isCorrect() throws Exception {
+        assertEquals(4, 2 + 2);
+    }
+}

+ 1 - 1
settings.gradle

@@ -1,2 +1,2 @@
-include ':pullToRefershLibraryMy', ':materialdialogs', ':MPAndroidChart', ':libedittextformlibrary', ':libfloatingactionbutton', ':libbdupdatesdk', ':library-viewpager-indicator', ':library-swipemenu_lv'
+include ':pullToRefershLibraryMy', ':materialdialogs', ':MPAndroidChart', ':libedittextformlibrary', ':libfloatingactionbutton', ':libbdupdatesdk', ':library-viewpager-indicator', ':library-swipemenu_lv', ':lib-zxing'
 include ':WeiChat'