解决安卓扫码问题
diff --git a/platforms/android/CordovaLib/AndroidManifest.xml b/platforms/android/CordovaLib/AndroidManifest.xml
index 1625b89..320c253 100755
--- a/platforms/android/CordovaLib/AndroidManifest.xml
+++ b/platforms/android/CordovaLib/AndroidManifest.xml
@@ -19,5 +19,4 @@
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
       package="org.apache.cordova" android:versionName="1.0" android:versionCode="1">
-    <uses-sdk android:minSdkVersion="19" />
 </manifest>
diff --git a/platforms/android/CordovaLib/CordovaLib.iml b/platforms/android/CordovaLib/CordovaLib.iml
index b80b08f..da4f936 100644
--- a/platforms/android/CordovaLib/CordovaLib.iml
+++ b/platforms/android/CordovaLib/CordovaLib.iml
@@ -15,6 +15,7 @@
           <task>generateDebugSources</task>
         </afterSyncTasks>
         <option name="ALLOW_USER_CONFIGURATION" value="false" />
+        <option name="RES_FOLDERS_RELATIVE_PATH" value="" />
         <option name="PROJECT_TYPE" value="1" />
       </configuration>
     </facet>
diff --git a/platforms/android/android.json b/platforms/android/android.json
index 6103bb9..f654e07 100644
--- a/platforms/android/android.json
+++ b/platforms/android/android.json
@@ -55,6 +55,10 @@
             {
               "xml": "<feature name=\"JPushPlugin\"><param name=\"android-package\" value=\"cn.jiguang.cordova.push.JPushPlugin\" /></feature>",
               "count": 1
+            },
+            {
+              "xml": "<feature name=\"AppVersion\"><param name=\"android-package\" value=\"uk.co.whiteoctober.cordova.AppVersion\" /></feature>",
+              "count": 1
             }
           ]
         }
@@ -221,7 +225,7 @@
               "count": 1
             },
             {
-              "xml": "<meta-data android:name=\"JPUSH_APPKEY\" android:value=\"your_jpush_appkey\" />",
+              "xml": "<meta-data android:name=\"JPUSH_APPKEY\" android:value=\"d644d997f2cab0551ff704a3\" />",
               "count": 1
             }
           ]
@@ -236,6 +240,14 @@
               "mode": "merge",
               "id": "config.xml"
             }
+          ],
+          "NSPhotoLibraryUsageDescription": [
+            {
+              "xml": "<string>APP需要使用您的相册权限,没有该权限将无法完成扫一扫功能</string>",
+              "count": 1,
+              "mode": "merge",
+              "id": "config.xml"
+            }
           ]
         }
       }
@@ -286,9 +298,15 @@
       "PACKAGE_NAME": "com.supwisdom.dlapp"
     },
     "jpush-phonegap-plugin": {
-      "APP_KEY": "your_jpush_appkey",
+      "APP_KEY": "d644d997f2cab0551ff704a3",
       "CHANNEL": "developer-default",
       "PACKAGE_NAME": "com.supwisdom.dlapp"
+    },
+    "cordova-plugin-app-version": {
+      "PACKAGE_NAME": "com.supwisdom.dlapp"
+    },
+    "cordova-plugin-wkwebview-engine": {
+      "PACKAGE_NAME": "com.dalicitycard.app"
     }
   },
   "dependent_plugins": {},
@@ -620,6 +638,14 @@
       "clobbers": [
         "JPush"
       ]
+    },
+    {
+      "id": "cordova-plugin-app-version.AppVersionPlugin",
+      "file": "plugins/cordova-plugin-app-version/www/AppVersionPlugin.js",
+      "pluginId": "cordova-plugin-app-version",
+      "clobbers": [
+        "cordova.getAppVersion"
+      ]
     }
   ],
   "plugin_metadata": {
@@ -637,6 +663,8 @@
     "cordova-plugin-device": "2.0.2",
     "cordova-plugin-themeablebrowser": "0.2.17",
     "cordova-plugin-jcore": "1.3.0",
-    "jpush-phonegap-plugin": "3.7.2"
+    "jpush-phonegap-plugin": "3.7.2",
+    "cordova-plugin-app-version": "0.1.9",
+    "cordova-plugin-wkwebview-engine": "1.2.1"
   }
 }
diff --git a/platforms/android/app/app.iml b/platforms/android/app/app.iml
index 2f4beb8..f1a0fda 100644
--- a/platforms/android/app/app.iml
+++ b/platforms/android/app/app.iml
@@ -17,6 +17,7 @@
         <option name="ALLOW_USER_CONFIGURATION" value="false" />
         <option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
         <option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
+        <option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" />
         <option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
       </configuration>
     </facet>
@@ -81,6 +82,7 @@
       <sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
       <sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
       <sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" />
+      <excludeFolder url="file://$MODULE_DIR$/build/.DS_Store" />
       <excludeFolder url="file://$MODULE_DIR$/build/intermediates/annotation_processor_list" />
       <excludeFolder url="file://$MODULE_DIR$/build/intermediates/apk_list" />
       <excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
@@ -106,6 +108,7 @@
       <excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
       <excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" />
       <excludeFolder url="file://$MODULE_DIR$/build/outputs" />
+      <excludeFolder url="file://$MODULE_DIR$/build/reports" />
       <excludeFolder url="file://$MODULE_DIR$/build/tmp" />
     </content>
     <orderEntry type="jdk" jdkName="Android API 24 Platform" jdkType="Android SDK" />
@@ -113,6 +116,8 @@
     <orderEntry type="library" name="Gradle: com.android.support:support-annotations:24.1.1@jar" level="project" />
     <orderEntry type="library" name="Gradle: com.squareup.okio:okio:1.14.0@jar" level="project" />
     <orderEntry type="library" name="Gradle: com.google.zxing:core:3.2.1@jar" level="project" />
+    <orderEntry type="library" name="Gradle: __local_aars__:/Users/shuwei/works2/cordova/dlapp/platforms/android/app/libs/jcore-android-2.1.2.jar:unspecified@jar" level="project" />
+    <orderEntry type="library" name="Gradle: __local_aars__:/Users/shuwei/works2/cordova/dlapp/platforms/android/app/libs/jpush-android-3.3.4.jar:unspecified@jar" level="project" />
     <orderEntry type="library" name="Gradle: com.journeyapps:zxing-android-embedded-3.3.0" level="project" />
     <orderEntry type="library" name="Gradle: com.squareup.okhttp3:okhttp-urlconnection:3.10.0@jar" level="project" />
     <orderEntry type="library" name="Gradle: com.android.support:appcompat-v7-23.1.0" level="project" />
diff --git a/platforms/android/app/build.gradle b/platforms/android/app/build.gradle
index 3ce2e04..26cd3f9 100644
--- a/platforms/android/app/build.gradle
+++ b/platforms/android/app/build.gradle
@@ -165,80 +165,37 @@
 
 android {
     defaultConfig {
-        versionCode cdvVersionCode ?: new BigInteger("" + privateHelpers.extractIntFromManifest("versionCode"))
         applicationId privateHelpers.extractStringFromManifest("package")
-
         if (cdvMinSdkVersion != null) {
             minSdkVersion cdvMinSdkVersion
         }
+        minSdkVersion 19
+        ndk {
+            abiFilters "armeabi"
+        }
     }
-
     lintOptions {
-      abortOnError false;
+        abortOnError false;
     }
-
     compileSdkVersion 24
     buildToolsVersion '28.0.3'
-
     // This code exists for Crosswalk and other Native APIs.
     // By default, we multiply the existing version code in the
     // Android Manifest by 10 and add a number for each architecture.
     // If you are not using Crosswalk or SQLite, you can
     // ignore this chunk of code, and your version codes will be respected.
 
-    if (Boolean.valueOf(cdvBuildMultipleApks)) {
-        flavorDimensions "default"
-
-        productFlavors {
-            armeabi {
-                versionCode defaultConfig.versionCode*10 + 1
-                ndk {
-                    abiFilters = ["armeabi"]
-                }
-            }
-            armv7 {
-                versionCode defaultConfig.versionCode*10 + 2
-                ndk {
-                    abiFilters = ["armeabi-v7a"]
-                }
-            }
-            arm64 {
-                versionCode defaultConfig.versionCode*10 + 3
-                ndk {
-                    abiFilters = ["arm64-v8a"]
-                }
-            }
-            x86 {
-                versionCode defaultConfig.versionCode*10 + 4
-                ndk {
-                    abiFilters = ["x86"]
-                }
-            }
-            x86_64 {
-                versionCode defaultConfig.versionCode*10 + 5
-                ndk {
-                    abiFilters = ["x86_64"]
-                }
-            }
-        }
-    } else if (Boolean.valueOf(cdvVersionCodeForceAbiDigit)) {
-        // This provides compatibility to the default logic for versionCode before cordova-android 5.2.0
-        defaultConfig {
-            versionCode defaultConfig.versionCode*10
-        }
-    }
-
     compileOptions {
         sourceCompatibility JavaVersion.VERSION_1_8
         targetCompatibility JavaVersion.VERSION_1_8
     }
-
     if (cdvReleaseSigningPropertiesFile) {
         signingConfigs {
             release {
                 // These must be set or Gradle will complain (even if they are overridden).
                 keyAlias = ""
-                keyPassword = "__unset" // And these must be set to non-empty in order to have the signing step added to the task graph.
+                keyPassword = "__unset"
+                // And these must be set to non-empty in order to have the signing step added to the task graph.
                 storeFile = null
                 storePassword = "__unset"
             }
@@ -250,10 +207,11 @@
         }
         addSigningProps(cdvReleaseSigningPropertiesFile, signingConfigs.release)
     }
-
     if (cdvDebugSigningPropertiesFile) {
         addSigningProps(cdvDebugSigningPropertiesFile, signingConfigs.debug)
     }
+    productFlavors {
+    }
 }
 
 /*
@@ -266,9 +224,9 @@
 dependencies {
     implementation fileTree(include: '*.jar', dir: 'libs')
     // SUB-PROJECT DEPENDENCIES START
-    implementation(project(path: ":CordovaLib"))
-    implementation "com.squareup.okhttp3:okhttp-urlconnection:3.10.0"
-    implementation "com.android.support:support-v4:24.1.1+"
+    implementation project(path: ':CordovaLib')
+    implementation 'com.squareup.okhttp3:okhttp-urlconnection:3.10.0'
+    implementation 'com.android.support:support-v4:24.1.1+'
     // SUB-PROJECT DEPENDENCIES END
 }
 
diff --git a/platforms/android/app/release/app-release.apk b/platforms/android/app/release/app-release.apk
new file mode 100644
index 0000000..8664e26
--- /dev/null
+++ b/platforms/android/app/release/app-release.apk
Binary files differ
diff --git a/platforms/android/app/release/output.json b/platforms/android/app/release/output.json
new file mode 100644
index 0000000..6e993a2
--- /dev/null
+++ b/platforms/android/app/release/output.json
@@ -0,0 +1 @@
+[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":10004,"versionName":"1.0.4","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}]
\ No newline at end of file
diff --git a/platforms/android/app/src/main/AndroidManifest.xml b/platforms/android/app/src/main/AndroidManifest.xml
index 0bc45cf..823d9b5 100644
--- a/platforms/android/app/src/main/AndroidManifest.xml
+++ b/platforms/android/app/src/main/AndroidManifest.xml
@@ -1,5 +1,5 @@
 <?xml version='1.0' encoding='utf-8'?>
-<manifest android:hardwareAccelerated="true" android:versionCode="10000" android:versionName="1.0.0" package="com.supwisdom.dlapp" xmlns:android="http://schemas.android.com/apk/res/android">
+<manifest android:hardwareAccelerated="true" android:versionCode="10004" android:versionName="1.0.4" package="com.dalicitycard.app" xmlns:android="http://schemas.android.com/apk/res/android">
     <supports-screens android:anyDensity="true" android:largeScreens="true" android:normalScreens="true" android:resizeable="true" android:smallScreens="true" android:xlargeScreens="true" />
     <application android:hardwareAccelerated="true" android:icon="@mipmap/ic_launcher" android:label="@string/launcher_name" android:supportsRtl="true">
         <activity android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale" android:label="@string/activity_name" android:launchMode="singleTop" android:name="MainActivity" android:screenOrientation="portrait" android:theme="@android:style/Theme.DeviceDefault.NoActionBar" android:windowSoftInputMode="adjustResize">
@@ -79,9 +79,8 @@
             </intent-filter>
         </receiver>
         <meta-data android:name="JPUSH_CHANNEL" android:value="developer-default" />
-        <meta-data android:name="JPUSH_APPKEY" android:value="your_jpush_appkey" />
+        <meta-data android:name="JPUSH_APPKEY" android:value="d644d997f2cab0551ff704a3" />
     </application>
-    <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="28" />
     <uses-permission android:name="android.permission.USE_FINGERPRINT" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.CAMERA" android:required="false" />
@@ -93,7 +92,6 @@
     <uses-permission android:name="android.permission.RECEIVE_USER_PRESENT" />
     <uses-permission android:name="android.permission.READ_PHONE_STATE" />
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
-    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
     <uses-permission android:name="android.permission.VIBRATE" />
diff --git a/platforms/android/app/src/main/assets/www/billdetail.html b/platforms/android/app/src/main/assets/www/billdetail.html
index e419a98..8289dbf 100644
--- a/platforms/android/app/src/main/assets/www/billdetail.html
+++ b/platforms/android/app/src/main/assets/www/billdetail.html
@@ -16,7 +16,7 @@
 
 <body>
     <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
-        <a class="aui-pull-left" href="javascript:window.history.go(-1)">
+        <a class="aui-pull-left" href="javascript:app.toBack();">
             <span class="aui-iconfont aui-icon-left"></span>
         </a>
         <div class="aui-title">账单详情</div>
diff --git a/platforms/android/app/src/main/assets/www/cordova_plugins.js b/platforms/android/app/src/main/assets/www/cordova_plugins.js
index 595ecb1..ee6832d 100644
--- a/platforms/android/app/src/main/assets/www/cordova_plugins.js
+++ b/platforms/android/app/src/main/assets/www/cordova_plugins.js
@@ -327,6 +327,14 @@
       "clobbers": [
         "JPush"
       ]
+    },
+    {
+      "id": "cordova-plugin-app-version.AppVersionPlugin",
+      "file": "plugins/cordova-plugin-app-version/www/AppVersionPlugin.js",
+      "pluginId": "cordova-plugin-app-version",
+      "clobbers": [
+        "cordova.getAppVersion"
+      ]
     }
   ];
   module.exports.metadata = {
@@ -344,6 +352,8 @@
     "cordova-plugin-device": "2.0.2",
     "cordova-plugin-themeablebrowser": "0.2.17",
     "cordova-plugin-jcore": "1.3.0",
-    "jpush-phonegap-plugin": "3.7.2"
+    "jpush-phonegap-plugin": "3.7.2",
+    "cordova-plugin-app-version": "0.1.9",
+    "cordova-plugin-wkwebview-engine": "1.2.1"
   };
 });
\ No newline at end of file
diff --git a/platforms/android/app/src/main/assets/www/js/billdetail.js b/platforms/android/app/src/main/assets/www/js/billdetail.js
index 3615234..51579aa 100644
--- a/platforms/android/app/src/main/assets/www/js/billdetail.js
+++ b/platforms/android/app/src/main/assets/www/js/billdetail.js
@@ -9,7 +9,8 @@
         this.loadBill()
     },
     toBack: function (){
-        window.history.back();
+        //window.history.back();
+        window.history.go(-1)
     },
     loadBill: function() {
         var refno = window.localStorage.getItem("currentrefno");
diff --git a/platforms/android/app/src/main/assets/www/js/index.js b/platforms/android/app/src/main/assets/www/js/index.js
index 112a927..db3d7ce 100644
--- a/platforms/android/app/src/main/assets/www/js/index.js
+++ b/platforms/android/app/src/main/assets/www/js/index.js
@@ -34,15 +34,10 @@
                 console.log(ret)
                 if (ok) {
                     if(ret.code==200){
-                        var exp =  window.localStorage.getItem("tokenexpire");
-                        var t = parseInt(exp);
-                        //token 小于10分钟了,需要刷新
-                        console.log((ret.now-t))
-                        if(ret.now-t>1000*60*10){
-                             window.location = "login.html";
-                        }else{
-                             window.location = "main.html";
+                        if(!isEmpty(ret.token)){
+                             window.localStorage.setItem("token",ret.token); 
                         }
+                        window.location = "main.html";
                     }else{
                         window.location = "login.html";
                     }
diff --git a/platforms/android/app/src/main/assets/www/js/login.js b/platforms/android/app/src/main/assets/www/js/login.js
index 77b8b2a..7931a48 100644
--- a/platforms/android/app/src/main/assets/www/js/login.js
+++ b/platforms/android/app/src/main/assets/www/js/login.js
@@ -33,7 +33,8 @@
         $.showLoading("登录中");
         var param={
             "username":phone,
-            "password":pwd
+            "password":pwd,
+            "platform":device.platform
         }
         Login(param,function(ok,ret){
             console.log(ret)
@@ -47,6 +48,7 @@
                  window.localStorage.setItem("phone",phone); 
                  window.localStorage.setItem("phoneX",ret.phone);
                  window.localStorage.setItem("token",ret.token); 
+                 window.localStorage.setItem("uid",ret.uid); 
                  window.localStorage.setItem("tenantid",ret.tenantid); 
                  window.localStorage.setItem("tokenexpire",ret.expire); 
                  window.localStorage.setItem("tokentime",ret.now); 
diff --git a/platforms/android/app/src/main/assets/www/js/main.js b/platforms/android/app/src/main/assets/www/js/main.js
index 3b01a2a..da93b6c 100644
--- a/platforms/android/app/src/main/assets/www/js/main.js
+++ b/platforms/android/app/src/main/assets/www/js/main.js
@@ -4,11 +4,52 @@
     initialize: function() {
         this.initTab();
         document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
+        document.addEventListener('jpush.receiveRegistrationId', function(event) {
+             console.log(event.registrationId)
+        }, false)
+        document.addEventListener("jpush.openNotification", function (event) {
+          var refno
+          console.log("openNotify:"+event);
+          if(device.platform == "Android") {
+            refno = event.extras.refno
+          } else {
+            refno = event.refno
+            window.JPush.setApplicationIconBadgeNumber(0);
+          }
+          app.openBill(refno);
+          console.log("openNotify:"+refno);
+        }, false)
+    },
+    openBill:function(billno){
+        window.localStorage.setItem("currentrefno",billno);
+        window.location='billdetail.html';
+    },
+    initJpush: function() {
+        if(device.platform == "Android") {
+        } else {
+         window.JPush.setApplicationIconBadgeNumber(0);
+        }
+        window.JPush.init();
+        window.JPush.setDebugMode(true);
+        window.JPush.isPushStopped(function(result) {
+            if (result == 0) {
+                //window.JPush.resumePush();
+            } else {
+                window.JPush.resumePush();
+            }
+        });
+        window.JPush.getUserNotificationSettings(function(result) {
+          if(result == 0) {
+          } else if(result > 0) {
+          }
+         });
+        var uid = window.localStorage.getItem("uid");
+
     },
 
     onDeviceReady: function() {
         var uid = window.localStorage.getItem("token");
-        console.log(CURRENT_INDEX);
+        this.initJpush();
         $('#scanBtn').click(function() {
             //window.location = "scan.html";
             app.checkBefore(function() {
@@ -42,11 +83,12 @@
             })
         });
         $('#secBtn').click(function() {
-            app.checkBefore(function() {
+            window.location = "security.html";
+            /*app.checkBefore(function() {
                 app.checkOther(function() {
                     window.location = "security.html";
                 })
-            })
+            })*/
         });
         $('#usersec').click(function() {
             app.checkBefore(function() {
@@ -57,22 +99,23 @@
         });
         this.initData();
     },
-    initTab:function(){
+    initTab: function() {
         $("#maincontent").css("top", $("#maintop").height())
         var tab = new auiTab({
             element: document.getElementById("footer"),
         }, function(ret) {
-            window.localStorage.setItem("tabindex",ret.index); 
-            
+            window.localStorage.setItem("tabindex", ret.index);
+
             changeTab(ret.index);
         });
-        var tabindex =  window.localStorage.getItem("tabindex"); 
-        if(!tabindex||tabindex==0){
+        var tabindex = window.localStorage.getItem("tabindex");
+        if (!tabindex || tabindex == 0) {
             tabindex = 1
         }
         changeTab(tabindex);
         tab.setActive(tabindex)
-        function changeTab(index){
+
+        function changeTab(index) {
             if (index == 1) {
                 $("#main1").show();
                 $("#main2").hide();
@@ -93,8 +136,9 @@
         }
         V1Bills(param, function(ok, ret) {
             if (ok) {
-                console.log(ret)
+                //console.log(ret)
                 if (ret.code == 200) {
+                    app.checkVersion(ret.version,ret.minversion,ret.versionmsg);
                     $("#maingt").text(ret.t + "!")
                     $("#user-amount").text(ret.amount)
                     $("#user-point").text(ret.point)
@@ -131,7 +175,17 @@
             }
         })
     },
-
+    checkVersion:function(ver,minver,msg){
+        cordova.getAppVersion.getVersionNumber(function (version) {
+            //alert(version);
+            if(version<minver){
+                //TODO 强制升级
+                alert("当前版本过低,为了不影响您的使用,请先升级");
+            }else if(ver>version){
+                alert("有新的版本");    
+            }
+        });
+    },
     initBillView: function(page) {
         var html = '';
         for (var i = 0; i < page.data.length; i++) {
@@ -255,4 +309,4 @@
         }
     }
 };
-app.initialize();
\ No newline at end of file
+app.initialize();
diff --git a/platforms/android/app/src/main/assets/www/js/register.js b/platforms/android/app/src/main/assets/www/js/register.js
index e0214ab..d10558e 100644
--- a/platforms/android/app/src/main/assets/www/js/register.js
+++ b/platforms/android/app/src/main/assets/www/js/register.js
@@ -33,7 +33,6 @@
                 $.hideLoading();
                 console.log(ret)
                 if(ret.code==200){
-                     
                      window.localStorage.setItem("phone",phone); 
                      window.localStorage.setItem("uid",ret.uid); 
                      window.localStorage.setItem("code",ret.randcode); 
diff --git a/platforms/android/app/src/main/assets/www/js/scan.js b/platforms/android/app/src/main/assets/www/js/scan.js
index e75eba8..cc50c0b 100644
--- a/platforms/android/app/src/main/assets/www/js/scan.js
+++ b/platforms/android/app/src/main/assets/www/js/scan.js
@@ -32,9 +32,9 @@
                         $.alert('扫描出错,请稍后再试:' + JSON.stringify(err), '提示');
                     } else {
                         // The scan completed, display the contents of the QR code:
+                        QRScanner.destroy();
                         //$.alert(text, '提示');
                         showRet(text);
-                        QRScanner.destroy();
                     }
                 }
                 //开始扫描,需要将页面的背景设置成透明
@@ -66,22 +66,55 @@
         });
     },
     goPage: function() {
-        QRScanner.destroy();
         window.location = "main.html"
     }
 };
 app.initialize();
 var inAppBrowserRef;
-function showRet(url) {
+function showRet(url){
+  if(isEmpty(url)){
+      return;
+  }
+  var userid = window.localStorage.getItem("userid");
+  if (url.indexOf("yy.dlsmk.cn")>=0) {
+    if(url.indexOf("?")>0){
+        url=url+'&userid='+userid;
+    }else{
+        url=url+'?userid='+userid;
+    }
+  }
+  var ref = cordova.InAppBrowser.open(url, '_blank',"location=yes,beforeload=yes");
+  ref.addEventListener('loadstart', function(params){
+     if (params.url.indexOf("yy.dlsmk.cn")>=0) {
+       if (params.url.indexOf("userid")<0) {
+           if(params.url.indexOf("?")>0){
+               params.url=params.url+'&userid='+userid;
+           }else{
+               params.url=params.url+'?userid='+userid;
+           }
+           ref.hide();
+           var neRef = cordova.InAppBrowser.open(params.url, '_blank',"location=yes,beforeload=yes");
+           neRef.addEventListener('exit', function(e){
+               ref.close();
+               window.location = "main.html"
+           });
+       }
+     }
+  });
+  //ref.show();
+}
+
+function showRet1(url) {
     if(isEmpty(url)){
         return;
     }
     var userid = window.localStorage.getItem("userid"); 
     if(url.indexOf("?")>0){
-        url=url+'&uid='+userid;
+        url=url+'&userid='+userid;
     }else{
-        url=url+'?uid='+userid;
+        url=url+'?userid='+userid;
     }
+    console.log(url)
     inAppBrowserRef = cordova.ThemeableBrowser.open(url, '_blank', {
         statusbar: {
             color: '#03a9f4ff'
@@ -95,14 +128,14 @@
             showPageTitle: true
         },
         backButton: {
-            image: 'back.png',
-            imagePressed: 'back.png',
+            wwwImage: 'img/back.png',
+            wwwImagePressed: 'img/back.png',
             align: 'left',
             event: 'backPressed'
         },
         closeButton: {
-            image: 'close.png',
-            imagePressed: 'close.png',
+            wwwImage: 'img/close.png',
+            wwwImagePressed: 'img/close.png',
             align: 'left',
             event: 'closePressed'
         },
@@ -117,13 +150,60 @@
         console.error(e.message);
     }).addEventListener(cordova.ThemeableBrowser.EVT_WRN, function(e) {
         console.log(e.message);
+    }).addEventListener('loadstart', function(params,e){
+      console.log("11111111"+JSON.stringify(params));
+      if (params.url.indexOf("yy.dlsmk.cn")>=0) {
+        if (params.url.indexOf("userid")<0) {
+            if(params.url.indexOf("?")>0){
+                params.url=params.url+'&userid='+userid;
+            }else{
+                params.url=params.url+'?userid='+userid;
+            }
+            inAppBrowserRef.close();
+            inAppBrowserRef = null;
+            openUrl(params.url);
+        }
+      }
     });
-    inAppBrowserRef.addEventListener('loadstart', loadStartCallBack);
-    inAppBrowserRef.addEventListener('beforeload', beforeloadCallBack);
+    //inAppBrowserRef.addEventListener('loadstart', loadStartCallBack);
+    //inAppBrowserRef.addEventListener('beforeload', beforeloadCallBack);
 }
-function loadStartCallBack(params,callback) {
-    console.log("1",params.url);
-}
-function beforeloadCallBack(params,callback) {
-    console.log("2",params.url);
+
+function openUrl(url){
+      inAppBrowserRef = cordova.ThemeableBrowser.open(url, '_blank', {
+          statusbar: {
+              color: '#03a9f4ff'
+          },
+          toolbar: {
+              height: 44,
+              color: '#03a9f4ff'
+          },
+          title: {
+              color: '#ffffffff',
+              showPageTitle: true
+          },
+          backButton: {
+              wwwImage: 'img/back.png',
+              wwwImagePressed: 'img/back.png',
+              align: 'left',
+              event: 'backPressed'
+          },
+          closeButton: {
+              wwwImage: 'img/close.png',
+              wwwImagePressed: 'img/close.png',
+              align: 'left',
+              event: 'closePressed'
+          },
+          backButtonCanClose: true
+      }).addEventListener('backPressed', function(e) {
+      }).addEventListener('closePressed', function(e) {
+          inAppBrowserRef.close();
+          window.location = "main.html"
+      }).addEventListener(cordova.ThemeableBrowser.EVT_ERR, function(e) {
+          console.error(e.message);
+      }).addEventListener(cordova.ThemeableBrowser.EVT_WRN, function(e) {
+          console.log(e.message);
+      }).addEventListener('loadstart', function(params,e){
+          console.log("333333"+JSON.stringify(params));
+      });
 }
diff --git a/platforms/android/app/src/main/assets/www/js/server.js b/platforms/android/app/src/main/assets/www/js/server.js
index 2bd6a73..c8eb688 100644
--- a/platforms/android/app/src/main/assets/www/js/server.js
+++ b/platforms/android/app/src/main/assets/www/js/server.js
@@ -1,11 +1,12 @@
-var dev = true;
-var SERVER = "http://ykt.supwisdom.com:10010/payapi/mobileapi";
+var dev = false;
+var SERVER = "https://yy.dlsmk.cn/payapi/mobileapi";
 var GLOBAL_TODAY="";
 var GLOBAL_YESTERDAY="";
 var CURRENT_INDEX=1;
 if (dev) {
-    SERVER = "http://172.28.43.3:8099/payapi/mobileapi";
+    SERVER = "http://172.28.201.70:10010/payapi/mobileapi";
 }
+
 function V1Qrcode(callback) {
     ajaxPost("/v1/qrcode", {}, callback)
 }
diff --git a/platforms/android/app/src/main/assets/www/register.html b/platforms/android/app/src/main/assets/www/register.html
index 640b3ee..34e5998 100644
--- a/platforms/android/app/src/main/assets/www/register.html
+++ b/platforms/android/app/src/main/assets/www/register.html
@@ -15,7 +15,7 @@
 </head>
 <body>
     <header class="aui-bar aui-bar-nav" style="padding-top:25px;">
-        <a class="aui-pull-left" href="javascript:window.history.back()">
+        <a class="aui-pull-left" href="login.html">
             <span class="aui-iconfont aui-icon-left"></span>
         </a>
         <div class="aui-title">注册</div>
diff --git a/platforms/android/app/src/main/assets/www/security.html b/platforms/android/app/src/main/assets/www/security.html
index 049a988..39a40ca 100644
--- a/platforms/android/app/src/main/assets/www/security.html
+++ b/platforms/android/app/src/main/assets/www/security.html
@@ -50,7 +50,7 @@
                 </div>
             </li>
         </ul>
-         <div style="padding: 20px;margin-top: 40px;">
+        <div style="padding: 20px;margin-top: 40px;">
             <a href="javascript:app.logout();" class="weui-btn weui-btn_warn">退出登录</a>
         </div>
     </section>
diff --git a/platforms/android/app/src/main/java/com/bitpay/cordova/qrscanner/QRScanner.java b/platforms/android/app/src/main/java/com/bitpay/cordova/qrscanner/QRScanner.java
index f2e37d7..c5cfe08 100755
--- a/platforms/android/app/src/main/java/com/bitpay/cordova/qrscanner/QRScanner.java
+++ b/platforms/android/app/src/main/java/com/bitpay/cordova/qrscanner/QRScanner.java
@@ -9,12 +9,11 @@
 import android.net.Uri;
 
 import com.google.zxing.BarcodeFormat;
-import com.google.zxing.ResultPoint;
-import com.journeyapps.barcodescanner.BarcodeCallback;
-import com.journeyapps.barcodescanner.BarcodeResult;
 import com.journeyapps.barcodescanner.BarcodeView;
-import com.journeyapps.barcodescanner.DefaultDecoderFactory;
 import com.journeyapps.barcodescanner.camera.CameraSettings;
+import com.visionsmarts.VSBarcodeReader;
+import com.visionsmarts.pic2shop.view.ScannerLiveView;
+
 import org.apache.cordova.CallbackContext;
 import org.apache.cordova.CordovaPlugin;
 import org.apache.cordova.PluginResult;
@@ -35,8 +34,8 @@
 
 
 @SuppressWarnings("deprecation")
-public class QRScanner extends CordovaPlugin implements BarcodeCallback {
-
+public class QRScanner extends CordovaPlugin  {
+    private ScannerLiveView scannerLiveView;
     private CallbackContext callbackContext;
     private boolean cameraClosing;
     private static Boolean flashAvailable;
@@ -60,7 +59,49 @@
     private boolean oneTime = true;
     private boolean keepDenied = false;
     private boolean appPausedWithActivePreview = false;
-    
+    private ScannerLiveView.Listener listener = new ScannerLiveView.Listener() {
+        @Override
+        public void onCodeScanned(String str, String data) {
+            if (nextScanCallback == null) {
+                return;
+            }
+
+            if(data != null) {
+                scanning = false;
+                nextScanCallback.success(data);
+                nextScanCallback = null;
+            }
+            else {
+                scan(nextScanCallback);
+            }
+        }
+
+        @Override
+        public void onCameraIssue() {
+
+        }
+    };
+
+    public void onCodeScanned(String type, String data) {
+        //PluginResult result = new PluginResult(PluginResult.Status.OK, data);
+        //callbackContext.sendPluginResult(result);
+        if (this.nextScanCallback == null) {
+            return;
+        }
+
+        if(data != null) {
+            scanning = false;
+            this.nextScanCallback.success(data);
+            this.nextScanCallback = null;
+        }
+        else {
+            scan(this.nextScanCallback);
+        }
+    }
+    public void onCameraIssue() {
+
+    }
+
     static class QRScannerError {
         private static final int UNEXPECTED_ERROR = 0,
                 CAMERA_ACCESS_DENIED = 1,
@@ -293,6 +334,13 @@
                     else
                         lightOn = false;
                 }
+                if(scannerLiveView!=null){
+                    scannerLiveView.setTorch(toggleLight);
+                    if (toggleLight)
+                        lightOn = true;
+                    else
+                        lightOn = false;
+                }
                 getStatus(callbackContext);
             }
         });
@@ -451,25 +499,29 @@
             @Override
             public void run() {
                 // Create our Preview view and set it as the content of our activity.
-                mBarcodeView = new BarcodeView(cordova.getActivity());
+                //mBarcodeView = new BarcodeView(cordova.getActivity());
+                scannerLiveView = new ScannerLiveView(cordova.getActivity(),listener);
 
+                VSBarcodeReader.VSinit();
+                VSBarcodeReader.setBlurryAcceptanceThresholdWithAF(0.0d);
                 //Configure the decoder
                 ArrayList<BarcodeFormat> formatList = new ArrayList<BarcodeFormat>();
                 formatList.add(BarcodeFormat.QR_CODE);
-                mBarcodeView.setDecoderFactory(new DefaultDecoderFactory(formatList, null, null));
+                //mBarcodeView.setDecoderFactory(new DefaultDecoderFactory(formatList, null, null));
 
                 //Configure the camera (front/back)
                 CameraSettings settings = new CameraSettings();
                 settings.setRequestedCameraId(getCurrentCameraId());
-                mBarcodeView.setCameraSettings(settings);
+                //mBarcodeView.setCameraSettings(settings);
 
                 FrameLayout.LayoutParams cameraPreviewParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
-                ((ViewGroup) webView.getView().getParent()).addView(mBarcodeView, cameraPreviewParams);
-
+                //((ViewGroup) webView.getView().getParent()).addView(mBarcodeView, cameraPreviewParams);
+                ((ViewGroup) webView.getView().getParent()).addView(scannerLiveView, cameraPreviewParams);
                 cameraPreviewing = true;
                 webView.getView().bringToFront();
 
-                mBarcodeView.resume();
+                //mBarcodeView.resume();
+                //scannerLiveView.onResume();
             }
         });
         prepared = true;
@@ -479,7 +531,7 @@
 
     }
 
-    @Override
+    /*@Override
     public void barcodeResult(BarcodeResult barcodeResult) {
         if (this.nextScanCallback == null) {
             return;
@@ -497,7 +549,7 @@
 
     @Override
     public void possibleResultPoints(List<ResultPoint> list) {
-    }
+    }*/
 
     // ---- BEGIN EXTERNAL API ----
     private void prepare(final CallbackContext callbackContext) {
@@ -588,7 +640,7 @@
             }
             shouldScanAgain = false;
             this.nextScanCallback = callbackContext;
-            final BarcodeCallback b = this;
+            /*final BarcodeCallback b = this;
             this.cordova.getActivity().runOnUiThread(new Runnable() {
                 @Override
                 public void run() {
@@ -596,7 +648,11 @@
                         mBarcodeView.decodeSingle(b);
                     }
                 }
-            });
+            });*/
+
+            if(scannerLiveView!=null){
+                scannerLiveView.onResume();
+            }
         }
     }
 
@@ -620,6 +676,9 @@
             @Override
             public void run() {
                 webView.getView().setBackgroundColor(Color.argb(1, 0, 0, 0));
+                if(scannerLiveView!=null){
+                    scannerLiveView.startCamera();
+                }
                 showing = true;
                 getStatus(callbackContext);
             }
@@ -777,8 +836,10 @@
             this.cordova.getActivity().runOnUiThread(new Runnable() {
                 @Override
                 public void run() {
+                  if(mBarcodeView!=null) {
                     ((ViewGroup) mBarcodeView.getParent()).removeView(mBarcodeView);
                     cameraPreviewing = false;
+                  }
                 }
             });
         }
@@ -788,6 +849,9 @@
         }
         closeCamera();
         currentCameraId = 0;
+        if(scannerLiveView!=null){
+          scannerLiveView.onPause();
+        }
         getStatus(callbackContext);
     }
 }
diff --git a/platforms/android/app/src/main/java/com/supwisdom/dlapp/MainActivity.java b/platforms/android/app/src/main/java/com/dalicitycard/app/MainActivity.java
similarity index 97%
rename from platforms/android/app/src/main/java/com/supwisdom/dlapp/MainActivity.java
rename to platforms/android/app/src/main/java/com/dalicitycard/app/MainActivity.java
index c48c351..7b7fe6b 100644
--- a/platforms/android/app/src/main/java/com/supwisdom/dlapp/MainActivity.java
+++ b/platforms/android/app/src/main/java/com/dalicitycard/app/MainActivity.java
@@ -17,7 +17,7 @@
        under the License.
  */
 
-package com.supwisdom.dlapp;
+package com.dalicitycard.app;
 
 import android.os.Bundle;
 import org.apache.cordova.*;
diff --git a/platforms/android/app/src/main/java/com/visionsmarts/VSBarcodeReader.java b/platforms/android/app/src/main/java/com/visionsmarts/VSBarcodeReader.java
new file mode 100644
index 0000000..feb3b33
--- /dev/null
+++ b/platforms/android/app/src/main/java/com/visionsmarts/VSBarcodeReader.java
@@ -0,0 +1,90 @@
+package com.visionsmarts;
+
+public class VSBarcodeReader {
+    public static final int BARCODE_TYPE_CODABAR = 64;
+    public static final int BARCODE_TYPE_CODE128 = 32;
+    public static final int BARCODE_TYPE_CODE39 = 16;
+    public static final int BARCODE_TYPE_CODE93 = 128;
+    public static final int BARCODE_TYPE_EAN_13_UPC_A = 1;
+    public static final int BARCODE_TYPE_EAN_8 = 2;
+    public static final String BARCODE_TYPE_ID_CODABAR = "CODABAR";
+    public static final String BARCODE_TYPE_ID_CODE128 = "CODE128";
+    public static final String BARCODE_TYPE_ID_CODE39 = "CODE39";
+    public static final String BARCODE_TYPE_ID_CODE93 = "CODE93";
+    public static final String BARCODE_TYPE_ID_EAN_13_UPC_A = "EAN13";
+    public static final String BARCODE_TYPE_ID_EAN_8 = "EAN8";
+    public static final String BARCODE_TYPE_ID_ITF = "ITF";
+    public static final String BARCODE_TYPE_ID_STD2OF5 = "STD2OF5";
+    public static final String BARCODE_TYPE_ID_UPC_E = "UPCE";
+    public static final int BARCODE_TYPE_INVALID = -1;
+    public static final int BARCODE_TYPE_ITF = 8;
+    public static final String BARCODE_TYPE_NAME_CODABAR = "Codabar";
+    public static final String BARCODE_TYPE_NAME_CODE128 = "Code 128";
+    public static final String BARCODE_TYPE_NAME_CODE39 = "Code 39";
+    public static final String BARCODE_TYPE_NAME_CODE93 = "Code 93";
+    public static final String BARCODE_TYPE_NAME_EAN_13_UPC_A = "EAN-13/UPC-A";
+    public static final String BARCODE_TYPE_NAME_EAN_8 = "EAN-8";
+    public static final String BARCODE_TYPE_NAME_ITF = "ITF";
+    public static final String BARCODE_TYPE_NAME_STD2OF5 = "STD 2 of 5";
+    public static final String BARCODE_TYPE_NAME_UPC_E = "UPC-E";
+    public static final int BARCODE_TYPE_STD2OF5 = 256;
+    public static final int BARCODE_TYPE_UPC_E = 4;
+
+    public static class DecoderValues {
+        public int evaluationDays;
+        public int left;
+        public Point lineEnd;
+        public Point lineStart;
+        public int right;
+        public int type;
+
+        public DecoderValues() {
+            this.lineStart = new Point();
+            this.lineEnd = new Point();
+        }
+    }
+
+    public static class Point {
+        public int x;
+        public int y;
+    }
+
+    public static native int VSinit();
+
+    public static native String decodeNextImage(byte[] bArr, int i, int i2, DecoderValues decoderValues);
+
+    public static native String decodeNextImageOmnidirectional(byte[] bArr, int i, int i2, int i3, DecoderValues decoderValues);
+
+    public static native int reset();
+
+    public static native int setBlurryAcceptanceThresholdWithAF(double d);
+
+    static {
+        System.loadLibrary("VSBarcodeReader");
+    }
+
+    public static String format(String barcode, int type) {
+        Object[] objArr;
+        switch (type) {
+            case BARCODE_TYPE_EAN_13_UPC_A /*1*/:
+                if (barcode.substring(0, BARCODE_TYPE_EAN_13_UPC_A).equals("0")) {
+                    objArr = new Object[BARCODE_TYPE_UPC_E];
+                    objArr[0] = barcode.substring(BARCODE_TYPE_EAN_13_UPC_A, BARCODE_TYPE_EAN_8);
+                    objArr[BARCODE_TYPE_EAN_13_UPC_A] = barcode.substring(BARCODE_TYPE_EAN_8, 7);
+                    objArr[BARCODE_TYPE_EAN_8] = barcode.substring(7, 12);
+                    objArr[3] = barcode.substring(12, 13);
+                    return String.format("%s-%s-%s-%s", objArr);
+                }
+                return String.format("%s-%s-%s", new Object[]{barcode.substring(0, BARCODE_TYPE_EAN_13_UPC_A), barcode.substring(BARCODE_TYPE_EAN_13_UPC_A, 7), barcode.substring(7, 13)});
+            case BARCODE_TYPE_EAN_8 /*2*/:
+                objArr = new Object[BARCODE_TYPE_EAN_8];
+                objArr[0] = barcode.substring(0, BARCODE_TYPE_UPC_E);
+                objArr[BARCODE_TYPE_EAN_13_UPC_A] = barcode.substring(BARCODE_TYPE_UPC_E, BARCODE_TYPE_ITF);
+                return String.format("%s-%s", objArr);
+            case BARCODE_TYPE_UPC_E /*4*/:
+                return String.format("%s-%s-%s", new Object[]{barcode.substring(0, BARCODE_TYPE_EAN_13_UPC_A), barcode.substring(BARCODE_TYPE_EAN_13_UPC_A, 7), barcode.substring(7, BARCODE_TYPE_ITF)});
+            default:
+                return barcode;
+        }
+    }
+}
diff --git a/platforms/android/app/src/main/java/com/visionsmarts/VSReaderQR.java b/platforms/android/app/src/main/java/com/visionsmarts/VSReaderQR.java
new file mode 100644
index 0000000..12acf68
--- /dev/null
+++ b/platforms/android/app/src/main/java/com/visionsmarts/VSReaderQR.java
@@ -0,0 +1,190 @@
+package com.visionsmarts;
+
+import java.nio.ByteBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+
+public class VSReaderQR {
+    public static final int MODE_ALPHANUMERIC = 2;
+    public static final int MODE_BYTE = 4;
+    public static final int MODE_KANJI = 8;
+    public static final int MODE_NUMERIC = 1;
+    public static final String QR_CODE_TYPE_ID = "QR";
+
+    public static class DecoderValues {
+        public Point corner1;
+        public Point corner2;
+        public Point corner3;
+        public Point corner4;
+        public int evaluationDays;
+        public int mode;
+
+        public DecoderValues() {
+            this.corner1 = new Point();
+            this.corner2 = new Point();
+            this.corner3 = new Point();
+            this.corner4 = new Point();
+        }
+    }
+
+    private static class ECIMarker {
+        public int eci;
+        public int position;
+
+        private ECIMarker() {
+        }
+    }
+
+    public static class Point {
+        public int x;
+        public int y;
+    }
+
+    public static native byte[] decodeImage(byte[] bArr, int i, int i2, DecoderValues decoderValues);
+
+    static {
+        System.loadLibrary("VSReaderQR");
+    }
+
+    public static String format(byte[] data, int mode) {
+        Charset charset = Charset.forName("UTF-8");
+        if ((mode & MODE_KANJI) == MODE_KANJI) {
+            charset = Charset.forName("Shift_JIS");
+        }
+        int position = 0;
+        if (data.length > 3 && data[0] == 93 && data[MODE_NUMERIC] == 81) {
+            if (data[MODE_ALPHANUMERIC] == 51 || data[MODE_ALPHANUMERIC] == 52) {
+                position = 0 + 3;
+            }
+            if ((data[MODE_ALPHANUMERIC] == 53 || data[MODE_ALPHANUMERIC] == 54) && data.length > 5) {
+                position += 5;
+            }
+        }
+        StringBuilder result = new StringBuilder(data.length);
+        do {
+            ECIMarker nextMarker = findFirstECIMarker(data, position);
+            String next = decodeData(ByteBuffer.wrap(data, position, Math.min(nextMarker.position, data.length) - position), charset);
+            if (next != null) {
+                result.append(next);
+            }
+            if (nextMarker.position != data.length) {
+                position = nextMarker.position + 7;
+                charset = getCharsetForECI(nextMarker.eci);
+                if (charset == null) {
+                    charset = getCharsetForECI(0);
+                }
+            }
+            if (nextMarker.position == data.length) {
+                break;
+            }
+        } while (position < data.length);
+        return result.toString();
+    }
+
+    private static ECIMarker findFirstECIMarker(byte[] data, int fromPosition) {
+        ECIMarker eciMarker = new ECIMarker();
+        eciMarker.position = data.length;
+        int position = fromPosition;
+        while (position < data.length - 6) {
+            if (data[position] == 92 && Character.isDigit(data[position + MODE_NUMERIC]) && Character.isDigit(data[position + MODE_ALPHANUMERIC]) && Character.isDigit(data[position + 3]) && Character.isDigit(data[position + MODE_BYTE]) && Character.isDigit(data[position + 5]) && Character.isDigit(data[position + 6])) {
+                eciMarker.position = position;
+                eciMarker.eci = ((((((data[position + MODE_NUMERIC] - 48) * 100000) + ((data[position + MODE_ALPHANUMERIC] - 48) * 10000)) + ((data[position + 3] - 48) * 1000)) + ((data[position + MODE_BYTE] - 48) * 100)) + ((data[position + 5] - 48) * 10)) + (data[position + 6] - 48);
+                break;
+            }
+            position += MODE_NUMERIC;
+        }
+        return eciMarker;
+    }
+
+    private static Charset getCharsetForECI(int eci) {
+        switch (eci) {
+
+            case MODE_NUMERIC /*1*/:
+                return Charset.forName("ISO-8859-1");
+            case MODE_ALPHANUMERIC /*2*/:
+                return Charset.forName("ISO-8859-1");
+            case MODE_BYTE /*4*/:
+                return Charset.forName("ISO-8859-2");
+            case 5:
+                return Charset.forName("ISO-8859-3");
+            case 6:
+                return Charset.forName("ISO-8859-4");
+            case 7:
+                return Charset.forName("ISO-8859-5");
+            case MODE_KANJI /*8*/:
+                return Charset.forName("ISO-8859-6");
+            case 9:
+                return Charset.forName("ISO-8859-7");
+            case 10:
+                return Charset.forName("ISO-8859-8");
+            case 11:
+                return Charset.forName("ISO-8859-9");
+            case 12:
+                return Charset.forName("ISO-8859-10");
+            case 13:
+                return Charset.forName("ISO-8859-11");
+            case 15:
+                return Charset.forName("ISO-8859-13");
+            case VSBarcodeReader.BARCODE_TYPE_CODE39 /*16*/:
+                return Charset.forName("ISO-8859-14");
+            case 17:
+                return Charset.forName("ISO-8859-15");
+            case 18:
+                return Charset.forName("ISO-8859-16");
+            case 20:
+                return Charset.forName("Shift_JIS");
+            case 21:
+                return Charset.forName("windows-1250");
+            case 22:
+                return Charset.forName("windows-1251");
+            case 23:
+                return Charset.forName("windows-1252");
+            case 24:
+                return Charset.forName("windows-1256");
+            case 25:
+                return Charset.forName("UTF-16BE");
+            case 26:
+                return Charset.forName("UTF-8");
+            case 27:
+                return Charset.forName("EUC-JP");
+            case 28:
+                return Charset.forName("Big5");
+            case 29:
+                return Charset.forName("x-EUC-CN");
+            case 30:
+                return Charset.forName("EUC-KR");
+            case 899:
+                return Charset.forName("UTF-8");
+            default:
+                return null;
+        }
+    }
+
+    public static String decodeData(ByteBuffer data, Charset charset) {
+        try {
+            return charset.newDecoder().decode(data).toString();
+        } catch (CharacterCodingException e) {
+            data.rewind();
+            try {
+                return Charset.forName("Shift_JIS").newDecoder().decode(data).toString();
+            } catch (CharacterCodingException e2) {
+                data.rewind();
+                try {
+                    return Charset.forName("UTF-8").newDecoder().decode(data).toString();
+                } catch (CharacterCodingException e3) {
+                    data.rewind();
+                    try {
+                        return Charset.forName("ISO-8859-1").newDecoder().decode(data).toString();
+                    } catch (CharacterCodingException e4) {
+                        data.rewind();
+                        try {
+                            return Charset.forName("US-ASCII").newDecoder().decode(data).toString();
+                        } catch (CharacterCodingException e5) {
+                            return null;
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/platforms/android/app/src/main/java/com/visionsmarts/pic2shop/view/BarQrCodeUtil.java b/platforms/android/app/src/main/java/com/visionsmarts/pic2shop/view/BarQrCodeUtil.java
new file mode 100644
index 0000000..222d7e2
--- /dev/null
+++ b/platforms/android/app/src/main/java/com/visionsmarts/pic2shop/view/BarQrCodeUtil.java
@@ -0,0 +1,27 @@
+package com.visionsmarts.pic2shop.view;
+
+import com.visionsmarts.VSReaderQR;
+
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+
+public class BarQrCodeUtil {
+  public static String qrToString(byte[] qrData) {
+    ByteBuffer qrBuffer;
+    if (qrData[qrData.length - 1] == 0) {
+      qrBuffer = ByteBuffer.wrap(qrData, 0, qrData.length - 1);
+    } else {
+      qrBuffer = ByteBuffer.wrap(qrData);
+    }
+    return VSReaderQR.decodeData(qrBuffer, Charset.forName("UTF-8"));
+  }
+
+  public static final int DECODE = 100;
+  public static final int QUIT = 101;
+  public static final int NOTFOUND = 102;
+
+  public static final int BARCODE = 103;
+  public static final int QRCODE = 104;
+
+  public static final int AUTO_FOCUS = 105;
+}
diff --git a/platforms/android/app/src/main/java/com/visionsmarts/pic2shop/view/ScannerLiveView.java b/platforms/android/app/src/main/java/com/visionsmarts/pic2shop/view/ScannerLiveView.java
new file mode 100644
index 0000000..a45ba8b
--- /dev/null
+++ b/platforms/android/app/src/main/java/com/visionsmarts/pic2shop/view/ScannerLiveView.java
@@ -0,0 +1,784 @@
+package com.visionsmarts.pic2shop.view;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.ImageFormat;
+import android.graphics.Point;
+import android.hardware.Camera;
+import android.hardware.Camera.AutoFocusCallback;
+import android.hardware.Camera.Parameters;
+import android.hardware.Camera.PreviewCallback;
+import android.hardware.Camera.Size;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.Display;
+import android.view.SurfaceHolder;
+import android.view.SurfaceHolder.Callback;
+import android.view.SurfaceView;
+import android.view.WindowManager;
+
+import com.google.zxing.client.android.camera.CameraConfigurationUtils;
+import com.visionsmarts.VSBarcodeReader;
+import com.visionsmarts.VSBarcodeReader.DecoderValues;
+import com.visionsmarts.VSReaderQR;
+
+import java.io.IOException;
+import java.util.regex.Pattern;
+
+public class ScannerLiveView extends SurfaceView implements Callback {
+    private Point screen;
+    private static final int BARCODE_TYPES_MASK = 7;
+    private static final Pattern COMMA_PATTERN;
+    private static final int DESIRED_ZOOM_X10 = 27;
+    private static final String TAG;
+    private AutoFocusCallback mAutoFocusCallback;
+    private volatile byte[] mCallbackBuffer;
+    private volatile Camera mCamera;
+    private DecodingThread mDecodingThread;
+    volatile boolean mFoundBarcodeOrQRCode;
+    volatile byte[] mFrameData;
+    volatile boolean mFrameDataIsAutoFocusInProgress;
+    volatile boolean mHasCameraAutoFocus;
+    volatile boolean mIsAutoFocusInProgress;
+    volatile boolean mIsPreviewStarted;
+    Listener mListener;
+    private PreviewCallback mPreviewCallback;
+    private int mPreviewFrameSize;
+    volatile Size mPreviewSize;
+    final ScannerHandler mScannerHandler;
+    private volatile int mCameraDisplayOrientation;
+
+    public interface Listener {
+        void onCodeScanned(String str, String str2);
+        void onCameraIssue();
+    }
+
+    /* renamed from: com.visionsmarts.pic2shop.view.ScannerLiveView.1 */
+    class ScanAutoFocusCallback implements AutoFocusCallback {
+        ScanAutoFocusCallback() {
+        }
+
+        public void onAutoFocus(boolean success, Camera camera) {
+            ScannerLiveView.this.mIsAutoFocusInProgress = false;
+        }
+    }
+
+    /* renamed from: com.visionsmarts.pic2shop.view.ScannerLiveView.2 */
+    class ScanPreviewCallback implements PreviewCallback {
+        ScanPreviewCallback() {
+        }
+
+        public synchronized void onPreviewFrame(byte[] frameData, Camera camera) {
+            if (!(!ScannerLiveView.this.mIsPreviewStarted || ScannerLiveView.this.mDecodingThread == null || ScannerLiveView.this.mFoundBarcodeOrQRCode)) {
+                boolean shouldSendDecodeRequest = ScannerLiveView.this.mFrameData == null;
+                ScannerLiveView.this.mFrameData = frameData;
+                ScannerLiveView.this.mFrameDataIsAutoFocusInProgress = ScannerLiveView.this.mIsAutoFocusInProgress;
+                if (shouldSendDecodeRequest) {
+                    ScannerLiveView.this.mDecodingThread.getHandler().obtainMessage(BarQrCodeUtil.DECODE).sendToTarget();
+                }
+            }
+        }
+    }
+
+    private class DecodingThread extends Thread {
+        DecoderValues mBarcodeDecoderValues;
+        private Handler mHandler;
+        private int mNumberConsecutiveFailedDecodingSinceFocusEnded;
+        private byte[] mPreviewLine;
+        VSReaderQR.DecoderValues mQRDecoderValues;
+
+        /* renamed from: com.visionsmarts.pic2shop.view.ScannerLiveView.DecodingThread.1 */
+        class DecodeMessageHandler extends Handler {
+            DecodeMessageHandler() {
+            }
+
+            public void handleMessage(Message message) {
+                switch (message.what) {
+                    case BarQrCodeUtil.DECODE:
+                        if (ScannerLiveView.this.mIsPreviewStarted && !ScannerLiveView.this.mFoundBarcodeOrQRCode) {
+                            DecodingThread.this.decode();
+                        }
+                        break;
+                    case BarQrCodeUtil.QUIT:
+                        Looper.myLooper().quit();
+                        break;
+                    default:
+                }
+            }
+        }
+
+        public DecodingThread() {
+            this.mNumberConsecutiveFailedDecodingSinceFocusEnded = 0;
+            this.mBarcodeDecoderValues = new DecoderValues();
+            this.mQRDecoderValues = new VSReaderQR.DecoderValues();
+            setPriority(10);
+            initialize();
+        }
+
+        synchronized Handler getHandler() {
+            if (this.mHandler == null) {
+                try {
+                    ScannerLiveView.this.mDecodingThread.wait(1000);
+                } catch (InterruptedException e) {
+                }
+            }
+            return this.mHandler;
+        }
+
+        public void initialize() {
+            if (ScannerLiveView.this.mPreviewSize != null && (this.mPreviewLine == null || this.mPreviewLine.length != ScannerLiveView.this.mPreviewSize.height)) {
+                this.mPreviewLine = new byte[ScannerLiveView.this.mPreviewSize.height];
+            }
+            this.mNumberConsecutiveFailedDecodingSinceFocusEnded = 0;
+            ScannerLiveView.this.mFoundBarcodeOrQRCode = false;
+            VSBarcodeReader.reset();
+        }
+
+        public void run() {
+            Looper.prepare();
+            synchronized (this) {
+                this.mHandler = new DecodeMessageHandler();
+                notify();
+            }
+            Looper.loop();
+        }
+
+        private void decode() {
+            byte[] previewLine = this.mPreviewLine;
+            int width = ScannerLiveView.this.mPreviewSize.width;
+            int height = ScannerLiveView.this.mPreviewSize.height;
+            synchronized (ScannerLiveView.this.mPreviewCallback) {
+                if (ScannerLiveView.this.mFrameData == null) {
+                    return;
+                }
+                byte[] frameData = ScannerLiveView.this.mFrameData;
+                boolean wasAutoFocusInProgress = ScannerLiveView.this.mFrameDataIsAutoFocusInProgress;
+                int offset  =  Math.round((float) (screen.y  / 2));
+                Log.e(TAG,"offset="+offset);
+                try {
+                    for (int i = previewLine.length - 1; i >= 0; i--) {
+                        previewLine[i] = frameData[offset];
+                        offset += width;
+                    }
+                } catch (ArrayIndexOutOfBoundsException e) {
+                }
+                if (ScannerLiveView.this.mFrameData != null) {
+                    String barcode = VSBarcodeReader.decodeNextImage(previewLine, ScannerLiveView.this.mHasCameraAutoFocus ? 1 : 0, ScannerLiveView.BARCODE_TYPES_MASK, this.mBarcodeDecoderValues);
+                    if (ScannerLiveView.this.mFrameData != null) {
+                        if (barcode.length() > 0) {
+                            ScannerLiveView.this.mFoundBarcodeOrQRCode = true;
+                            ScannerLiveView.this.mScannerHandler.obtainMessage(BarQrCodeUtil.BARCODE, barcode).sendToTarget();
+                        } else {
+                            try {
+                                byte[] qrData = VSReaderQR.decodeImage(frameData, width, height, this.mQRDecoderValues);
+                                if (qrData.length > 0) {
+                                    ScannerLiveView.this.mFoundBarcodeOrQRCode = true;
+                                    ScannerLiveView.this.mScannerHandler.obtainMessage(BarQrCodeUtil.QRCODE, qrData).sendToTarget();
+                                } else if (wasAutoFocusInProgress) {
+                                    this.mNumberConsecutiveFailedDecodingSinceFocusEnded = 0;
+                                } else {
+                                    this.mNumberConsecutiveFailedDecodingSinceFocusEnded++;
+                                    if (ScannerLiveView.this.mHasCameraAutoFocus && !ScannerLiveView.this.mIsAutoFocusInProgress && this.mNumberConsecutiveFailedDecodingSinceFocusEnded >= 4) {
+                                        ScannerLiveView.this.mScannerHandler.obtainMessage(BarQrCodeUtil.AUTO_FOCUS).sendToTarget();
+                                    }
+                                }
+                            }catch (Exception e){
+                                e.printStackTrace();
+                            }
+                        }
+                        synchronized (ScannerLiveView.this.mPreviewCallback) {
+                            ScannerLiveView.this.mFrameData = null;
+                            if (!(ScannerLiveView.this.mFoundBarcodeOrQRCode || ScannerLiveView.this.mCallbackBuffer == null)) {
+                                ScannerLiveView.this.mCamera.addCallbackBuffer(ScannerLiveView.this.mCallbackBuffer);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private class ScannerHandler extends Handler {
+        private ScannerHandler() {
+        }
+
+        public void handleMessage(Message message) {
+            switch (message.what) {
+                case BarQrCodeUtil.AUTO_FOCUS:
+                    ScannerLiveView.this.requestAutoFocus();
+                    break;
+                case BarQrCodeUtil.BARCODE:
+                    if (ScannerLiveView.this.mIsPreviewStarted) {
+                        ScannerLiveView.this.stopCamera();
+                        ScannerLiveView.this.mListener.onCodeScanned("BAR", (String)message.obj);
+                    }
+                    break;
+                case BarQrCodeUtil.QRCODE:
+                    if (ScannerLiveView.this.mIsPreviewStarted) {
+                        ScannerLiveView.this.stopCamera();
+                        ScannerLiveView.this.mListener.onCodeScanned("QR", BarQrCodeUtil.qrToString((byte[])message.obj));
+                    }
+                    break;
+                default:
+            }
+        }
+    }
+
+    public ScannerLiveView(Context context,Listener mListener) {
+        super(context);
+        this.mPreviewFrameSize = 0;
+        this.mScannerHandler = new ScannerHandler();
+        this.mIsPreviewStarted = false;
+        this.mIsAutoFocusInProgress = false;
+        this.mFrameData = null;
+        this.mFrameDataIsAutoFocusInProgress = false;
+        this.mFoundBarcodeOrQRCode = false;
+        this.mListener = mListener;
+        initialize(context);
+    }
+
+    public ScannerLiveView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        this.mPreviewFrameSize = 0;
+        this.mScannerHandler = new ScannerHandler();
+        this.mIsPreviewStarted = false;
+        this.mIsAutoFocusInProgress = false;
+        this.mFrameData = null;
+        this.mFrameDataIsAutoFocusInProgress = false;
+        this.mFoundBarcodeOrQRCode = false;
+
+        initialize(context);
+    }
+
+    public ScannerLiveView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        this.mPreviewFrameSize = 0;
+        this.mScannerHandler = new ScannerHandler();
+        this.mIsPreviewStarted = false;
+        this.mIsAutoFocusInProgress = false;
+        this.mFrameData = null;
+        this.mFrameDataIsAutoFocusInProgress = false;
+        this.mFoundBarcodeOrQRCode = false;
+        initialize(context);
+    }
+
+    private void initialize(Context context) {
+        //this.mListener = (Listener) context;
+        SurfaceHolder holder = getHolder();
+        holder.addCallback(this);
+        holder.setType(3);
+        holder.setKeepScreenOn(true);
+        this.mAutoFocusCallback = new ScanAutoFocusCallback();
+        this.mPreviewCallback = new ScanPreviewCallback();
+        Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
+        screen = new Point();
+        display.getSize(screen);
+    }
+
+
+    public void surfaceCreated(SurfaceHolder holder) {
+        if (holder == null) {
+            throw new IllegalStateException("No SurfaceHolder provided");
+        } else if (this.mCamera == null) {
+            try {
+                this.mCamera = null;
+                try {
+                    Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
+                    int cameraCount = Camera.getNumberOfCameras();
+                    for (int camIdx = 0; camIdx < cameraCount; camIdx++) {
+                        Camera.getCameraInfo(camIdx, cameraInfo);
+                        if (cameraInfo.facing == 0) {
+                            this.mCamera = Camera.open(camIdx);
+                            //this.mCamera.setDisplayOrientation(90);
+                            setCameraDisplayOrientation(camIdx);
+                            break;
+                        }
+                    }
+                } catch (LinkageError e) {
+                }
+                if (this.mCamera == null) {
+                    try {
+                        this.mCamera = Camera.open(0);
+                        //this.mCamera.setDisplayOrientation(90);
+                        setCameraDisplayOrientation(0);
+                    } catch (LinkageError e2) {
+                    }
+                }
+                if (this.mCamera == null) {
+                    this.mCamera = Camera.open();
+                }
+                this.mCamera.setPreviewDisplay(holder);
+                this.mIsPreviewStarted = false;
+            } catch (IOException e3) {
+                this.mListener.onCameraIssue();
+            } catch (RuntimeException e4) {
+                this.mListener.onCameraIssue();
+            }
+        }
+    }
+
+    public void setCameraDisplayOrientation(int cameraId) {
+        Camera.CameraInfo info = new Camera.CameraInfo();
+        Camera.getCameraInfo(cameraId, info);
+        int degrees = 0;
+        switch (((Activity) getContext()).getWindowManager().getDefaultDisplay().getRotation()) {
+            case 0:
+                degrees = 0;
+                break;
+            case 1:
+                degrees = 90;
+                break;
+            case 2:
+                degrees = 180;
+                break;
+            case 3:
+                degrees = 270;
+                break;
+        }
+        if (info.facing == 1) {
+            this.mCameraDisplayOrientation = (info.orientation + degrees) % 360;
+            this.mCameraDisplayOrientation = (360 - this.mCameraDisplayOrientation) % 360;
+        } else {
+            this.mCameraDisplayOrientation = ((info.orientation - degrees) + 360) % 360;
+        }
+        this.mCamera.setDisplayOrientation(this.mCameraDisplayOrientation);
+    }
+
+    public void surfaceDestroyed(SurfaceHolder holder) {
+        if (this.mCamera != null) {
+            stopCamera();
+            this.mPreviewFrameSize = 0;
+        }
+    }
+
+    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+        if (this.mCamera != null) {
+            stopCamera();
+            setCameraParameters(screen.y,screen.x);
+            if (isShown()) {
+                startCamera();
+            }
+        }
+    }
+
+    public void onPause() {
+        stopCamera();
+        if (this.mCamera != null) {
+            this.mCamera.release();
+            this.mCamera = null;
+        }
+        if(this.mDecodingThread!=null) {
+          Message.obtain(this.mDecodingThread.getHandler(), BarQrCodeUtil.QUIT).sendToTarget();
+          try {
+            this.mDecodingThread.join();
+          } catch (InterruptedException e) {
+          }
+        }
+        if(this.mScannerHandler!=null) {
+          this.mScannerHandler.removeMessages(BarQrCodeUtil.AUTO_FOCUS);
+          this.mScannerHandler.removeMessages(BarQrCodeUtil.BARCODE);
+          this.mScannerHandler.removeMessages(BarQrCodeUtil.QRCODE);
+        }
+        this.mDecodingThread = null;
+    }
+
+    public void setTorch(boolean on) {
+        if (this.mCamera != null) {
+            boolean isOn = isTorchOn();
+            if (on != isOn) {
+
+                Camera.Parameters parameters = this.mCamera.getParameters();
+                CameraConfigurationUtils.setTorch(parameters, on);
+                this.mCamera.setParameters(parameters);
+            }
+        }
+    }
+
+    public boolean isTorchOn() {
+        Camera.Parameters parameters = this.mCamera.getParameters();
+        if (parameters != null) {
+            String flashMode = parameters.getFlashMode();
+            return flashMode != null &&
+                (Camera.Parameters.FLASH_MODE_ON.equals(flashMode) ||
+                    Camera.Parameters.FLASH_MODE_TORCH.equals(flashMode));
+        } else {
+            return false;
+        }
+    }
+
+    public void onResume() {
+        /*this.mScannerOverlay = (ScannerOverlay) ((Activity) getContext()).findViewById(R.id.scanner_overlay);
+        this.mScannerOverlay.setBarcodeLocation(-1, -1);*/
+        this.mDecodingThread = new DecodingThread();
+        this.mDecodingThread.start();
+        startCamera();
+    }
+
+    public void startCamera() {
+        if (this.mCamera != null && !this.mIsPreviewStarted) {
+            this.mIsAutoFocusInProgress = false;
+            this.mFrameData = null;
+            if (this.mDecodingThread != null) {
+                this.mDecodingThread.initialize();
+            }
+            if (this.mPreviewFrameSize > 0) {
+                try {
+                    this.mCallbackBuffer = new byte[this.mPreviewFrameSize];
+                } catch (OutOfMemoryError e) {
+                    this.mCallbackBuffer = null;
+                }
+            }
+            if (this.mCallbackBuffer != null) {
+                this.mCamera.setPreviewCallbackWithBuffer(this.mPreviewCallback);
+                this.mCamera.addCallbackBuffer(this.mCallbackBuffer);
+            } else {
+                this.mCamera.setPreviewCallback(this.mPreviewCallback);
+            }
+            try {
+                this.mCamera.startPreview();
+                this.mIsPreviewStarted = true;
+                requestAutoFocus();
+            } catch (RuntimeException e2) {
+                this.mCamera.setPreviewCallback(null);
+                this.mCallbackBuffer = null;
+                this.mListener.onCameraIssue();
+            }
+        }
+    }
+
+    public void stopCamera() {
+        /*if (this.mCamera != null && this.mIsPreviewStarted) {
+            this.mCamera.setPreviewCallback(null);
+            this.mCamera.stopPreview();
+            this.mIsPreviewStarted = false;
+            if (this.mDecodingThread.getHandler() != null) {
+                this.mDecodingThread.getHandler().removeMessages(R.id.decode);
+            }
+            this.mScannerHandler.removeMessages(R.id.auto_focus);
+            this.mScannerHandler.removeMessages(R.id.msg_barcode_found);
+        }*/
+
+        if (this.mCamera != null && this.mIsPreviewStarted) {
+            synchronized (this.mPreviewCallback) {
+                this.mCamera.setPreviewCallback(null);
+                this.mCamera.stopPreview();
+                this.mIsPreviewStarted = false;
+                this.mCamera.cancelAutoFocus();
+                this.mFrameData = null;
+                this.mCallbackBuffer = null;
+            }
+            if (!(this.mDecodingThread == null || this.mDecodingThread.getHandler() == null)) {
+                this.mDecodingThread.getHandler().removeMessages(BarQrCodeUtil.DECODE);
+            }
+            this.mScannerHandler.removeMessages(BarQrCodeUtil.AUTO_FOCUS);
+            this.mScannerHandler.removeMessages(BarQrCodeUtil.BARCODE);
+            this.mScannerHandler.removeMessages(BarQrCodeUtil.QRCODE);
+        }
+
+    }
+
+    void requestAutoFocus() {
+        if (this.mCamera != null && this.mHasCameraAutoFocus && this.mIsPreviewStarted && !this.mIsAutoFocusInProgress) {
+            try {
+                this.mCamera.autoFocus(this.mAutoFocusCallback);
+                this.mIsAutoFocusInProgress = true;
+            } catch (RuntimeException e) {
+                Log.e(TAG, "Camera auto-focus failed: " + e.getLocalizedMessage());
+            }
+        }
+    }
+
+
+    private void setCameraParameters(int screenWidth, int screenHeight) {
+        Parameters parameters = this.mCamera.getParameters();
+        Log.e(TAG,"screenWidth="+screenWidth+",screenHeight="+screenHeight);
+        setPreviewSize(screenWidth, screenHeight, parameters);
+        setZoom(parameters);
+        String focusModeValues = parameters.get("focus-mode-values");
+        if (focusModeValues != null && focusModeValues.contains("macro")) {
+            parameters.set("focus-mode", "macro");
+            this.mHasCameraAutoFocus = true;
+        } else if (focusModeValues == null || !focusModeValues.contains("auto")) {
+            this.mHasCameraAutoFocus = false;
+        } else {
+            parameters.set("focus-mode", "auto");
+            this.mHasCameraAutoFocus = true;
+        }
+        try {
+            this.mCamera.setParameters(parameters);
+        } catch (RuntimeException e) {
+            this.mListener.onCameraIssue();
+        }
+        parameters = this.mCamera.getParameters();
+        this.mPreviewSize = parameters.getPreviewSize();
+        this.mPreviewFrameSize = ((this.mPreviewSize.width * this.mPreviewSize.height) * ImageFormat.getBitsPerPixel(parameters.getPreviewFormat())) / 8;
+    }
+
+    private void setPreviewSize(int screenWidth, int screenHeight, Parameters parameters) {
+        String previewSizeValuesString = parameters.get("preview-size-values");
+        if (previewSizeValuesString == null) {
+            previewSizeValuesString = parameters.get("preview-size-value");
+        }
+        Point bestPreviewSize = null;
+        if (previewSizeValuesString != null) {
+            bestPreviewSize = findBestPreviewSize(previewSizeValuesString, screenWidth, screenHeight);
+        }
+        if (bestPreviewSize != null) {
+            parameters.setPreviewSize(bestPreviewSize.x, bestPreviewSize.y);
+        } else {
+            parameters.setPreviewSize((screenWidth >> 4) << 4, (screenHeight >> 1) << 1);
+        }
+    }
+
+    private static Point findBestPreviewSize(CharSequence previewSizeValuesString, int screenWidth, int screenHeight) {
+        int bestPreviewWidth = 0;
+        int bestPreviewHeight = 0;
+        int minDifference = Integer.MAX_VALUE;
+        for (String previewSizeValueString : COMMA_PATTERN.split(previewSizeValuesString)) {
+            String previewSizeValueString2 = previewSizeValueString.trim();
+            int separatorPosition = previewSizeValueString2.indexOf(120);
+            if (separatorPosition >= 0) {
+                try {
+                    int previewSizeValueWidth = Integer.parseInt(previewSizeValueString2.substring(0, separatorPosition));
+                    int previewSizeValueHeight = Integer.parseInt(previewSizeValueString2.substring(separatorPosition + 1));
+                    int difference = Math.abs(previewSizeValueWidth - screenWidth) + Math.abs(previewSizeValueHeight - screenHeight);
+                    if (difference == 0) {
+                        bestPreviewWidth = previewSizeValueWidth;
+                        bestPreviewHeight = previewSizeValueHeight;
+                        break;
+                    } else if (difference < minDifference) {
+                        bestPreviewWidth = previewSizeValueWidth;
+                        bestPreviewHeight = previewSizeValueHeight;
+                        minDifference = difference;
+                    }
+                } catch (NumberFormatException e) {
+                }
+            }
+        }
+        if (bestPreviewWidth <= 0 || bestPreviewHeight <= 0) {
+            return null;
+        }
+        Log.e(TAG,"bestPreviewWidth="+bestPreviewWidth+",bestPreviewHeight="+bestPreviewHeight);
+        return new Point(bestPreviewWidth, bestPreviewHeight);
+    }
+
+    private void setZoom(Parameters parameters) {
+        String zoomSupportedString = parameters.get("zoom-supported");
+        if (zoomSupportedString == null || Boolean.parseBoolean(zoomSupportedString)) {
+            int maxZoomX10;
+            int desiredZoomX10 = DESIRED_ZOOM_X10;
+            String maxZoomString = parameters.get("max-zoom");
+            if (maxZoomString != null) {
+                try {
+                    maxZoomX10 = (int) (10.0d * Double.parseDouble(maxZoomString));
+                    if (DESIRED_ZOOM_X10 > maxZoomX10) {
+                        desiredZoomX10 = maxZoomX10;
+                    }
+                } catch (NumberFormatException e) {
+                }
+            }
+            String takingPictureZoomMaxString = parameters.get("taking-picture-zoom-max");
+            if (takingPictureZoomMaxString != null) {
+                try {
+                    maxZoomX10 = Integer.parseInt(takingPictureZoomMaxString);
+                    if (desiredZoomX10 > maxZoomX10) {
+                        desiredZoomX10 = maxZoomX10;
+                    }
+                } catch (NumberFormatException e2) {
+                }
+            }
+            String motZoomValuesString = parameters.get("mot-zoom-values");
+            if (motZoomValuesString != null) {
+                desiredZoomX10 = findBestMotZoomX10(motZoomValuesString, desiredZoomX10);
+            }
+            String motZoomStepString = parameters.get("mot-zoom-step");
+            if (motZoomStepString != null) {
+                try {
+                    int motZoomStepX10 = (int) (10.0d * Double.parseDouble(motZoomStepString.trim()));
+                    if (motZoomStepX10 > 1) {
+                        desiredZoomX10 -= desiredZoomX10 % motZoomStepX10;
+                    }
+                } catch (NumberFormatException e3) {
+                }
+            }
+            if (!(maxZoomString == null && motZoomValuesString == null)) {
+                parameters.set("zoom", String.valueOf(((double) desiredZoomX10) / 10.0d));
+            }
+            if (takingPictureZoomMaxString != null) {
+                parameters.set("taking-picture-zoom", desiredZoomX10);
+            }
+        }
+    }
+
+    private static int findBestMotZoomX10(CharSequence motZoomValuesString, int desiredZoomX10) {
+        int bestMotZoomX10 = 0;
+        String[] split = COMMA_PATTERN.split(motZoomValuesString);
+        int length = split.length;
+        int i = 0;
+        while (i < length) {
+            try {
+                int motZoomValueX10 = (int) (10.0d * Double.parseDouble(split[i].trim()));
+                if (Math.abs(desiredZoomX10 - motZoomValueX10) < Math.abs(desiredZoomX10 - bestMotZoomX10)) {
+                    bestMotZoomX10 = motZoomValueX10;
+                }
+                i++;
+            } catch (NumberFormatException e) {
+                return desiredZoomX10;
+            }
+        }
+        return bestMotZoomX10;
+    }
+    /*private void setCameraParameters(int screenWidth, int screenHeight) {
+        Parameters parameters = this.mCamera.getParameters();
+        setPreviewSize(screenWidth, screenHeight, parameters);
+        parameters.set("flash-mode", "off");
+        parameters.set("flash-value", 2);
+        setZoom(parameters);
+        int apiLevel = Integer.parseInt(VERSION.SDK);
+        if (apiLevel <= 3) {
+            this.mHasCameraAutoFocus = true;
+        } else if (apiLevel >= 5) {
+            String focusModeValues = parameters.get("focus-mode-values");
+            if (focusModeValues != null && focusModeValues.contains("macro")) {
+                parameters.set("focus-mode", "macro");
+                this.mHasCameraAutoFocus = true;
+            } else if (focusModeValues == null || !focusModeValues.contains("auto")) {
+                this.mHasCameraAutoFocus = false;
+            } else {
+                parameters.set("focus-mode", "auto");
+                this.mHasCameraAutoFocus = true;
+            }
+        } else {
+            String model = Build.MODEL.toLowerCase();
+            if (model.contains("devour") || model.contains("tattoo")) {
+                this.mHasCameraAutoFocus = false;
+            } else {
+                this.mHasCameraAutoFocus = true;
+            }
+        }
+        this.mCamera.setParameters(parameters);
+        this.mPreviewSize = parameters.getPreviewSize();
+    }
+
+    private void setPreviewSize(int screenWidth, int screenHeight, Parameters parameters) {
+        String previewSizeValuesString = parameters.get("preview-size-values");
+        if (previewSizeValuesString == null) {
+            previewSizeValuesString = parameters.get("preview-size-value");
+        }
+        Point bestPreviewSize = null;
+        if (previewSizeValuesString != null) {
+            bestPreviewSize = findBestPreviewSize(previewSizeValuesString, screenWidth, screenHeight);
+        }
+        if (bestPreviewSize != null) {
+            parameters.setPreviewSize(bestPreviewSize.x, bestPreviewSize.y);
+        } else {
+            parameters.setPreviewSize((screenWidth >> 3) << 3, (screenHeight >> 3) << 3);
+        }
+    }
+
+    private static Point findBestPreviewSize(CharSequence previewSizeValuesString, int screenWidth, int screenHeight) {
+        int bestPreviewWidth = 0;
+        int bestPreviewHeight = 0;
+        int minDifference = Integer.MAX_VALUE;
+        for (String previewSizeValueString : COMMA_PATTERN.split(previewSizeValuesString)) {
+            String previewSizeValueString2 = previewSizeValueString.trim();
+            int separatorPosition = previewSizeValueString2.indexOf(120);
+            if (separatorPosition >= 0) {
+                try {
+                    int previewSizeValueWidth = Integer.parseInt(previewSizeValueString2.substring(0, separatorPosition));
+                    int previewSizeValueHeight = Integer.parseInt(previewSizeValueString2.substring(separatorPosition + 1));
+                    int difference = Math.abs(previewSizeValueWidth - screenWidth) + Math.abs(previewSizeValueHeight - screenHeight);
+                    if (difference == 0) {
+                        bestPreviewWidth = previewSizeValueWidth;
+                        bestPreviewHeight = previewSizeValueHeight;
+                        break;
+                    } else if (difference < minDifference) {
+                        bestPreviewWidth = previewSizeValueWidth;
+                        bestPreviewHeight = previewSizeValueHeight;
+                        minDifference = difference;
+                    }
+                } catch (NumberFormatException e) {
+                }
+            }
+        }
+        if (bestPreviewWidth <= 0 || bestPreviewHeight <= 0) {
+            return null;
+        }
+        return new Point(bestPreviewWidth, bestPreviewHeight);
+    }
+
+    private void setZoom(Parameters parameters) {
+        String zoomSupportedString = parameters.get("zoom-supported");
+        if (zoomSupportedString == null || Boolean.parseBoolean(zoomSupportedString)) {
+            int maxZoomX10;
+            int desiredZoomX10 = DESIRED_ZOOM_X10;
+            String maxZoomString = parameters.get("max-zoom");
+            if (maxZoomString != null) {
+                try {
+                    maxZoomX10 = (int) (10.0d * Double.parseDouble(maxZoomString));
+                    if (DESIRED_ZOOM_X10 > maxZoomX10) {
+                        desiredZoomX10 = maxZoomX10;
+                    }
+                } catch (NumberFormatException e) {
+                }
+            }
+            String takingPictureZoomMaxString = parameters.get("taking-picture-zoom-max");
+            if (takingPictureZoomMaxString != null) {
+                try {
+                    maxZoomX10 = Integer.parseInt(takingPictureZoomMaxString);
+                    if (desiredZoomX10 > maxZoomX10) {
+                        desiredZoomX10 = maxZoomX10;
+                    }
+                } catch (NumberFormatException e2) {
+                }
+            }
+            String motZoomValuesString = parameters.get("mot-zoom-values");
+            if (motZoomValuesString != null) {
+                desiredZoomX10 = findBestMotZoomX10(motZoomValuesString, desiredZoomX10);
+            }
+            String motZoomStepString = parameters.get("mot-zoom-step");
+            if (motZoomStepString != null) {
+                try {
+                    int motZoomStepX10 = (int) (10.0d * Double.parseDouble(motZoomStepString.trim()));
+                    if (motZoomStepX10 > 1) {
+                        desiredZoomX10 -= desiredZoomX10 % motZoomStepX10;
+                    }
+                } catch (NumberFormatException e3) {
+                }
+            }
+            if (!(maxZoomString == null && motZoomValuesString == null)) {
+                parameters.set("zoom", String.valueOf(((double) desiredZoomX10) / 10.0d));
+            }
+            if (takingPictureZoomMaxString != null) {
+                parameters.set("taking-picture-zoom", desiredZoomX10);
+            }
+        }
+    }
+
+    private static int findBestMotZoomX10(CharSequence motZoomValuesString, int desiredZoomX10) {
+        int bestMotZoomX10 = 0;
+        String[] split = COMMA_PATTERN.split(motZoomValuesString);
+        int length = split.length;
+        int i = 0;
+        while (i < length) {
+            try {
+                int motZoomValueX10 = (int) (10.0d * Double.parseDouble(split[i].trim()));
+                if (Math.abs(desiredZoomX10 - motZoomValueX10) < Math.abs(desiredZoomX10 - bestMotZoomX10)) {
+                    bestMotZoomX10 = motZoomValueX10;
+                }
+                i++;
+            } catch (NumberFormatException e) {
+                return desiredZoomX10;
+            }
+        }
+        return bestMotZoomX10;
+    }*/
+
+    static {
+        TAG = ScannerLiveView.class.getSimpleName();
+        COMMA_PATTERN = Pattern.compile(",");
+    }
+}
diff --git a/platforms/android/app/src/main/java/com/visionsmarts/pic2shop/view/ScannerLiveViewLiner.java b/platforms/android/app/src/main/java/com/visionsmarts/pic2shop/view/ScannerLiveViewLiner.java
new file mode 100644
index 0000000..08a211c
--- /dev/null
+++ b/platforms/android/app/src/main/java/com/visionsmarts/pic2shop/view/ScannerLiveViewLiner.java
@@ -0,0 +1,601 @@
+package com.visionsmarts.pic2shop.view;
+
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.ImageFormat;
+import android.graphics.Point;
+import android.hardware.Camera;
+import android.hardware.Camera.AutoFocusCallback;
+import android.hardware.Camera.CameraInfo;
+import android.hardware.Camera.Parameters;
+import android.hardware.Camera.PreviewCallback;
+import android.hardware.Camera.Size;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.SurfaceHolder;
+import android.view.SurfaceHolder.Callback;
+import android.view.SurfaceView;
+
+import com.visionsmarts.VSBarcodeReader;
+import com.visionsmarts.VSBarcodeReader.DecoderValues;
+import com.visionsmarts.VSReaderQR;
+
+import java.io.IOException;
+import java.util.regex.Pattern;
+
+public class ScannerLiveViewLiner extends SurfaceView implements Callback {
+    private static final int BARCODE_TYPES_MASK = 7;
+    private static final Pattern COMMA_PATTERN;
+    private static final int DESIRED_ZOOM_X10 = 27;
+    private static final String TAG;
+    private AutoFocusCallback mAutoFocusCallback;
+    private volatile byte[] mCallbackBuffer;
+    private volatile Camera mCamera;
+    private volatile int mCameraDisplayOrientation;
+    private DecodingThread mDecodingThread;
+    volatile boolean mFoundBarcodeOrQRCode;
+    volatile byte[] mFrameData;
+    volatile boolean mFrameDataIsAutoFocusInProgress;
+    volatile boolean mHasCameraAutoFocus;
+    volatile boolean mIsAutoFocusInProgress;
+    volatile boolean mIsPreviewStarted;
+    Listener mListener;
+    private PreviewCallback mPreviewCallback;
+    private int mPreviewFrameSize;
+    volatile Size mPreviewSize;
+    final ScannerHandler mScannerHandler;
+    ScannerOverlay mScannerOverlay;
+
+    /* renamed from: com.visionsmarts.pic2shop.view.ScannerLiveViewLiner.1 */
+    class C01731 implements AutoFocusCallback {
+        C01731() {
+        }
+
+        public void onAutoFocus(boolean success, Camera camera) {
+            ScannerLiveViewLiner.this.mIsAutoFocusInProgress = false;
+        }
+    }
+
+    /* renamed from: com.visionsmarts.pic2shop.view.ScannerLiveViewLiner.2 */
+    class C01742 implements PreviewCallback {
+        C01742() {
+        }
+
+        public synchronized void onPreviewFrame(byte[] frameData, Camera camera) {
+            if (!(!ScannerLiveViewLiner.this.mIsPreviewStarted || ScannerLiveViewLiner.this.mDecodingThread == null || ScannerLiveViewLiner.this.mFoundBarcodeOrQRCode)) {
+                boolean shouldSendDecodeRequest = ScannerLiveViewLiner.this.mFrameData == null;
+                ScannerLiveViewLiner.this.mFrameData = frameData;
+                ScannerLiveViewLiner.this.mFrameDataIsAutoFocusInProgress = ScannerLiveViewLiner.this.mIsAutoFocusInProgress;
+                if (shouldSendDecodeRequest) {
+                    ScannerLiveViewLiner.this.mDecodingThread.getHandler().obtainMessage(BarQrCodeUtil.DECODE).sendToTarget();
+                }
+            }
+        }
+    }
+
+    private class DecodingThread extends Thread {
+        DecoderValues mBarcodeDecoderValues;
+        private Handler mHandler;
+        private int mNumberConsecutiveFailedDecodingSinceFocusEnded;
+        private byte[] mPreviewLine;
+        VSReaderQR.DecoderValues mQRDecoderValues;
+
+        /* renamed from: com.visionsmarts.pic2shop.view.ScannerLiveViewLiner.DecodingThread.1 */
+        class C01751 extends Handler {
+            C01751() {
+            }
+
+            public void handleMessage(Message message) {
+                switch (message.what) {
+                    case BarQrCodeUtil.DECODE:
+                        if (ScannerLiveViewLiner.this.mIsPreviewStarted && !ScannerLiveViewLiner.this.mFoundBarcodeOrQRCode) {
+                            DecodingThread.this.decode();
+                        }
+                        break;
+                    case BarQrCodeUtil.QUIT:
+                        Looper.myLooper().quit();
+                        break;
+                    default:
+                }
+            }
+        }
+
+        public DecodingThread() {
+            this.mNumberConsecutiveFailedDecodingSinceFocusEnded = 0;
+            this.mBarcodeDecoderValues = new DecoderValues();
+            this.mQRDecoderValues = new VSReaderQR.DecoderValues();
+            setPriority(10);
+            initialize();
+        }
+
+        synchronized Handler getHandler() {
+            if (this.mHandler == null) {
+                try {
+                    ScannerLiveViewLiner.this.mDecodingThread.wait(1000);
+                } catch (InterruptedException e) {
+                }
+            }
+            return this.mHandler;
+        }
+
+        public void initialize() {
+            if (ScannerLiveViewLiner.this.mPreviewSize != null && (this.mPreviewLine == null || this.mPreviewLine.length != ScannerLiveViewLiner.this.mPreviewSize.height)) {
+                this.mPreviewLine = new byte[ScannerLiveViewLiner.this.mPreviewSize.height];
+            }
+            this.mNumberConsecutiveFailedDecodingSinceFocusEnded = 0;
+            ScannerLiveViewLiner.this.mFoundBarcodeOrQRCode = false;
+            VSBarcodeReader.reset();
+        }
+
+        public void run() {
+            Looper.prepare();
+            synchronized (this) {
+                this.mHandler = new C01751();
+                notify();
+            }
+            Looper.loop();
+        }
+
+        @TargetApi(8)
+        private void decode() {
+            byte[] previewLine = this.mPreviewLine;
+            int width = ScannerLiveViewLiner.this.mPreviewSize.width;
+            int height = ScannerLiveViewLiner.this.mPreviewSize.height;
+            synchronized (ScannerLiveViewLiner.this.mPreviewCallback) {
+                if (ScannerLiveViewLiner.this.mFrameData == null) {
+                    return;
+                }
+                byte[] frameData = ScannerLiveViewLiner.this.mFrameData;
+                boolean wasAutoFocusInProgress = ScannerLiveViewLiner.this.mFrameDataIsAutoFocusInProgress;
+                int offset = Math.round(ScannerLiveViewLiner.this.mScannerOverlay.getNormalizedLaserLinePosition() * ((float) width));
+                Log.e(TAG,"offset="+offset);
+                int i = previewLine.length - 1;
+                while (i >= 0) {
+                    try {
+                        previewLine[i] = frameData[offset];
+                        offset += width;
+                        i--;
+                    } catch (ArrayIndexOutOfBoundsException e) {
+                        throw new ArrayIndexOutOfBoundsException(e.getMessage() + "; width=" + width + "; height=" + height + "; previewLine.length=" + previewLine.length + "; initOffset=" + Math.round(ScannerLiveViewLiner.this.mScannerOverlay.getNormalizedLaserLinePosition() * ((float) width)));
+                    }
+                }
+                if (ScannerLiveViewLiner.this.mFrameData != null) {
+                    String barcode = VSBarcodeReader.decodeNextImage(previewLine, ScannerLiveViewLiner.this.mHasCameraAutoFocus ? 1 : 0, ScannerLiveViewLiner.BARCODE_TYPES_MASK, this.mBarcodeDecoderValues);
+                    if (ScannerLiveViewLiner.this.mFrameData != null) {
+                        if (this.mBarcodeDecoderValues.left >= 0) {
+                            int left = this.mBarcodeDecoderValues.left;
+                            int right = this.mBarcodeDecoderValues.right;
+                            float lineLength = (float) previewLine.length;
+                            if (ScannerLiveViewLiner.this.mCameraDisplayOrientation == 180) {
+                                ScannerLiveViewLiner.this.mScannerOverlay.setNormalizedBarcodeLocation(((float) (height - right)) / lineLength, ((float) (height - left)) / lineLength);
+                            } else {
+                                ScannerLiveViewLiner.this.mScannerOverlay.setNormalizedBarcodeLocation(((float) left) / lineLength, ((float) right) / lineLength);
+                            }
+                        } else {
+                            ScannerLiveViewLiner.this.mScannerOverlay.setNoBarcodeLocation();
+                        }
+                        if (barcode.length() > 0) {
+                            ScannerLiveViewLiner.this.mFoundBarcodeOrQRCode = true;
+                            ScannerLiveViewLiner.this.mScannerHandler.obtainMessage(BarQrCodeUtil.BARCODE, barcode).sendToTarget();
+                        } else {
+                            byte[] qrData = VSReaderQR.decodeImage(frameData, width, height, this.mQRDecoderValues);
+                            if (qrData.length > 0) {
+                                ScannerLiveViewLiner.this.mFoundBarcodeOrQRCode = true;
+                                ScannerLiveViewLiner.this.mScannerHandler.obtainMessage(BarQrCodeUtil.QRCODE, qrData).sendToTarget();
+                            } else if (wasAutoFocusInProgress) {
+                                this.mNumberConsecutiveFailedDecodingSinceFocusEnded = 0;
+                            } else {
+                                this.mNumberConsecutiveFailedDecodingSinceFocusEnded++;
+                                if (ScannerLiveViewLiner.this.mHasCameraAutoFocus && !ScannerLiveViewLiner.this.mIsAutoFocusInProgress && this.mNumberConsecutiveFailedDecodingSinceFocusEnded >= 4) {
+                                    ScannerLiveViewLiner.this.mScannerHandler.obtainMessage(BarQrCodeUtil.AUTO_FOCUS).sendToTarget();
+                                }
+                            }
+                        }
+                        synchronized (ScannerLiveViewLiner.this.mPreviewCallback) {
+                            ScannerLiveViewLiner.this.mFrameData = null;
+                            if (!(ScannerLiveViewLiner.this.mFoundBarcodeOrQRCode || ScannerLiveViewLiner.this.mCallbackBuffer == null)) {
+                                ScannerLiveViewLiner.this.mCamera.addCallbackBuffer(ScannerLiveViewLiner.this.mCallbackBuffer);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    public interface Listener {
+        void onCameraIssue();
+
+        void onCodeScanned(String str, String str2);
+    }
+
+    private class ScannerHandler extends Handler {
+        private ScannerHandler() {
+        }
+
+        public void handleMessage(Message message) {
+            switch (message.what) {
+                case BarQrCodeUtil.AUTO_FOCUS:
+                    ScannerLiveViewLiner.this.requestAutoFocus();
+                    break;
+                case BarQrCodeUtil.BARCODE:
+                    if (ScannerLiveViewLiner.this.mIsPreviewStarted) {
+                        ScannerLiveViewLiner.this.stopCamera();
+                        ScannerLiveViewLiner.this.mListener.onCodeScanned("BAR", (String)message.obj);
+                    }
+                    break;
+                case BarQrCodeUtil.QRCODE:
+                    if (ScannerLiveViewLiner.this.mIsPreviewStarted) {
+                        ScannerLiveViewLiner.this.stopCamera();
+                        ScannerLiveViewLiner.this.mListener.onCodeScanned("QR", BarQrCodeUtil.qrToString((byte[])message.obj));
+                    }
+                    break;
+                default:
+            }
+        }
+    }
+
+    public ScannerLiveViewLiner(Context context) {
+        super(context);
+        this.mPreviewFrameSize = 0;
+        this.mScannerHandler = new ScannerHandler();
+        this.mIsPreviewStarted = false;
+        this.mIsAutoFocusInProgress = false;
+        this.mFrameData = null;
+        this.mFrameDataIsAutoFocusInProgress = false;
+        this.mFoundBarcodeOrQRCode = false;
+        initialize(context);
+    }
+
+    public ScannerLiveViewLiner(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        this.mPreviewFrameSize = 0;
+        this.mScannerHandler = new ScannerHandler();
+        this.mIsPreviewStarted = false;
+        this.mIsAutoFocusInProgress = false;
+        this.mFrameData = null;
+        this.mFrameDataIsAutoFocusInProgress = false;
+        this.mFoundBarcodeOrQRCode = false;
+        initialize(context);
+    }
+
+    public ScannerLiveViewLiner(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        this.mPreviewFrameSize = 0;
+        this.mScannerHandler = new ScannerHandler();
+        this.mIsPreviewStarted = false;
+        this.mIsAutoFocusInProgress = false;
+        this.mFrameData = null;
+        this.mFrameDataIsAutoFocusInProgress = false;
+        this.mFoundBarcodeOrQRCode = false;
+        initialize(context);
+    }
+
+    private void initialize(Context context) {
+        this.mListener = (Listener) context;
+        SurfaceHolder holder = getHolder();
+        holder.addCallback(this);
+        holder.setType(3);
+        holder.setKeepScreenOn(true);
+        this.mAutoFocusCallback = new C01731();
+        this.mPreviewCallback = new C01742();
+    }
+
+    @TargetApi(9)
+    public void surfaceCreated(SurfaceHolder holder) {
+        if (holder == null) {
+            throw new IllegalStateException("No SurfaceHolder provided");
+        } else if (this.mCamera == null) {
+            try {
+                this.mCamera = null;
+                try {
+                    CameraInfo cameraInfo = new CameraInfo();
+                    int cameraCount = Camera.getNumberOfCameras();
+                    for (int camIdx = 0; camIdx < cameraCount; camIdx++) {
+                        Camera.getCameraInfo(camIdx, cameraInfo);
+                        if (cameraInfo.facing == 0) {
+                            this.mCamera = Camera.open(camIdx);
+                            setCameraDisplayOrientation(camIdx);
+                            break;
+                        }
+                    }
+                } catch (LinkageError e) {
+                }
+                if (this.mCamera == null) {
+                    try {
+                        this.mCamera = Camera.open(0);
+                        setCameraDisplayOrientation(0);
+                    } catch (LinkageError e2) {
+                    }
+                }
+                if (this.mCamera == null) {
+                    this.mCamera = Camera.open();
+                }
+                this.mCamera.setPreviewDisplay(holder);
+                this.mIsPreviewStarted = false;
+            } catch (IOException e3) {
+                this.mListener.onCameraIssue();
+            } catch (RuntimeException e4) {
+                this.mListener.onCameraIssue();
+            }
+        }
+    }
+
+    public void surfaceDestroyed(SurfaceHolder holder) {
+        if (this.mCamera != null) {
+            stopCamera();
+            this.mPreviewFrameSize = 0;
+        }
+    }
+
+    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+        if (this.mCamera != null) {
+            stopCamera();
+            setCameraParameters(width, height);
+            if (isShown()) {
+                startCamera();
+            }
+        }
+    }
+
+    public void onPause() {
+        stopCamera();
+        if (this.mCamera != null) {
+            this.mCamera.release();
+            this.mCamera = null;
+        }
+        Message.obtain(this.mDecodingThread.getHandler(), BarQrCodeUtil.QUIT).sendToTarget();
+        try {
+            this.mDecodingThread.join();
+        } catch (InterruptedException e) {
+        }
+        this.mScannerHandler.removeMessages(BarQrCodeUtil.AUTO_FOCUS);
+        this.mScannerHandler.removeMessages(BarQrCodeUtil.BARCODE);
+        this.mScannerHandler.removeMessages(BarQrCodeUtil.QRCODE);
+        this.mDecodingThread = null;
+    }
+
+    @TargetApi(8)
+    public void startCamera() {
+        if (this.mCamera != null && !this.mIsPreviewStarted) {
+            this.mIsAutoFocusInProgress = false;
+            this.mFrameData = null;
+            if (this.mDecodingThread != null) {
+                this.mDecodingThread.initialize();
+            }
+            if (this.mScannerOverlay != null) {
+                this.mScannerOverlay.setNoBarcodeLocation();
+            }
+            if (this.mPreviewFrameSize > 0) {
+                try {
+                    this.mCallbackBuffer = new byte[this.mPreviewFrameSize];
+                } catch (OutOfMemoryError e) {
+                    this.mCallbackBuffer = null;
+                }
+            }
+            if (this.mCallbackBuffer != null) {
+                this.mCamera.setPreviewCallbackWithBuffer(this.mPreviewCallback);
+                this.mCamera.addCallbackBuffer(this.mCallbackBuffer);
+            } else {
+                this.mCamera.setPreviewCallback(this.mPreviewCallback);
+            }
+            try {
+                this.mCamera.startPreview();
+                this.mIsPreviewStarted = true;
+                requestAutoFocus();
+            } catch (RuntimeException e2) {
+                this.mCamera.setPreviewCallback(null);
+                this.mCallbackBuffer = null;
+                this.mListener.onCameraIssue();
+            }
+        }
+    }
+
+    public void stopCamera() {
+        if (this.mCamera != null && this.mIsPreviewStarted) {
+            synchronized (this.mPreviewCallback) {
+                this.mCamera.setPreviewCallback(null);
+                this.mCamera.stopPreview();
+                this.mIsPreviewStarted = false;
+                this.mCamera.cancelAutoFocus();
+                this.mFrameData = null;
+                this.mCallbackBuffer = null;
+            }
+            if (!(this.mDecodingThread == null || this.mDecodingThread.getHandler() == null)) {
+                this.mDecodingThread.getHandler().removeMessages(BarQrCodeUtil.DECODE);
+            }
+            this.mScannerHandler.removeMessages(BarQrCodeUtil.AUTO_FOCUS);
+            this.mScannerHandler.removeMessages(BarQrCodeUtil.BARCODE);
+            this.mScannerHandler.removeMessages(BarQrCodeUtil.QRCODE);
+        }
+    }
+
+    void requestAutoFocus() {
+        if (this.mCamera != null && this.mHasCameraAutoFocus && this.mIsPreviewStarted && !this.mIsAutoFocusInProgress) {
+            try {
+                this.mCamera.autoFocus(this.mAutoFocusCallback);
+                this.mIsAutoFocusInProgress = true;
+            } catch (RuntimeException e) {
+                Log.e(TAG, "Camera auto-focus failed: " + e.getLocalizedMessage());
+            }
+        }
+    }
+
+    @TargetApi(9)
+    public void setCameraDisplayOrientation(int cameraId) {
+        CameraInfo info = new CameraInfo();
+        Camera.getCameraInfo(cameraId, info);
+        int degrees = 0;
+        switch (((Activity) getContext()).getWindowManager().getDefaultDisplay().getRotation()) {
+            case 0 /*0*/:
+                degrees = 0;
+                break;
+            case 1 /*1*/:
+                degrees = 90;
+                break;
+            case 2 /*2*/:
+                degrees = 180;
+                break;
+            case 3 /*3*/:
+                degrees = 270;
+                break;
+        }
+        if (info.facing == 1) {
+            this.mCameraDisplayOrientation = (info.orientation + degrees) % 360;
+            this.mCameraDisplayOrientation = (360 - this.mCameraDisplayOrientation) % 360;
+        } else {
+            this.mCameraDisplayOrientation = ((info.orientation - degrees) + 360) % 360;
+        }
+        this.mCamera.setDisplayOrientation(this.mCameraDisplayOrientation);
+    }
+
+    @TargetApi(8)
+    private void setCameraParameters(int screenWidth, int screenHeight) {
+        Log.e(TAG,"screenWidth="+screenWidth+",screenHeight="+screenHeight);
+        Parameters parameters = this.mCamera.getParameters();
+        setPreviewSize(screenWidth, screenHeight, parameters);
+        setZoom(parameters);
+        String focusModeValues = parameters.get("focus-mode-values");
+        if (focusModeValues != null && focusModeValues.contains("macro")) {
+            parameters.set("focus-mode", "macro");
+            this.mHasCameraAutoFocus = true;
+        } else if (focusModeValues == null || !focusModeValues.contains("auto")) {
+            this.mHasCameraAutoFocus = false;
+        } else {
+            parameters.set("focus-mode", "auto");
+            this.mHasCameraAutoFocus = true;
+        }
+        try {
+            this.mCamera.setParameters(parameters);
+        } catch (RuntimeException e) {
+            this.mListener.onCameraIssue();
+        }
+        parameters = this.mCamera.getParameters();
+        this.mPreviewSize = parameters.getPreviewSize();
+        this.mPreviewFrameSize = ((this.mPreviewSize.width * this.mPreviewSize.height) * ImageFormat.getBitsPerPixel(parameters.getPreviewFormat())) / 8;
+    }
+
+    private void setPreviewSize(int screenWidth, int screenHeight, Parameters parameters) {
+        String previewSizeValuesString = parameters.get("preview-size-values");
+        if (previewSizeValuesString == null) {
+            previewSizeValuesString = parameters.get("preview-size-value");
+        }
+        Point bestPreviewSize = null;
+        if (previewSizeValuesString != null) {
+            bestPreviewSize = findBestPreviewSize(previewSizeValuesString, screenWidth, screenHeight);
+        }
+        if (bestPreviewSize != null) {
+            parameters.setPreviewSize(bestPreviewSize.x, bestPreviewSize.y);
+        } else {
+            parameters.setPreviewSize((screenWidth >> 4) << 4, (screenHeight >> 1) << 1);
+        }
+    }
+
+    private static Point findBestPreviewSize(CharSequence previewSizeValuesString, int screenWidth, int screenHeight) {
+        int bestPreviewWidth = 0;
+        int bestPreviewHeight = 0;
+        int minDifference = Integer.MAX_VALUE;
+        for (String previewSizeValueString : COMMA_PATTERN.split(previewSizeValuesString)) {
+            String previewSizeValueString2 = previewSizeValueString.trim();
+            int separatorPosition = previewSizeValueString2.indexOf(120);
+            if (separatorPosition >= 0) {
+                try {
+                    int previewSizeValueWidth = Integer.parseInt(previewSizeValueString2.substring(0, separatorPosition));
+                    int previewSizeValueHeight = Integer.parseInt(previewSizeValueString2.substring(separatorPosition + 1));
+                    int difference = Math.abs(previewSizeValueWidth - screenWidth) + Math.abs(previewSizeValueHeight - screenHeight);
+                    if (difference == 0) {
+                        bestPreviewWidth = previewSizeValueWidth;
+                        bestPreviewHeight = previewSizeValueHeight;
+                        break;
+                    } else if (difference < minDifference) {
+                        bestPreviewWidth = previewSizeValueWidth;
+                        bestPreviewHeight = previewSizeValueHeight;
+                        minDifference = difference;
+                    }
+                } catch (NumberFormatException e) {
+                }
+            }
+        }
+        if (bestPreviewWidth <= 0 || bestPreviewHeight <= 0) {
+            return null;
+        }
+        Log.e(TAG,"bestPreviewWidth="+bestPreviewWidth+",bestPreviewHeight="+bestPreviewHeight);
+        return new Point(bestPreviewWidth, bestPreviewHeight);
+    }
+
+    private void setZoom(Parameters parameters) {
+        String zoomSupportedString = parameters.get("zoom-supported");
+        if (zoomSupportedString == null || Boolean.parseBoolean(zoomSupportedString)) {
+            int maxZoomX10;
+            int desiredZoomX10 = DESIRED_ZOOM_X10;
+            String maxZoomString = parameters.get("max-zoom");
+            if (maxZoomString != null) {
+                try {
+                    maxZoomX10 = (int) (10.0d * Double.parseDouble(maxZoomString));
+                    if (DESIRED_ZOOM_X10 > maxZoomX10) {
+                        desiredZoomX10 = maxZoomX10;
+                    }
+                } catch (NumberFormatException e) {
+                }
+            }
+            String takingPictureZoomMaxString = parameters.get("taking-picture-zoom-max");
+            if (takingPictureZoomMaxString != null) {
+                try {
+                    maxZoomX10 = Integer.parseInt(takingPictureZoomMaxString);
+                    if (desiredZoomX10 > maxZoomX10) {
+                        desiredZoomX10 = maxZoomX10;
+                    }
+                } catch (NumberFormatException e2) {
+                }
+            }
+            String motZoomValuesString = parameters.get("mot-zoom-values");
+            if (motZoomValuesString != null) {
+                desiredZoomX10 = findBestMotZoomX10(motZoomValuesString, desiredZoomX10);
+            }
+            String motZoomStepString = parameters.get("mot-zoom-step");
+            if (motZoomStepString != null) {
+                try {
+                    int motZoomStepX10 = (int) (10.0d * Double.parseDouble(motZoomStepString.trim()));
+                    if (motZoomStepX10 > 1) {
+                        desiredZoomX10 -= desiredZoomX10 % motZoomStepX10;
+                    }
+                } catch (NumberFormatException e3) {
+                }
+            }
+            if (!(maxZoomString == null && motZoomValuesString == null)) {
+                parameters.set("zoom", String.valueOf(((double) desiredZoomX10) / 10.0d));
+            }
+            if (takingPictureZoomMaxString != null) {
+                parameters.set("taking-picture-zoom", desiredZoomX10);
+            }
+        }
+    }
+
+    private static int findBestMotZoomX10(CharSequence motZoomValuesString, int desiredZoomX10) {
+        int bestMotZoomX10 = 0;
+        String[] split = COMMA_PATTERN.split(motZoomValuesString);
+        int length = split.length;
+        int i = 0;
+        while (i < length) {
+            try {
+                int motZoomValueX10 = (int) (10.0d * Double.parseDouble(split[i].trim()));
+                if (Math.abs(desiredZoomX10 - motZoomValueX10) < Math.abs(desiredZoomX10 - bestMotZoomX10)) {
+                    bestMotZoomX10 = motZoomValueX10;
+                }
+                i++;
+            } catch (NumberFormatException e) {
+                return desiredZoomX10;
+            }
+        }
+        return bestMotZoomX10;
+    }
+
+    static {
+        TAG = ScannerLiveViewLiner.class.getSimpleName();
+        COMMA_PATTERN = Pattern.compile(",");
+    }
+}
diff --git a/platforms/android/app/src/main/java/com/visionsmarts/pic2shop/view/ScannerOverlay.java b/platforms/android/app/src/main/java/com/visionsmarts/pic2shop/view/ScannerOverlay.java
new file mode 100644
index 0000000..696fe7d
--- /dev/null
+++ b/platforms/android/app/src/main/java/com/visionsmarts/pic2shop/view/ScannerOverlay.java
@@ -0,0 +1,124 @@
+package com.visionsmarts.pic2shop.view;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Paint.Align;
+import android.graphics.Paint.Style;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.graphics.Typeface;
+import android.text.Layout.Alignment;
+import android.text.StaticLayout;
+import android.text.TextPaint;
+import android.util.AttributeSet;
+import android.view.Display;
+import android.view.View;
+import android.view.WindowManager;
+
+public class ScannerOverlay extends View {
+    private static final float LASER_LINE_WIDTH_160_DPI = 7.0f;
+    private static final float TEXT_FONT_SIZE = 20.0f;
+    private Paint mBarcodeLinePaint;
+    private Rect mBarcodeLineRect;
+    private Rect mCanvasClipRect;
+    private Paint mLaserLinePaint;
+    private int mLaserLinePosition;
+    private Rect mLaserLineRect;
+    private float mScreenDensity;
+    private Point mScreenResolution;
+    private Paint mTextBackgroundPaint;
+    private StaticLayout mTextLayout;
+
+    public ScannerOverlay(Context context) {
+        super(context);
+        this.mCanvasClipRect = new Rect();
+        this.mLaserLineRect = new Rect();
+        this.mBarcodeLineRect = new Rect(-1, -1, -1, -1);
+        initialize(context);
+    }
+
+    public ScannerOverlay(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        this.mCanvasClipRect = new Rect();
+        this.mLaserLineRect = new Rect();
+        this.mBarcodeLineRect = new Rect(-1, -1, -1, -1);
+        initialize(context);
+    }
+
+    public ScannerOverlay(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        this.mCanvasClipRect = new Rect();
+        this.mLaserLineRect = new Rect();
+        this.mBarcodeLineRect = new Rect(-1, -1, -1, -1);
+        initialize(context);
+    }
+
+    private void initialize(Context context) {
+        this.mTextBackgroundPaint = new Paint();
+        this.mTextBackgroundPaint.setStyle(Style.FILL);
+        this.mTextBackgroundPaint.setColor(Color.GREEN);
+        this.mTextBackgroundPaint.setAlpha(204);
+        TextPaint textPaint = new TextPaint();
+        textPaint.setStyle(Style.FILL);
+        textPaint.setStrokeWidth(1.0f);
+        textPaint.setColor(-1);
+        textPaint.setAlpha(204);
+        textPaint.setAntiAlias(true);
+        textPaint.setTypeface(Typeface.DEFAULT_BOLD);
+        textPaint.setTextSize(TEXT_FONT_SIZE * context.getResources().getDisplayMetrics().scaledDensity);
+        textPaint.setTextAlign(Align.CENTER);
+        this.mTextLayout = new StaticLayout("将二维码/条形码放入框内, 即可自动扫描", textPaint, context.getResources().getDisplayMetrics().heightPixels, Alignment.ALIGN_NORMAL, 1.0f, 0.0f, true);
+        this.mLaserLinePaint = new Paint();
+        this.mLaserLinePaint.setStyle(Style.FILL);
+        this.mLaserLinePaint.setColor(-65536);
+        this.mLaserLinePaint.setAlpha(255);
+        this.mBarcodeLinePaint = new Paint();
+        this.mBarcodeLinePaint.setStyle(Style.FILL);
+        this.mBarcodeLinePaint.setColor(-16711936);
+        this.mBarcodeLinePaint.setAlpha(255);
+        Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
+        this.mScreenResolution = new Point(display.getWidth(), display.getHeight());
+        this.mScreenDensity = getContext().getResources().getDisplayMetrics().density;
+        this.mLaserLinePosition = Math.round((float) (this.mScreenResolution.x / 2));
+    }
+
+    protected void onDraw(Canvas canvas) {
+        float center = ((float) canvas.getHeight()) / 2.0f;
+        canvas.rotate(-90.0f, center, center);
+        if (canvas.getClipBounds(this.mCanvasClipRect)) {
+            if (this.mCanvasClipRect.height() == canvas.getWidth()) {
+                canvas.drawRect(0.0f, (float) (this.mCanvasClipRect.bottom - this.mTextLayout.getHeight()), (float) this.mCanvasClipRect.right, (float) this.mCanvasClipRect.bottom, this.mTextBackgroundPaint);
+                canvas.save();
+                canvas.translate(this.mCanvasClipRect.exactCenterX(), (float) (this.mCanvasClipRect.bottom - this.mTextLayout.getHeight()));
+                this.mTextLayout.draw(canvas);
+                canvas.restore();
+                int lineWidth = Math.round(LASER_LINE_WIDTH_160_DPI * this.mScreenDensity);
+                this.mLaserLineRect.set(this.mCanvasClipRect.width() / 8, this.mLaserLinePosition - (lineWidth / 2), (this.mCanvasClipRect.width() * 7) / 8, this.mLaserLinePosition + ((lineWidth - 1) / 2));
+                this.mBarcodeLineRect.top = this.mLaserLineRect.top;
+                this.mBarcodeLineRect.bottom = this.mLaserLineRect.bottom;
+            }
+            canvas.drawRect(this.mLaserLineRect, this.mLaserLinePaint);
+            if (this.mBarcodeLineRect.left >= 0 && this.mBarcodeLineRect.right >= 0) {
+                canvas.drawRect(this.mBarcodeLineRect, this.mBarcodeLinePaint);
+            }
+        }
+    }
+
+    public float getNormalizedLaserLinePosition() {
+        return ((float) this.mLaserLinePosition) / ((float) this.mScreenResolution.x);
+    }
+
+    public void setNormalizedBarcodeLocation(float left, float right) {
+        this.mBarcodeLineRect.left = Math.round(((float) this.mScreenResolution.y) * left);
+        this.mBarcodeLineRect.right = Math.round(((float) this.mScreenResolution.y) * right);
+        postInvalidate(this.mLaserLineRect.top, 0, this.mLaserLineRect.bottom, this.mScreenResolution.y - 1);
+    }
+
+    public void setNoBarcodeLocation() {
+        this.mBarcodeLineRect.left = -1;
+        this.mBarcodeLineRect.right = -1;
+        postInvalidate(this.mLaserLineRect.top, 0, this.mLaserLineRect.bottom, this.mScreenResolution.y - 1);
+    }
+}
diff --git a/platforms/android/app/src/main/java/uk/co/whiteoctober/cordova/AppVersion.java b/platforms/android/app/src/main/java/uk/co/whiteoctober/cordova/AppVersion.java
new file mode 100644
index 0000000..204ed7e
--- /dev/null
+++ b/platforms/android/app/src/main/java/uk/co/whiteoctober/cordova/AppVersion.java
@@ -0,0 +1,45 @@
+package uk.co.whiteoctober.cordova;
+
+import org.apache.cordova.CordovaPlugin;
+import org.apache.cordova.CallbackContext;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.PackageManager;
+
+public class AppVersion extends CordovaPlugin {
+  @Override
+  public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
+
+    try {
+      if (action.equals("getAppName")) {
+        PackageManager packageManager = this.cordova.getActivity().getPackageManager();
+        ApplicationInfo app = packageManager.getApplicationInfo(this.cordova.getActivity().getPackageName(), 0);
+        callbackContext.success((String)packageManager.getApplicationLabel(app));
+        return true;
+      }
+      if (action.equals("getPackageName")) {
+        callbackContext.success(this.cordova.getActivity().getPackageName());
+        return true;
+      }
+      if (action.equals("getVersionNumber")) {
+        PackageManager packageManager = this.cordova.getActivity().getPackageManager();
+        callbackContext.success(packageManager.getPackageInfo(this.cordova.getActivity().getPackageName(), 0).versionName);
+      return true;
+      }
+      if (action.equals("getVersionCode")) {
+        PackageManager packageManager = this.cordova.getActivity().getPackageManager();
+        callbackContext.success(packageManager.getPackageInfo(this.cordova.getActivity().getPackageName(), 0).versionCode);
+      return true;
+      }
+      return false;
+    } catch (NameNotFoundException e) {
+      callbackContext.success("N/A");
+      return true;
+    }
+  }
+
+}
diff --git a/platforms/android/app/src/main/jniLibs/armeabi/libVSBarcodeReader.so b/platforms/android/app/src/main/jniLibs/armeabi/libVSBarcodeReader.so
new file mode 100644
index 0000000..aa3d33b
--- /dev/null
+++ b/platforms/android/app/src/main/jniLibs/armeabi/libVSBarcodeReader.so
Binary files differ
diff --git a/platforms/android/app/src/main/jniLibs/armeabi/libVSReaderQR.so b/platforms/android/app/src/main/jniLibs/armeabi/libVSReaderQR.so
new file mode 100644
index 0000000..f6cd34d
--- /dev/null
+++ b/platforms/android/app/src/main/jniLibs/armeabi/libVSReaderQR.so
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable/back.png b/platforms/android/app/src/main/res/drawable/back.png
new file mode 100644
index 0000000..51bac9f
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable/back.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/drawable/close.png b/platforms/android/app/src/main/res/drawable/close.png
new file mode 100644
index 0000000..3fb7db5
--- /dev/null
+++ b/platforms/android/app/src/main/res/drawable/close.png
Binary files differ
diff --git a/platforms/android/app/src/main/res/xml/config.xml b/platforms/android/app/src/main/res/xml/config.xml
index a0b93ed..cda74bc 100644
--- a/platforms/android/app/src/main/res/xml/config.xml
+++ b/platforms/android/app/src/main/res/xml/config.xml
@@ -1,5 +1,5 @@
 <?xml version='1.0' encoding='utf-8'?>
-<widget id="com.supwisdom.dlapp" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+<widget id="com.dalicitycard.app" version="1.0.4" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
     <feature name="Fingerprint">
         <param name="android-package" value="de.niklasmerz.cordova.fingerprint.Fingerprint" />
     </feature>
@@ -37,6 +37,9 @@
     <feature name="JPushPlugin">
         <param name="android-package" value="cn.jiguang.cordova.push.JPushPlugin" />
     </feature>
+    <feature name="AppVersion">
+        <param name="android-package" value="uk.co.whiteoctober.cordova.AppVersion" />
+    </feature>
     <name short="大理市民卡">dlapp</name>
     <description>
         A sample Apache Cordova application that responds to the deviceready event.
@@ -59,6 +62,9 @@
     <edit-config file="*-Info.plist" mode="merge" target="NSCameraUsageDescription">
         <string>APP需要使用您的相机权限,没有该权限将无法完成扫一扫功能</string>
     </edit-config>
+    <edit-config file="*-Info.plist" mode="merge" target="NSPhotoLibraryUsageDescription">
+        <string>APP需要使用您的相册权限,没有该权限将无法完成扫一扫功能</string>
+    </edit-config>
     <allow-intent href="market:*" />
     <preference name="loglevel" value="DEBUG" />
     <preference name="AutoHideSplashScreen" value="true" />
@@ -70,4 +76,5 @@
     <preference name="DisallowOverscroll" value="true" />
     <preference name="UIWebViewBounce" value="false" />
     <preference name="BackupWebStorage" value="local" />
+    <preference name="CordovaWebViewEngine" value="CDVWKWebViewEngine" />
 </widget>
diff --git a/platforms/android/cordova-plugin-qrscanner/dlapp-qrscanner.gradle b/platforms/android/cordova-plugin-qrscanner/dlapp-qrscanner.gradle
index df682e7..6188e34 100644
--- a/platforms/android/cordova-plugin-qrscanner/dlapp-qrscanner.gradle
+++ b/platforms/android/cordova-plugin-qrscanner/dlapp-qrscanner.gradle
@@ -3,8 +3,8 @@
 }
 
 dependencies {
-    compile 'com.journeyapps:zxing-android-embedded:3.3.0'
-    compile 'com.android.support:appcompat-v7:23.1.0'
+    implementation 'com.journeyapps:zxing-android-embedded:3.3.0'
+    implementation 'com.android.support:appcompat-v7:23.1.0'
 }
 
 android {
diff --git a/platforms/android/platform_www/cordova_plugins.js b/platforms/android/platform_www/cordova_plugins.js
index 595ecb1..ee6832d 100644
--- a/platforms/android/platform_www/cordova_plugins.js
+++ b/platforms/android/platform_www/cordova_plugins.js
@@ -327,6 +327,14 @@
       "clobbers": [
         "JPush"
       ]
+    },
+    {
+      "id": "cordova-plugin-app-version.AppVersionPlugin",
+      "file": "plugins/cordova-plugin-app-version/www/AppVersionPlugin.js",
+      "pluginId": "cordova-plugin-app-version",
+      "clobbers": [
+        "cordova.getAppVersion"
+      ]
     }
   ];
   module.exports.metadata = {
@@ -344,6 +352,8 @@
     "cordova-plugin-device": "2.0.2",
     "cordova-plugin-themeablebrowser": "0.2.17",
     "cordova-plugin-jcore": "1.3.0",
-    "jpush-phonegap-plugin": "3.7.2"
+    "jpush-phonegap-plugin": "3.7.2",
+    "cordova-plugin-app-version": "0.1.9",
+    "cordova-plugin-wkwebview-engine": "1.2.1"
   };
 });
\ No newline at end of file
diff --git a/platforms/android/platform_www/plugins/cordova-plugin-app-version/www/AppVersionPlugin.js b/platforms/android/platform_www/plugins/cordova-plugin-app-version/www/AppVersionPlugin.js
new file mode 100644
index 0000000..430f50d
--- /dev/null
+++ b/platforms/android/platform_www/plugins/cordova-plugin-app-version/www/AppVersionPlugin.js
@@ -0,0 +1,68 @@
+cordova.define("cordova-plugin-app-version.AppVersionPlugin", function(require, exports, module) {
+/*jslint indent: 2 */
+/*global window, jQuery, angular, cordova */
+"use strict";
+
+// Returns a jQuery or AngularJS deferred object, or pass a success and fail callbacks if you don't want to use jQuery or AngularJS
+var getPromisedCordovaExec = function (command, success, fail) {
+  var toReturn, deferred, injector, $q;
+  if (success === undefined) {
+    if (window.jQuery) {
+      deferred = jQuery.Deferred();
+      success = deferred.resolve;
+      fail = deferred.reject;
+      toReturn = deferred;
+    } else if (window.angular) {
+      injector = angular.injector(["ng"]);
+      $q = injector.get("$q");
+      deferred = $q.defer();
+      success = deferred.resolve;
+      fail = deferred.reject;
+      toReturn = deferred.promise;
+    } else if (window.when && window.when.promise) {
+      deferred = when.defer();
+      success = deferred.resolve;
+      fail = deferred.reject;
+      toReturn = deferred.promise;
+    } else if (window.Promise) {
+      toReturn = new Promise(function(c, e) {
+        success = c;
+        fail = e;
+      });
+    } else if (window.WinJS && window.WinJS.Promise) {
+      toReturn = new WinJS.Promise(function(c, e) {
+        success = c;
+        fail = e;
+      });
+    } else {
+      return console.error('AppVersion either needs a success callback, or jQuery/AngularJS/Promise/WinJS.Promise defined for using promises');
+    }
+  }
+  // 5th param is NOT optional. must be at least empty array
+  cordova.exec(success, fail, "AppVersion", command, []);
+  return toReturn;
+};
+
+var getAppVersion = function (success, fail) {
+  return getPromisedCordovaExec('getVersionNumber', success, fail);
+};
+
+getAppVersion.getAppName = function (success, fail) {
+  return getPromisedCordovaExec('getAppName', success, fail);
+};
+
+getAppVersion.getPackageName = function (success, fail) {
+  return getPromisedCordovaExec('getPackageName', success, fail);
+};
+
+getAppVersion.getVersionNumber = function (success, fail) {
+  return getPromisedCordovaExec('getVersionNumber', success, fail);
+};
+
+getAppVersion.getVersionCode = function (success, fail) {
+  return getPromisedCordovaExec('getVersionCode', success, fail);
+};
+
+module.exports = getAppVersion;
+
+});