Merge branch 'feature/init' into develop
diff --git a/app/.gitignore b/app/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/app/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/app/build.gradle b/app/build.gradle
new file mode 100644
index 0000000..e9986f9
--- /dev/null
+++ b/app/build.gradle
@@ -0,0 +1,76 @@
+plugins {
+ id 'com.gladed.androidgitversion' version '0.4.9'
+}
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-android-extensions'
+
+android {
+ compileSdkVersion 28
+ defaultConfig {
+ applicationId "com.supwisdom.posa711"
+ minSdkVersion 22
+ targetSdkVersion 28
+ versionCode 1
+ versionName "1.0"
+ ndk {
+ abiFilters "arm64-v8a"
+ }
+ multiDexEnabled true
+ }
+ signingConfigs {
+ release {
+ storeFile file("$rootDir/keys-app.jks")
+ storePassword "123456"
+ keyAlias "sup"
+ keyPassword "123456"
+ }
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+ compileOptions {
+ sourceCompatibility 1.8
+ targetCompatibility 1.8
+ }
+ packagingOptions {
+ exclude 'META-INF/DEPENDENCIES'
+ exclude 'META-INF/LICENSE'
+ exclude 'META-INF/LICENSE.txt'
+ exclude 'META-INF/license.txt'
+ exclude 'META-INF/NOTICE'
+ exclude 'META-INF/NOTICE.txt'
+ exclude 'META-INF/notice.txt'
+ exclude 'META-INF/ASL2.0'
+ }
+}
+
+dependencies {
+// implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+ implementation 'com.android.support:appcompat-v7:28.0.0'
+ implementation 'com.android.support.constraint:constraint-layout:1.1.3'
+ testImplementation 'junit:junit:4.12'
+ androidTestImplementation 'com.android.support.test:runner:1.0.2'
+ androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
+
+// compile 'com.alibaba:fastjson:1.1.70.android'
+ compile 'com.google.code.gson:gson:2.8.5'
+ compile 'com.nineoldandroids:parent:2.4.0'
+ compile 'com.squareup.okhttp3:okhttp:3.10.0'
+ compile 'net.java.dev.jna:jna:4.5.0@aar'
+ compile 'com.koushikdutta.async:androidasync:2.2.1'
+ compile group: 'com.android.support', name: 'recyclerview-v7', version: '28.0.0'
+ compile 'org.apache.commons:commons-lang3:3.7'
+ compile 'com.android.support:multidex:1.0.3'
+ compile 'org.jetbrains.kotlin:kotlin-reflect:1.3.41'
+ compile 'org.springframework.android:spring-android-core:1.0.1.RELEASE'
+ compile 'org.apache.httpcomponents:httpcore:4.4.10'
+ compile("com.beust:klaxon:0.30") {
+ exclude group: 'org.jetbrains'
+ }
+ compile files('libs/zxinglibsl.jar')
+}
diff --git a/app/libs/zxinglibsl.jar b/app/libs/zxinglibsl.jar
new file mode 100644
index 0000000..c645c93
--- /dev/null
+++ b/app/libs/zxinglibsl.jar
Binary files differ
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
new file mode 100644
index 0000000..f1b4245
--- /dev/null
+++ b/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/app/src/androidTest/java/com/supwisdom/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/supwisdom/ExampleInstrumentedTest.kt
new file mode 100644
index 0000000..2aff141
--- /dev/null
+++ b/app/src/androidTest/java/com/supwisdom/ExampleInstrumentedTest.kt
@@ -0,0 +1,24 @@
+package com.supwisdom
+
+import android.support.test.InstrumentationRegistry
+import android.support.test.runner.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppContext() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getTargetContext()
+ assertEquals("com.supwisdom", appContext.packageName)
+ }
+}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..ed48cb0
--- /dev/null
+++ b/app/src/main/AndroidManifest.xml
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:serviceandroid="http://schemas.android.com/tools"
+ package="com.supwisdom"
+ android:sharedUserId="android.uid.system">
+
+ <uses-permission android:name="android.permission.VIBRATE"/>
+ <uses-permission
+ android:name="android.permission.WRITE_SETTINGS"
+ serviceandroid:ignore="ProtectedPermissions"/>
+ <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
+ <uses-permission
+ android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
+ serviceandroid:ignore="ProtectedPermissions"/>
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
+ <uses-permission android:name="android.permission.INTERNET"/>
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+ <uses-permission android:name="android.permission.CAMERA"/>
+ <uses-permission android:name="android.permission.NFC"/>
+ <uses-permission android:name="android.permission.READ_PROFILE"/>
+ <uses-permission android:name="android.permission.RECEIVE_USER_PRESENT"/>
+ <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
+ <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
+ <uses-permission android:name="android.permission.RECORD_AUDIO"/>
+ <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
+ <uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT"/>
+ <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>
+ <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/>
+ <uses-permission android:name="android.permission.USE_CREDENTIALS"/>
+ <uses-permission android:name="android.permission.FLASHLIGHT"/>
+ <uses-permission android:name="android.permission.WEITE_EXTERNAL_STORAGE"/>
+ <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
+ <uses-permission android:name="android.permission.WAKE_LOCK"/>
+
+ <!--写时钟权限-->
+ <uses-permission
+ android:name="android.permission.WRITE_SETTINGS"
+ serviceandroid:ignore="ProtectedPermissions"/>
+ <uses-permission
+ android:name="android.permission.WRITE_SECURE_SETTINGS"
+ serviceandroid:ignore="ProtectedPermissions"/>
+
+ <uses-feature android:name="android.hardware.camera"/>
+ <uses-feature android:name="android.hardware.camera.autofocus"/>
+
+ <uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>
+ <uses-permission
+ android:name="android.permission.READ_LOGS"
+ serviceandroid:ignore="ProtectedPermissions"/>
+
+ <application
+ android:name=".activities.SPApplication"
+ android:allowBackup="true"
+ android:icon="@drawable/app_logo"
+ android:label="@string/app_name"
+ android:persistent="false"
+ android:supportsRtl="true"
+ android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
+ <activity
+ android:name=".activities.splash.SplashActivity"
+ android:launchMode="singleTask"
+ android:screenOrientation="portrait">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+
+ <!--<category android:name="android.intent.category.HOME" />-->
+ <category android:name="android.intent.category.DEFAULT"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED"/>
+ </intent-filter>
+ </activity>
+
+ <service android:name=".activities.ServiceDemo">
+ <intent-filter>
+ <category android:name="android.intent.category.default"/>
+ </intent-filter>
+ </service>
+
+ <activity
+ android:name=".activities.consume.ConsumeActivity"
+ android:label="@string/title_activity_consume"
+ android:launchMode="singleInstance"/>
+ <activity
+ android:name=".activities.init.InitActivity"
+ android:label="@string/title_activity_consume"
+ android:windowSoftInputMode="stateHidden"
+ android:launchMode="singleTask"/>
+ <activity
+ android:name=".activities.cardlib.CardlibActivity"
+ android:label="@string/title_activity_consume"
+ android:launchMode="singleTask"/>
+ <activity
+ android:name=".activities.load.LoadActivity"
+ android:label="@string/title_activity_consume"
+ android:launchMode="singleTask"/>
+ <activity
+ android:name=".activities.unregister.UnregisterActivity"
+ android:label="@string/title_activity_consume"
+ android:launchMode="singleTask"/>
+ <activity
+ android:name=".activities.upgrade.UpgradeActivity"
+ android:label="@string/title_activity_consume"
+ android:launchMode="singleTask"/>
+ <activity
+ android:name=".activities.control.ControlActivity"
+ android:label="@string/title_activity_consume"
+ android:launchMode="singleTask"/>
+ <activity
+ android:name=".activities.manage.ManageActivity"
+ android:label="@string/title_activity_consume"
+ android:launchMode="singleTask"/>
+ <activity
+ android:name=".activities.menu.MenuActivity"
+ android:label="@string/title_activity_consume"
+ android:launchMode="singleTask"/>
+ <activity
+ android:name=".activities.transdtl.TransdtlActivity"
+ android:label="@string/title_activity_consume"
+ android:launchMode="singleTask"/>
+ <activity
+ android:name=".activities.communicate.CommunicateActivity"
+ android:label="@string/title_activity_consume"
+ android:launchMode="singleTask"/>
+ <activity
+ android:name=".activities.checkShoppwd.CheckShoppwdActivity"
+ android:label="@string/title_activity_consume"
+ android:launchMode="singleTask"/>
+ <activity
+ android:name=".activities.checkMngpwd.CheckMngpwdActivity"
+ android:label="@string/title_activity_consume"
+ android:launchMode="singleTask"/>
+ <activity
+ android:name=".activities.consumeMode.ConsumeModeActivity"
+ android:label="@string/title_activity_consume"
+ android:launchMode="singleTask"/>
+ <activity
+ android:name=".activities.passwd.PasswdActivity"
+ android:label="@string/title_activity_consume"
+ android:launchMode="singleTask"/>
+ <activity
+ android:name=".activities.revenue.RevenueActivity"
+ android:label="@string/title_activity_consume"
+ android:launchMode="singleTask"/>
+ <activity
+ android:name=".activities.syspara.SysparaActivity"
+ android:label="@string/title_activity_consume"
+ android:launchMode="singleTask"/>
+ </application>
+
+</manifest>
\ No newline at end of file
diff --git a/app/src/main/java/com/newcapec/jni/ApduResp.java b/app/src/main/java/com/newcapec/jni/ApduResp.java
new file mode 100644
index 0000000..940be4b
--- /dev/null
+++ b/app/src/main/java/com/newcapec/jni/ApduResp.java
@@ -0,0 +1,9 @@
+package com.newcapec.jni;
+
+public class ApduResp {
+
+ public short LenOut; //????IC??????????????
+ public byte[] DataOut = new byte[512]; //??IC??????????????
+ public byte SWA; //IC??????1
+ public byte SWB; //IC??????2
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/newcapec/jni/ApduSend.java b/app/src/main/java/com/newcapec/jni/ApduSend.java
new file mode 100644
index 0000000..d5dbe30
--- /dev/null
+++ b/app/src/main/java/com/newcapec/jni/ApduSend.java
@@ -0,0 +1,9 @@
+package com.newcapec.jni;
+
+
+public class ApduSend {
+ public byte[] Command = new byte[4]; //CLA, INS, P1, P2
+ public short Lc; //?????IC???????????
+ public byte[] DataIn = new byte[512]; //?????IC????????
+ public short Le; //????????????????
+}
diff --git a/app/src/main/java/com/newcapec/jni/AuxScreen.java b/app/src/main/java/com/newcapec/jni/AuxScreen.java
new file mode 100644
index 0000000..6e7a1cb
--- /dev/null
+++ b/app/src/main/java/com/newcapec/jni/AuxScreen.java
@@ -0,0 +1,197 @@
+package com.newcapec.jni;
+
+public class AuxScreen {
+
+ /**
+ * font code type
+ */
+ public static final int FONT_CODE_UCS2 = 0;
+ public static final int FONT_CODE_GB2312 = 1;
+ public static final int FONT_CODE_UTF8 = 2;
+
+
+ static {
+ try {
+ System.loadLibrary("auxScreen");
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * @return
+ */
+ public int open() {
+ return Native_ScrOpen();
+ }
+
+ /**
+ *
+ */
+ public void close() {
+ Native_ScrClose();
+ }
+
+ /**
+ * 清全屏
+ *
+ * @return
+ */
+ public int cls() {
+ return Native_ScrCls();
+ }
+
+ /**
+ * 清屏
+ *
+ * @param startline 起始行
+ * @param endline 结束行
+ * @return
+ */
+ public int clrLine(int startline, int endline) {
+ return Native_ScrClrLine(startline, endline);
+ }
+
+ /**
+ * 设置前景颜色
+ *
+ * @param fgcolor
+ * @return
+ */
+ public int setFgcolor(int fgcolor) {
+ return Native_ScrSetFgcolor(fgcolor);
+ }
+
+ /**
+ * 设置背景颜色
+ *
+ * @param bgcolor
+ * @return
+ */
+ public int setBgcolor(int bgcolor) {
+ return Native_ScrSetBgcolor(bgcolor);
+ }
+
+ /**
+ * 选择字体
+ *
+ * @param fonttype
+ * @return
+ */
+ public int selectFont(int fonttype) {
+ return Native_ScrSelectFont(fonttype);
+ }
+
+ /**
+ * 设置字体大小
+ *
+ * @param fontsize
+ * @return
+ */
+ public int setFontSize(int fontsize) {
+ return Native_ScrSetFontSize(fontsize);
+ }
+
+ /**
+ * 设置字、行间距
+ *
+ * @param CharSpace
+ * @param LineSpace
+ */
+ public void setSpace(int CharSpace, int LineSpace) {
+ Native_ScrSpaceSet(CharSpace, LineSpace);
+ }
+
+ /**
+ * 设置像素点颜色
+ *
+ * @param x
+ * @param y
+ * @param color
+ */
+ public void drawDot(int x, int y, int color) {
+ Native_ScrDrawDot(x, y, color);
+ }
+
+ /**
+ * 矩形框
+ *
+ * @param left
+ * @param top
+ * @param right
+ * @param bottom
+ * @param color
+ */
+ public void drawRect(int left, int top, int right, int bottom, int color) {
+ Native_ScrDrawRect(left, top, right, bottom, color);
+ }
+
+ /**
+ * 从某个点画字
+ *
+ * @param x
+ * @param y
+ * @param txt
+ * @return
+ */
+ public int textOut(int x, int y, String txt) {
+ return Native_ScrTextOut(x, y, txt);
+ }
+
+ /**
+ * 获取屏幕的宽高
+ *
+ * @param width
+ * @param height
+ * @return
+ */
+ public int getSize(int width[], int height[]) {
+ return Native_ScrGetSize(width, height);
+ }
+
+ public int drawBmp(int width, int height, byte bmp[]) {
+ return Native_ScrDrawBmp(width, height, bmp);
+ }
+
+ public void ScrDrawLogo() {
+ Native_ScrDrawLogo();
+ }
+
+ public void ScrClrRect(int left, int top, int width, int height) {
+ Native_ScrClrRect(left, top, width, height);
+ }
+
+
+ private native final int Native_ScrOpen();
+
+ private native final void Native_ScrClose();
+
+ private native final int Native_ScrCls();
+
+ private native final int Native_ScrClrLine(int startline, int endline);
+
+ private native final int Native_ScrSetFgcolor(int fgcolor);
+
+ private native final int Native_ScrSetBgcolor(int bgcolor);
+
+ private native final int Native_ScrSelectFont(int fonttype);
+
+ private native final int Native_ScrSetFontSize(int fontsize);
+
+ private native final void Native_ScrSpaceSet(int CharSpace, int LineSpace);
+
+ private native final void Native_ScrDrawDot(int x, int y, int color);
+
+ private native final void Native_ScrDrawRect(int left, int top, int right, int bottom, int color);
+
+ private native final int Native_ScrTextOut(int x, int y, String txt);
+
+ private native final int Native_ScrGetSize(int width[], int height[]);
+
+ private native final int Native_ScrDrawBmp(int width, int height, byte bmp[]);
+
+ private native final void Native_ScrDrawLogo();
+
+ private native final void Native_ScrClrRect(int left, int top, int width, int height);
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/newcapec/jni/Icc.java b/app/src/main/java/com/newcapec/jni/Icc.java
new file mode 100644
index 0000000..3a4f197
--- /dev/null
+++ b/app/src/main/java/com/newcapec/jni/Icc.java
@@ -0,0 +1,57 @@
+package com.newcapec.jni;
+
+/**
+ * 接触卡
+ *
+ * @author mayixi
+ */
+public class Icc {
+ static {
+
+ }
+
+ /**
+ * @param version
+ */
+ public Icc(int version) {
+ if (version < 110) {
+ System.loadLibrary("iccV108");
+ } else if (version < 115) {
+ System.loadLibrary("iccV110");
+ } else if (version < 116) {
+ System.loadLibrary("iccV115");
+ } else {
+ System.loadLibrary("iccV116");
+ }
+ }
+
+ public int init(byte slot, byte attr[]) {
+ return Native_Icc_Init(slot, attr);
+ }
+
+ public int close(byte slot) {
+ return Native_Icc_Close(slot);
+ }
+
+ public int autoResp(byte slot, byte autoresp) {
+ return Native_Icc_AutoResp(slot, autoresp);
+ }
+
+ public int sendIsoCommand(byte slot, ApduSend send, ApduResp recv) {
+ return Native_Icc_IsoCommand(slot, send, recv);
+ }
+
+ public int detect(byte slot) {
+ return Native_Icc_Detect(slot);
+ }
+
+ private native final int Native_Icc_Init(byte slot, byte atr[]);
+
+ private native final int Native_Icc_Close(byte slot);
+
+ private native final int Native_Icc_AutoResp(byte slot, byte autoresp);
+
+ private native final int Native_Icc_IsoCommand(byte slot, ApduSend send, ApduResp recv);
+
+ private native final int Native_Icc_Detect(byte slot);
+};
diff --git a/app/src/main/java/com/newcapec/jni/Picc.java b/app/src/main/java/com/newcapec/jni/Picc.java
new file mode 100644
index 0000000..fadb179
--- /dev/null
+++ b/app/src/main/java/com/newcapec/jni/Picc.java
@@ -0,0 +1,195 @@
+/*******************************************************************
+ * PiccInterface.java
+ * PiccInterface 、PICC_PARA、DetectInfo、ErrocCode
+ * A302 射频卡操作接口类
+ * 2014-11-05
+ * v0.1
+ *******************************************************************/
+package com.newcapec.jni;
+
+public class Picc {
+ static {
+
+ }
+
+ public static class PICC_PARA {
+
+ public byte drv_ver[]; // 驱动程序的版本信息,如:”1.01A”;只能读取,写入无效
+ public byte drv_date[]; // 驱动程序的日期信息,如:”2006.08.25”; 只能读取
+ public byte a_conduct_w; // A卡输出电导写入允许:1--允许,其它—不允许
+ public byte a_conduct_val; // A卡输出电导控制变量,有效范围0~63,超出时视为63
+ public byte m_conduct_w; // M1卡输出电导写入允许
+ public byte m_conduct_val; // M1卡输出电导控制变量,有效范围0~63,超出时视为63
+ public byte b_modulate_w; //B卡调制指数写入允许:
+ public byte b_modulate_val; // B卡调制指数控制变量,有效范围0~63,超出时视为63
+ public byte card_buffer_w; //卡片接收缓冲区大小写入允许:
+
+ public short card_buffer_val; //卡片接收缓冲区大小参数(单位:字节),有效值1~256.大于256时,将以256写入;设为0时,将不会写入
+ public byte wait_retry_limit_w; // S(WTX)响应发送次数写入允许(暂不适用)
+ public short wait_retry_limit_val; //S(WTX)响应最大重试次数(暂不适用)
+ public byte card_type_check_w; //卡片类型检查写入允许 */
+ public byte card_type_check_val; // 0-检查卡片类型,其他-不检查卡片类型(默认为检查卡片类型)
+ public byte card_RxThreshold_w; //B卡片接收灵敏度写入允许:1--允许,其它值--不允许。该值不可读
+ public byte card_RxThreshold_val; //B卡片接收灵敏度
+
+ public byte f_modulate_w; //felica调制指数写入允许
+ public byte f_modulate_val;
+ public byte a_modulate_w;
+ public byte a_modulate_val;
+ public byte a_card_RxThreshold_w;
+ public byte a_card_RxThreshold_val; //felica调制指数
+
+ /*A卡调制指数控制变量,有效范围0~63,超出时视为63*/
+ /*A卡接收灵敏度检查写入允许:1--允许,其它值--不允许*/
+ /*A卡接收灵敏度*/
+ public byte a_card_antenna_gain_w;
+ public byte a_card_antenna_gain_val; //A卡的天线增益
+ public byte b_card_antenna_gain_w;
+ public byte b_card_antenna_gain_val; //B卡的天线增益
+ public byte f_card_antenna_gain_w;
+ public byte f_card_antenna_gain_val; //Felica的天线增益
+ public byte f_card_RxThreshold_w;
+ public byte f_card_RxThreshold_val; //Felica的接收灵敏度
+ public byte f_conduct_w;
+ public byte f_conduct_val;
+ public byte user_control_w;
+ public byte user_control_val; //paypass认证需求,指定按键值,按下时强制退出交易*/ /*Felica的电导率*/
+ public byte reserved[]; //保留字节,用于将来扩展;写入时应全清零
+
+ public PICC_PARA() {
+ drv_ver = new byte[5];
+ drv_date = new byte[12];
+ reserved = new byte[72];
+ }
+ }
+
+ public static class DetectInfo {
+ public String CardType;
+ public String SerialInfo;
+ public String Cid;
+ public String Other;
+ public byte Cid_Array[];
+ public byte SerialInfo_Array[];
+
+ public DetectInfo() {
+ CardType = new String();
+ SerialInfo = new String();
+ Other = new String();
+ Cid = new String();
+
+ Cid_Array = new byte[10];
+ SerialInfo_Array = new byte[20];
+ }
+ }
+
+// public class ErrocCode {
+// public final static int PICC_STATUS_SUCCESS = 0x00; //成功
+// public final static int PICC_STATUS_ARGUMENTS_ERROR = 0x01; //参数错误
+// public final static int PICC_STATUS_NOT_OPEN = 0x02; //射频模块未开启
+// public final static int PICC_STATUS_NO_CARD = 0x03; //未搜寻到卡片(感应区内无指定类型的卡片)
+// public final static int PICC_STATUS_MANY_CARD = 0x04; //感应区内卡片过多(出现通讯冲突)
+// public final static int PICC_STATUS_ERROR_PROTOCOL = 0x06; //协议错误(卡片应答中出现违反协议规定的数据)
+// public final static int PICC_STATUS_CARD_NO_ACTIVE = 0x13; //卡片未激活
+// public final static int PICC_STATUS_CARDS_CONFLICT = 0x14; //多卡冲突?
+// public final static int PICC_STATUS_TIMEOUT = 0x15; //超时无响应
+// //public final static int PICC_STATUS_DATA_LONG = 0x16 ; //协议错误
+// public final static int PICC_STATUS_COMMUNICAT_ERROR = 0x17; //通信传输错误
+// public final static int PICC_STATUS_M1_CARD_Authentication_ERROR = 0x18; //M1卡认证失败
+// public final static int PICC_STATUS_SECTION_NO_Authentication = 0x19; //扇区未认证
+// public final static int PICC_STATUS_DATA_FORMAT_ERROR = 0x1A; //数值块数据格式有误
+// public final static int PICC_STATUS_CARD_IN_INDUCTION_ZONE = 0x1B; //卡片仍在感应区内
+// public final static int PICC_STATUS_CARD_STATE_ERROR = 0x1C; //卡片状态错误(如A/B卡调用M1卡接口, 或M1卡调用PiccIsoCommand接口)
+// public final static int PICC_STATUS_CARD_ABORT = 0xFF; //接口芯片不存在或异常
+// }
+
+ /**
+ * @param version
+ */
+ public Picc(int version) {
+ if (version < 110) {
+ System.loadLibrary("piccV108");
+ } else if (version < 116) {
+ System.loadLibrary("piccV115");
+ } else {
+ System.loadLibrary("piccV116");
+ }
+ }
+
+ public int open() {
+ return Native_Picc_Open();
+ }
+
+ public int setup(byte mode, PICC_PARA para) {
+ return Native_Picc_Setup(mode, para);
+ }
+
+ public int sendIsoCommand(byte cid, ApduSend Send, ApduResp Resp) {
+ return Native_Picc_IsoCommand(cid, Send, Resp);
+ }
+
+ public int remove(byte mode, byte cid) {
+ return Native_Picc_Remove(mode, cid);
+ }
+
+ public int close() {
+ return Native_Picc_Close();
+ }
+
+ public int m1Authority(byte Type, byte BlkNo, byte Pwd[], byte SerialNo[]) {
+ return Native_Picc_M1Authority(Type, BlkNo, Pwd, SerialNo);
+ }
+
+ public int readM1Block(byte BlkNo, byte BlkValue[], int BlkLen) {
+ return Native_Picc_M1ReadBlock(BlkNo, BlkValue, BlkLen);
+ }
+
+ public int writeM1Block(byte BlkNo, byte BlkValue[], int BlkLen) {
+ return Native_Picc_M1WriteBlock(BlkNo, BlkValue, BlkLen);
+ }
+
+ public int operateM1(byte Type, byte BlkNo, byte Value[], byte UpdateBlkNo) {
+ return Native_Picc_M1Operate(Type, BlkNo, Value, UpdateBlkNo);
+ }
+
+ public int light(byte ucLedIndex, byte ucOnOff) {
+ return Native_Picc_Light(ucLedIndex, ucOnOff);
+ }
+
+ public int initFelica(byte ucRate, byte ucPol) {
+ return Native_Picc_InitFelica(ucRate, ucPol);
+ }
+
+ public int exchangeCmd(int uiSendLen, String paucInData, int puiRecLen[], String paucOutData) {
+ return Native_Picc_CmdExchange(uiSendLen, paucInData, puiRecLen, paucOutData);
+ }
+
+ public int detect(byte Mode, DetectInfo info) {
+ return Native_Picc_Detect(Mode, info);
+ }
+
+ private native final int Native_Picc_Open();
+
+ private native final int Native_Picc_Setup(byte mode, PICC_PARA para);
+
+ private native final int Native_Picc_IsoCommand(byte cid, ApduSend ApduSend, ApduResp ApduRecv);
+
+ private native final int Native_Picc_Remove(byte mode, byte cid);
+
+ private native final int Native_Picc_Close();
+
+ private native final int Native_Picc_M1Authority(byte Type, byte BlkNo, byte Pwd[], byte SerialNo[]);
+
+ private native final int Native_Picc_M1ReadBlock(byte BlkNo, byte BlkValue[], int BlkLen);
+
+ private native final int Native_Picc_M1WriteBlock(byte BlkNo, byte BlkValue[], int BlkLen);
+
+ private native final int Native_Picc_M1Operate(byte Type, byte BlkNo, byte Value[], byte UpdateBlkNo);
+
+ private native final int Native_Picc_Light(byte ucLedIndex, byte ucOnOff);
+
+ private native final int Native_Picc_InitFelica(byte ucRate, byte ucPol);
+
+ private native final int Native_Picc_CmdExchange(int uiSendLen, String paucInData, int puiRecLen[], String paucOutData);
+
+ private native final int Native_Picc_Detect(byte Mode, DetectInfo info);
+};
diff --git a/app/src/main/java/com/newcapec/serial/SerialPort.java b/app/src/main/java/com/newcapec/serial/SerialPort.java
new file mode 100644
index 0000000..f8099fb
--- /dev/null
+++ b/app/src/main/java/com/newcapec/serial/SerialPort.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2009 Cedric Priscal
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.newcapec.serial;
+
+import java.io.IOException;
+
+public class SerialPort {
+
+ private static final String TAG = "SerialPort";
+ static {
+ System.loadLibrary("serial_port");
+ }
+
+ /**
+ * @name open
+ * @desc ??????1
+ * @param : ??
+ * @return 0-???, ????-???
+ * @throws IOException ??
+ */
+ public int open(int port, int baudrate, int flags)
+ {
+ return Native_Serial_Open(port, baudrate, flags);
+ }
+
+ /**
+ * @name sendMsg
+ * @desc ????????
+ * @param : ??
+ * @return 0-???, ????-???
+ * @throws IOException ??
+ */
+ public int sendMsg(byte[] msg)
+ {
+ return Native_Serial_SendMsg(msg);
+ }
+
+ /**
+ * @name recvMsg
+ * @desc ????????
+ * @param : ??
+ * @return 0-???, ????-???
+ * @throws IOException ??
+ */
+ public byte[] recvMsg()
+ {
+ return Native_Serial_RecvMsg();
+ }
+
+ /**
+ * @name close
+ * @desc ??????
+ * @param : ??
+ * @return 0-???, ????-???
+ * @throws IOException ??
+ */
+ public int close()
+ {
+ return Native_Serial_Close();
+ }
+
+
+ private native final int Native_Serial_Open(int port, int baudrate, int flags);
+ private native final int Native_Serial_SendMsg(byte[] msg);
+ private native final byte[] Native_Serial_RecvMsg();
+ private native final int Native_Serial_Close();
+
+}
diff --git a/app/src/main/java/com/supwisdom/activities/BaseActivity.kt b/app/src/main/java/com/supwisdom/activities/BaseActivity.kt
new file mode 100644
index 0000000..6183f9a
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/BaseActivity.kt
@@ -0,0 +1,31 @@
+package com.supwisdom.activities
+
+import android.app.Activity
+import android.content.Intent
+import android.os.Bundle
+import com.supwisdom.utils.AppExitUtil
+
+/**
+ ** create by zzq on 2019/7/23
+ ** @desc
+ **/
+open class BaseActivity : Activity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ //getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ AppExitUtil.add(this)
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ AppExitUtil.remove(this)
+ }
+
+ override fun onResume() {
+ super.onResume()
+ }
+
+ fun <T> jumpActivity(cls: Class<T>) {
+ startActivity(Intent(applicationContext, cls))
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/CrashHandler.kt b/app/src/main/java/com/supwisdom/activities/CrashHandler.kt
new file mode 100644
index 0000000..48caaf3
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/CrashHandler.kt
@@ -0,0 +1,133 @@
+package com.supwisdom.activities
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.content.pm.PackageManager
+import android.os.Build
+import android.os.Looper
+import com.supwisdom.utils.*
+import com.supwisdom.view.ToastUtil
+import java.io.PrintWriter
+import java.io.StringWriter
+import java.util.*
+
+/**
+ ** create by zzq on 2019/7/23
+ ** @desc
+ **/
+class CrashHandler : Thread.UncaughtExceptionHandler {
+ private var context: Context? = null
+ private var mDefaultHandler: Thread.UncaughtExceptionHandler? = null
+ private val info = HashMap<String, String>()
+
+ companion object {
+ @SuppressLint("StaticFieldLeak")
+ private var INSTANCE: CrashHandler? = null
+
+ fun getInstance(): CrashHandler {
+ if (INSTANCE == null) {
+ synchronized(CrashHandler::class) {
+ if (INSTANCE == null) {
+ INSTANCE = CrashHandler()
+ }
+ }
+ }
+ return INSTANCE!!
+ }
+ }
+
+ fun init(context: Context) {
+ this.context = context
+ // 获取系统默认的 UncaughtException 处理器
+ mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler()
+ // 设置该 CrashHandler 为程序的默认处理器
+ Thread.setDefaultUncaughtExceptionHandler(this)
+ }
+
+ override fun uncaughtException(thread: Thread, ex: Throwable) {
+ if (!handleException(ex) && mDefaultHandler != null) {
+ // 如果自定义的没有处理则让系统默认的异常处理器来处理
+ mDefaultHandler!!.uncaughtException(thread, ex)
+ } else {
+ AppExitUtil.exit()
+ }
+ }
+
+ /**
+ * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
+ *
+ * @param ex 异常信息
+ * @return true 如果处理了该异常信息;否则返回false.
+ */
+ private fun handleException(ex: Throwable?): Boolean {
+ ThreadPool.getShortPool().execute(Runnable {
+ CommonUtil.doSleep(500)
+ Looper.prepare()
+ ToastUtil.show(context!!, "很抱歉,程序运行异常")
+ Looper.loop()
+ })
+ if (ex == null) {
+ return false
+ }
+ // 收集设备参数信息
+ collectDeviceInfo()
+ // 保存日志文件
+ saveCrashInfo2File(ex)
+ return true
+ }
+
+ /**
+ * 收集设备参数信息
+ */
+
+ private fun collectDeviceInfo() {
+ try {
+ val pm = context!!.packageManager// 获得包管理器
+ val pi = pm.getPackageInfo(
+ context!!.packageName,
+ PackageManager.GET_ACTIVITIES
+ )// 得到该应用的信息,即主Activity
+ if (pi != null) {
+ info["versionName"] = pi.versionName ?: "null"
+ info["versionCode"] = pi.versionCode.toString()
+ }
+ } catch (e: PackageManager.NameNotFoundException) {
+ e.printStackTrace()
+ }
+
+ val fields = Build::class.java.declaredFields// 反射机制
+ for (field in fields) {
+ try {
+ field.isAccessible = true
+ info[field.name] = field.get("").toString()
+ } catch (e: IllegalArgumentException) {
+ e.printStackTrace()
+ } catch (e: IllegalAccessException) {
+ e.printStackTrace()
+ }
+ }
+ }
+
+ private fun saveCrashInfo2File(ex: Throwable): Boolean {
+ val sb = StringBuffer()
+ sb.append("\r\n crash time :").append(DateUtil.getNowTime()).append("\r\n")
+ for ((key, value) in info) {
+ sb.append("$key=$value\r\n")
+ }
+ val writer = StringWriter()
+ val pw = PrintWriter(writer)
+ ex.printStackTrace(pw)
+ var cause: Throwable? = ex.cause
+ // 循环着把所有的异常信息写入writer中
+ while (cause != null) {
+ cause.printStackTrace(pw)
+ cause = cause.cause
+ }
+ pw.close()// 记得关闭
+ val result = writer.toString()
+ sb.append(result)
+ // 保存文件
+ FileUtil.writeCrashFile(sb.toString())
+ return true
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/SPApplication.kt b/app/src/main/java/com/supwisdom/activities/SPApplication.kt
new file mode 100644
index 0000000..61e704d
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/SPApplication.kt
@@ -0,0 +1,70 @@
+package com.supwisdom.activities
+
+import android.content.Context
+import android.content.Intent
+import android.support.multidex.MultiDex
+import android.support.multidex.MultiDexApplication
+import com.supwisdom.db.Pos
+import com.supwisdom.service.BackgroundTaskService
+import com.supwisdom.utils.CommonUtil
+import com.supwisdom.utils.PublicDef
+
+/**
+ ** create by zzq on 2019/7/23
+ ** @desc
+ **/
+class SPApplication : MultiDexApplication() {
+ private var mPos: Pos? = null
+ @Volatile
+ private var epayLinking: Boolean = false //链路状态 true 联机
+
+ companion object {
+ @Volatile
+ private var mInstance: SPApplication? = null
+
+ fun getInstance(): SPApplication {
+ return mInstance!!
+ }
+ }
+
+ fun getPos(): Pos {
+ if (mPos == null) {
+ synchronized(SPApplication::class.java) {
+ if (mPos == null) {
+ mPos = Pos(applicationContext)
+ }
+ }
+ }
+ return mPos!!
+ }
+
+ fun setEpayLinking(isOnline: Boolean) {
+ epayLinking = isOnline
+ }
+
+ fun isOnline(): Boolean {
+ return epayLinking
+ }
+
+ override fun onCreate() {
+ super.onCreate()
+ mInstance = this
+ startService()
+ CrashHandler.getInstance().init(applicationContext)
+ }
+
+ override fun attachBaseContext(base: Context) {
+ super.attachBaseContext(base)
+ MultiDex.install(this)
+ }
+
+ private fun startService() {
+ if (!CommonUtil.isServiceWork(this, PublicDef.BG_SERVICE_NAME)) {
+ startService(Intent(this, BackgroundTaskService::class.java))
+ }
+ }
+
+ fun stopService() {
+ stopService(Intent(this, BackgroundTaskService::class.java))
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/ServiceDemo.kt b/app/src/main/java/com/supwisdom/activities/ServiceDemo.kt
new file mode 100644
index 0000000..c0bc6b1
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/ServiceDemo.kt
@@ -0,0 +1,15 @@
+package com.supwisdom.activities
+
+import android.app.Service
+import android.content.Intent
+import android.os.IBinder
+
+/**
+ ** create by zzq on 2019/7/23
+ ** @desc
+ **/
+class ServiceDemo : Service() {
+ override fun onBind(intent: Intent): IBinder? {
+ return null
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/YktSession.kt b/app/src/main/java/com/supwisdom/activities/YktSession.kt
new file mode 100644
index 0000000..0d01687
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/YktSession.kt
@@ -0,0 +1,81 @@
+package com.supwisdom.activities
+
+import com.supwisdom.okhttp.NetworkHandler
+import com.supwisdom.okhttp.TransResp
+import com.supwisdom.okhttp.WebAPISession
+import com.supwisdom.okhttp.WebParams
+import com.supwisdom.utils.DateUtil
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+class YktSession private constructor() {
+ companion object {
+ private var yktSession: YktSession? = null
+ private var mSession: WebAPISession? = null
+ /**
+ * Create YktSession instance
+ *
+ * @return YktSession object
+ */
+ @Synchronized
+ fun getInstance(): YktSession {
+ if (null == yktSession) {
+ synchronized(YktSession::class.java) {
+ if (null == yktSession) {
+ yktSession = YktSession()
+ mSession = WebAPISession()
+ }
+ }
+ }
+ return yktSession!!
+ }
+ }
+
+ fun setSessionKey(sessionKey: String) {
+ mSession!!.setSessionKey(sessionKey)
+ }
+
+
+ // 设置通信参数
+ fun setWebAPISession(epayIP: String, epayPort: Int, uri: String, termid: String, commTime: Int) {
+ val sb = StringBuilder()
+ if (epayIP.startsWith("http")) {
+ sb.append(epayIP)
+ } else {
+ sb.append("http://").append(epayIP)
+ }
+ sb.append(":").append(epayPort).append("/").append(uri)
+
+ mSession!!.setEpayurl(sb.toString())
+ NetworkHandler.getInstance().setCommTime(commTime)
+ }
+
+ // post
+ fun sendYktRequestPost(uri: String, signdata: String, params: WebParams): TransResp? {
+ val timestamp = DateUtil.getNowDateTimeNoFormat()
+ val temp = signdata.replace("null".toRegex(), "")
+ val mysign = calcSignForCardPay(temp, timestamp)
+ params.setParameter("sign", mysign)
+ .setParameter("timestamp", timestamp)
+ val url = mSession!!.getEpayurl() + uri
+ return NetworkHandler.getInstance().post(url, params)
+ }
+
+ fun sendYktRequestLongPost(uri: String, signdata: String, params: WebParams): TransResp? {
+ val timestamp = DateUtil.getNowDateTimeNoFormat()
+ val temp = signdata.replace("null".toRegex(), "")
+ val mysign = calcSignForCardPay(temp, timestamp)
+ params.setParameter("sign", mysign)
+ .setParameter("timestamp", timestamp)
+ val url = mSession!!.getEpayurl() + uri
+ return NetworkHandler.getInstance().longPost(url, params)
+ }
+
+ private fun calcSignForCardPay(extdata: String, nTimestamp: String): String {
+ val signData = extdata + nTimestamp + mSession!!.getSessionKey()
+// val mySign = Encrypt.HMACSHA1(signData, mSession.getAppSecret())
+ return ""//mySign.toLowerCase()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/auxscreen/AuxScreenController.kt b/app/src/main/java/com/supwisdom/activities/auxscreen/AuxScreenController.kt
new file mode 100644
index 0000000..2e81b1c
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/auxscreen/AuxScreenController.kt
@@ -0,0 +1,263 @@
+package com.supwisdom.auxscreen
+
+import android.graphics.Color
+import com.newcapec.jni.AuxScreen
+import com.supwisdom.utils.CommonUtil
+import java.util.concurrent.locks.ReentrantLock
+
+/**
+ * @author gqy
+ * @version 1.0.1
+ * @date 2018/7/11
+ * @desc 小屏控制器
+ */
+class AuxScreenController private constructor() {
+ private var auxScreen = AuxScreen()
+ private val xStart = 15
+ private val xSecStart = 240
+ private val sTitle = "refreshTitle"
+ private val sContent = "refreshContent"
+ private val sBottom = "refreshBottom"
+ private val lock = ReentrantLock()
+ private val refreshMap = hashMapOf<String, Any>()
+ private val auxRunnable = AuxRunnable()
+ private var isExit = false
+ private var taskThread: Thread? = null
+
+ companion object {
+ @Volatile
+ private var auxController: AuxScreenController? = null
+
+ fun getInstance(): AuxScreenController {
+ if (null == auxController) {
+ synchronized(AuxScreenController::class.java) {
+ if (null == auxController) {
+ auxController = AuxScreenController()
+ }
+ }
+ }
+ return auxController!!
+ }
+ }
+
+ /**
+ * 刷新标题栏
+ * @param title 标题
+ */
+ fun refreshTitle(title: String) {
+ lock.lock()
+ refreshMap[sTitle] = title
+ lock.unlock()
+ }
+
+ private fun localRefreshTitle(title: String) {
+ auxScreen.setBgcolor(Color.parseColor("#FFFFFF"))
+ auxScreen.clrLine(0, 50)
+ auxScreen.setBgcolor(Color.parseColor("#FFFFFF"))
+ auxScreen.setFontSize(20)
+ auxScreen.setFgcolor(Color.parseColor("#000000"))
+ auxScreen.textOut(xStart, 15, title)
+ }
+
+ /**
+ * 内容显示
+ * @param list 显示内容 size<=5
+ */
+ fun refreshContent(list: List<String>) {
+ lock.lock()
+ refreshMap[sContent] = list
+ lock.unlock()
+ }
+
+ private fun localRefreshContent(list: List<String>) {
+ auxScreen.setBgcolor(Color.parseColor("#F2F2F2"))
+ clearCenterContent()
+
+ val size = list.size
+ auxScreen.setFgcolor(Color.parseColor("#000000"))
+ when (size) {
+ 0 -> {
+
+ }
+ 1 -> {
+ auxScreen.setFontSize(40)
+ auxScreen.textOut(xStart, 140, getNotEmptyString(list[0]))
+ }
+ 2 -> {
+ auxScreen.setFontSize(35)
+ for (index in 0 until size) {
+ auxScreen.textOut(xStart, 120 + 60 * index, getNotEmptyString(list[index]))
+ }
+ }
+ 3 -> {
+ auxScreen.setFontSize(30)
+ for (index in 0 until size) {
+ auxScreen.textOut(xStart, 100 + 50 * index, getNotEmptyString(list[index]))
+ }
+ }
+ 4 -> {
+ auxScreen.setFontSize(25)
+ for (index in 0 until size) {
+ auxScreen.textOut(xStart, 80 + 45 * index, getNotEmptyString(list[index]))
+ }
+ }
+ 5 -> {
+ auxScreen.setFontSize(20)
+ for (index in 0 until size) {
+ auxScreen.textOut(xStart, 70 + 40 * index, getNotEmptyString(list[index]))
+ }
+ }
+ 6 -> {
+ auxScreen.setFontSize(15)
+ for (index in 0 until size) {
+ auxScreen.textOut(xStart, 60 + 35 * index, getNotEmptyString(list[index]))
+ }
+ }
+ 7, 8 -> {
+ auxScreen.setFontSize(25)
+ for (index in 0 until (size + 1) / 2) {
+ auxScreen.textOut(xStart, 80 + 45 * index, getNotEmptyString(list[2 * index]))
+ if (2 * index + 1 < size) {
+ auxScreen.textOut(xSecStart, 80 + 45 * index, getNotEmptyString(list[2 * index + 1]))
+ }
+ }
+ }
+ 9, 10 -> {
+ auxScreen.setFontSize(20)
+ for (index in 0 until (size + 1) / 2) {
+ auxScreen.textOut(xStart, 70 + 40 * index, getNotEmptyString(list[2 * index]))
+ if (2 * index + 1 < size) {
+ auxScreen.textOut(xSecStart, 70 + 40 * index, getNotEmptyString(list[2 * index + 1]))
+ }
+ }
+ }
+ else -> {
+ auxScreen.setFontSize(15)
+ for (index in 0 until (size + 1) / 2) {
+ auxScreen.textOut(xStart, 60 + 35 * index, getNotEmptyString(list[2 * index]))
+ if (2 * index + 1 < size) {
+ auxScreen.textOut(xSecStart, 60 + 35 * index, getNotEmptyString(list[2 * index + 1]))
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * 处理输入的空字符串
+ */
+ private fun getNotEmptyString(input: String?): String {
+ if (input == null || input.isEmpty()) {
+ return " "
+ }
+ return input
+ }
+
+ /**
+ * 刷新底部状态
+ * @param bottom 提示
+ */
+ fun refreshBottom(bottom: String) {
+ lock.lock()
+ refreshMap[sBottom] = bottom
+ lock.unlock()
+ }
+
+ private fun localRefreshBootom(bottom: String) {
+ auxScreen.setBgcolor(Color.parseColor("#FFFFFF"))
+ auxScreen.clrLine(269, 319)
+
+ auxScreen.setFontSize(20)
+ auxScreen.setFgcolor(Color.parseColor("#000000"))
+ auxScreen.textOut(15, 284, bottom)
+ }
+
+ /**
+ * 清空中间的内容
+ * @注意:此处必须一行一行的清除,底层bug
+ */
+ private fun clearCenterContent() {
+ auxScreen.clrLine(50, 100)
+ auxScreen.clrLine(100, 150)
+ auxScreen.clrLine(150, 200)
+ auxScreen.clrLine(200, 250)
+ auxScreen.clrLine(250, 269)
+ auxScreen.setFontSize(50)
+ }
+
+ /**
+ * 打开小屏
+ */
+ fun open() {
+ auxScreen.open()
+ if (taskThread == null) {
+ isExit = false
+ taskThread = Thread(auxRunnable)
+ taskThread!!.start()
+ }
+ }
+
+ /**
+ * 关闭小屏
+ */
+ fun close() {
+ auxScreen.close()
+ isExit = true
+ taskThread?.interrupt()
+ taskThread = null
+ }
+
+ /**
+ * 初始化小屏
+ */
+ private fun init() {
+ auxScreen.setBgcolor(Color.parseColor("#F2F2F2"))
+ auxScreen.cls()
+ auxScreen.setSpace(5, 5)
+ auxScreen.selectFont(AuxScreen.FONT_CODE_UTF8)
+ }
+
+ inner class AuxRunnable : Runnable {
+ override fun run() {
+ init()
+ while (!isExit) {
+ try {
+ try {
+ lock.lock()
+ val title = refreshMap[sTitle]
+ if (title != null) {
+ localRefreshTitle(title as String)
+ refreshMap.remove(sTitle)
+ }
+ } finally {
+ lock.unlock()
+ }
+ try {
+ lock.lock()
+ val content = refreshMap[sContent]
+ if (content != null) {
+ localRefreshContent(content as List<String>)
+ refreshMap.remove(sContent)
+ }
+ } finally {
+ lock.unlock()
+ }
+ try {
+ lock.lock()
+ val bottom = refreshMap[sBottom]
+ if (bottom != null) {
+ localRefreshBootom(bottom as String)
+ refreshMap.remove(sBottom)
+ }
+ } finally {
+ lock.unlock()
+ }
+ } catch (ex: Exception) {
+ ex.printStackTrace()
+ }
+ CommonUtil.doSleep(25)
+ }
+ }
+ }
+}
+
diff --git a/app/src/main/java/com/supwisdom/activities/auxscreen/AuxScreenViewSchedule.kt b/app/src/main/java/com/supwisdom/activities/auxscreen/AuxScreenViewSchedule.kt
new file mode 100644
index 0000000..896e3a6
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/auxscreen/AuxScreenViewSchedule.kt
@@ -0,0 +1,51 @@
+package com.supwisdom.activities.auxscreen
+
+import android.os.Handler
+import android.os.HandlerThread
+import android.os.Message
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+class AuxScreenViewSchedule private constructor() {
+ private val mExector: Runnable? = null
+ private var mAuxWorkHandler: Handler
+ private var mHandlerThread: HandlerThread
+
+ companion object {
+ private var _instance: AuxScreenViewSchedule? = null
+ fun getInstancs(): AuxScreenViewSchedule {
+ if (_instance == null)
+ _instance =
+ AuxScreenViewSchedule()
+ return _instance!!
+ }
+ }
+
+ init {
+ mHandlerThread = HandlerThread("AuxScreenViewThread")
+
+ mHandlerThread.start()
+
+ mAuxWorkHandler = object : Handler(mHandlerThread.looper) {
+ override// 消息处理的操作
+ fun handleMessage(msg: Message) {
+ super.handleMessage(msg)
+ }
+ }
+ }
+
+ fun Post(r: Runnable, attr: Int) {
+ //定时任务
+ //mAuxWorkHandler.getLooper().getQueue()
+ mAuxWorkHandler.removeCallbacks(r)
+ mAuxWorkHandler.post(r)
+ }
+
+ fun PostDelayed(r: Runnable, millis: Int) {
+ //定时任务
+ //mAuxWorkHandler.getLooper().getQueue()
+ mAuxWorkHandler.postDelayed(r, millis.toLong())
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/cardlib/CardlibActivity.kt b/app/src/main/java/com/supwisdom/activities/cardlib/CardlibActivity.kt
new file mode 100644
index 0000000..f64c8cb
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/cardlib/CardlibActivity.kt
@@ -0,0 +1,121 @@
+package com.supwisdom.activities.cardlib
+
+import android.os.Bundle
+import android.view.KeyEvent
+import android.view.View
+import android.view.Window
+import android.widget.ProgressBar
+import android.widget.TextView
+import com.supwisdom.R
+import com.supwisdom.activities.BaseActivity
+import com.supwisdom.activities.SPApplication
+import com.supwisdom.activities.init.InitActivity
+import com.supwisdom.activities.load.LoadActivity
+import com.supwisdom.auxscreen.AuxScreenController
+import com.supwisdom.utils.AppExitUtil
+import com.supwisdom.utils.DateUtil
+import com.supwisdom.view.BigProgressDialog
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+@Suppress("DEPRECATION")
+class CardlibActivity : BaseActivity(), ICardlibView {
+ private val pos = SPApplication.getInstance().getPos()
+ private var vResult: TextView? = null
+ private var vProgressBar: ProgressBar? = null
+ private var presenter: CardlibPresenter? = null
+ @Volatile
+ private var isLoading = false
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ //在窗口标题上显示带进度的横向进度条
+ requestWindowFeature(Window.FEATURE_PROGRESS)
+ //显示不带进度的进度条
+ requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS)
+
+ setContentView(R.layout.activity_cardlib)
+ initView()
+ initData()
+ }
+
+ private fun initData() {
+ presenter = CardlibPresenter(this)
+ }
+
+ private fun initView() {
+ vProgressBar = this.findViewById(R.id.cardlib_bar) as ProgressBar
+ vResult = this.findViewById(R.id.cardlib_result) as TextView
+ }
+
+ override fun showProgress(progress: Int) {
+ vProgressBar!!.progress = progress
+ }
+
+ override fun onResume() {
+ super.onResume()
+ if (!isLoading) {
+ isLoading = true
+ refresh()
+ presenter!!.initCardlib(this)
+ }
+ }
+
+ override fun dispatchKeyEvent(event: KeyEvent): Boolean {
+ if (event.action == KeyEvent.ACTION_DOWN) {
+ if (isLoading) {
+ return false
+ }
+ when (event.keyCode) {
+ KeyEvent.KEYCODE_DEL -> {
+ AppExitUtil.exit()
+ }
+ }
+ }
+ return super.dispatchKeyEvent(event)
+ }
+
+ private fun refresh() {
+ AuxScreenController.getInstance().refreshTitle("卡库初始化")
+ AuxScreenController.getInstance().refreshBottom(DateUtil.getNowDateTime())
+ AuxScreenController.getInstance().refreshContent(listOf("加载硬件驱动", "请稍等..."))
+ }
+
+ override fun showInitCardlibResult(issuccess: Boolean, msg: String) {
+ if (issuccess) {
+ val record = pos.getConfigPara()
+ if (record != null && record.initOK) {
+ jumpActivity(LoadActivity::class.java)
+ } else {
+ jumpActivity(InitActivity::class.java)
+ }
+ } else {
+ vResult!!.text = msg
+ vResult!!.visibility = View.VISIBLE
+ AuxScreenController.getInstance().refreshTitle("卡库初始化")
+ AuxScreenController.getInstance().refreshBottom(DateUtil.getNowDateTime())
+ AuxScreenController.getInstance().refreshContent(listOf("请联系管理员", "加载驱动失败", "原因:", msg))
+ }
+ isLoading = false
+ }
+
+ private var dialogProgress: BigProgressDialog? = null
+
+ override fun showProgressDialog(msg: String) {
+ if (dialogProgress == null) {
+ dialogProgress = BigProgressDialog(this, msg, false)
+ }
+ dialogProgress!!.setMsg(msg)
+ dialogProgress!!.show()
+ }
+
+ override fun closeProgressDialog() {
+ dialogProgress?.dismiss()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/cardlib/CardlibPresenter.kt b/app/src/main/java/com/supwisdom/activities/cardlib/CardlibPresenter.kt
new file mode 100644
index 0000000..d843183
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/cardlib/CardlibPresenter.kt
@@ -0,0 +1,98 @@
+package com.supwisdom.activities.cardlib
+
+import android.app.Activity
+import android.os.AsyncTask
+import android.os.Handler
+import android.os.Looper
+import android.os.Message
+import com.supwisdom.epaycard.Cardlib
+import com.supwisdom.exception.CardlibInitError
+import com.supwisdom.utils.CommonUtil
+import com.supwisdom.utils.ThreadPool
+
+/**
+ * Created by zzq on 2017/11/7.
+ */
+class CardlibPresenter constructor(iCardlibView: ICardlibView) {
+ private val iCardlibView = iCardlibView
+ private val handler: Handler
+ @Volatile
+ private var cardlibStat = CardLibStatus.INIT
+ private var cardlibResult: String? = null
+
+ init {
+ handler = object : Handler(Looper.getMainLooper()) {
+ override fun handleMessage(msg: Message?) {
+ when (msg!!.what) {
+ 1 ->
+ iCardlibView.showProgress(msg.obj as Int)
+ 2 -> {
+ if (CardLibStatus.SUCCESS == cardlibStat) {
+ iCardlibView.showInitCardlibResult(true, cardlibResult!!)
+ } else {
+ iCardlibView.showInitCardlibResult(false, cardlibResult!!)
+ }
+ }
+ }
+ }
+ }
+ }
+
+ fun initCardlib(acy: Activity) {
+ doProgressBar()
+ AsyncInitCardlib().execute(acy)
+ }
+
+ private inner class AsyncInitCardlib : AsyncTask<Activity, Unit, CardlibInitError?>() {
+ override fun onPostExecute(result: CardlibInitError?) {
+ if (result != null) {
+ cardlibStat = CardLibStatus.FAIL
+ cardlibResult = result.toString()
+ } else {
+ cardlibStat = CardLibStatus.SUCCESS
+ cardlibResult = "加载读卡库成功"
+ }
+ }
+
+ override fun doInBackground(vararg p0: Activity?): CardlibInitError? {
+ return try {
+ Cardlib.instance.init()
+ null
+ } catch (ex: CardlibInitError) {
+ ex
+ }
+ }
+ }
+
+ private fun doProgressBar() {
+ ThreadPool.getShortPool().execute(Runnable {
+ var i = 0
+ while (cardlibStat == CardLibStatus.INIT) {
+ CommonUtil.doSleep(100)
+ i++
+ if (i > 100) {
+ i = 100
+ }
+ sendMsg(1, i)
+ }
+ while (i < 100) {
+ CommonUtil.doSleep(20)
+ sendMsg(1, i++)
+ }
+ sendMsg(2, 100)
+ })
+ }
+
+ private fun sendMsg(retcode: Int, retmsg: Any) {
+ val msg = Message()
+ msg.what = retcode
+ msg.obj = retmsg
+ handler.sendMessage(msg)
+ }
+}
+
+private enum class CardLibStatus(num: Int) {
+ INIT(0),
+ SUCCESS(1),
+ FAIL(2)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/cardlib/ICardlibView.kt b/app/src/main/java/com/supwisdom/activities/cardlib/ICardlibView.kt
new file mode 100644
index 0000000..bdb8c6c
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/cardlib/ICardlibView.kt
@@ -0,0 +1,14 @@
+package com.supwisdom.activities.cardlib
+
+/**
+ * Created by zzq on 2017/11/7.
+ */
+interface ICardlibView {
+ fun showProgressDialog(msg: String)
+
+ fun closeProgressDialog()
+
+ fun showInitCardlibResult(issuccess: Boolean, msg: String)
+
+ fun showProgress(progress: Int)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/checkMngpwd/CheckMngpwdActivity.kt b/app/src/main/java/com/supwisdom/activities/checkMngpwd/CheckMngpwdActivity.kt
new file mode 100644
index 0000000..007c9cd
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/checkMngpwd/CheckMngpwdActivity.kt
@@ -0,0 +1,138 @@
+package com.supwisdom.activities.checkMngpwd
+
+import android.content.Intent
+import android.os.Bundle
+import android.os.CountDownTimer
+import android.view.KeyEvent
+import android.widget.TextView
+import com.supwisdom.R
+import com.supwisdom.activities.BaseActivity
+import com.supwisdom.activities.manage.ManageActivity
+import com.supwisdom.auxscreen.AuxScreenController
+import com.supwisdom.utils.CommonUtil
+import java.util.*
+
+/**
+ ** create by zzq on 2019/7/26
+ ** @desc
+ **/
+class CheckMngpwdActivity : BaseActivity() {
+ private var tmpPwd: String = ""
+ private lateinit var vTitle: TextView
+ private var password: String = ""
+ private var mode: String? = null
+ private var keyActive = true
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ this.setContentView(R.layout.activity_check_mngpwd)
+ initView()
+ }
+
+ private fun initView() {
+ vTitle = findViewById<TextView>(R.id.title)
+ }
+
+ override fun dispatchKeyEvent(event: KeyEvent): Boolean {
+ if (event.action == KeyEvent.ACTION_DOWN) {
+ if (!keyActive) {
+ return super.dispatchKeyEvent(event)
+ }
+ resetCounter(200)
+
+ val keyCode = event.keyCode
+ when (keyCode) {
+ KeyEvent.KEYCODE_0,
+ KeyEvent.KEYCODE_1,
+ KeyEvent.KEYCODE_2,
+ KeyEvent.KEYCODE_3,
+ KeyEvent.KEYCODE_4,
+ KeyEvent.KEYCODE_5,
+ KeyEvent.KEYCODE_6,
+ KeyEvent.KEYCODE_7,
+ KeyEvent.KEYCODE_8,
+ KeyEvent.KEYCODE_9 -> {
+ tmpPwd += keyCode - KeyEvent.KEYCODE_0
+ if (tmpPwd.length >= 6) {
+ if (checkMngPwd(tmpPwd)) {
+ jumpActivity(ManageActivity::class.java)
+ } else {
+ AuxScreenController.getInstance().refreshContent(Arrays.asList<String>("维护密码:", "密码错误"))
+ }
+ tmpPwd = ""
+ } else {
+ AuxScreenController.getInstance()
+ .refreshContent(Arrays.asList("维护密码:", CommonUtil.getPasswordStar(tmpPwd.length)))
+ }
+ }
+ KeyEvent.KEYCODE_DEL -> {
+ //cancel
+ val len = tmpPwd.length
+ when {
+ len == 1 -> {
+ tmpPwd = ""
+ AuxScreenController.getInstance()
+ .refreshContent(Arrays.asList("维护密码:", CommonUtil.getPasswordStar(tmpPwd.length)))
+ }
+ len > 1 -> {
+ tmpPwd = tmpPwd.substring(0, len - 1)
+ AuxScreenController.getInstance()
+ .refreshContent(Arrays.asList("维护密码:", CommonUtil.getPasswordStar(tmpPwd.length)))
+ }
+ else -> finish()
+ }
+ }
+ }
+ }
+ return super.dispatchKeyEvent(event)
+ }
+
+ override fun onResume() {
+ super.onResume()
+ keyActive = true
+ password = this.intent.getStringExtra("password")
+ mode = this.intent.getStringExtra("mode")
+ refresh()
+ }
+
+ override fun onNewIntent(intent: Intent) {
+ super.onNewIntent(intent)
+ this.intent.putExtra("password", intent.getStringExtra("password"))
+ this.intent.putExtra("mode", intent.getStringExtra("mode"))
+ }
+
+ private fun refresh() {
+ tmpPwd = ""
+ vTitle.text = "维护密码验证"
+ AuxScreenController.getInstance().refreshTitle("维护密码验证")
+ AuxScreenController.getInstance().refreshBottom("取消键返回上页")
+ AuxScreenController.getInstance().refreshContent(Arrays.asList<String>("维护密码:", " "))
+ }
+
+ private fun checkMngPwd(inputPwd: String): Boolean {
+ return inputPwd == password
+ }
+
+ private var counter: ContinuePressTimer? = null
+
+ private fun resetCounter(timems: Long) {
+ counter?.cancel()
+ if (counter == null) {
+ counter = ContinuePressTimer(timems, 100)
+ }
+ keyActive = false
+ counter!!.start()
+ }
+
+ private inner class ContinuePressTimer internal constructor(millisInFuture: Long, countDownInterval: Long) :
+ CountDownTimer(millisInFuture, countDownInterval) {
+
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ keyActive = true
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/checkShoppwd/CheckShoppwdActivity.kt b/app/src/main/java/com/supwisdom/activities/checkShoppwd/CheckShoppwdActivity.kt
new file mode 100644
index 0000000..5b12e29
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/checkShoppwd/CheckShoppwdActivity.kt
@@ -0,0 +1,161 @@
+package com.supwisdom.activities.checkShoppwd
+
+import android.content.Intent
+import android.os.Bundle
+import android.os.CountDownTimer
+import android.view.KeyEvent
+import android.widget.TextView
+import com.supwisdom.R
+import com.supwisdom.activities.BaseActivity
+import com.supwisdom.activities.SPApplication
+import com.supwisdom.activities.consume.ConsumeActivity
+import com.supwisdom.activities.consume.bean.CardUserInfoBean
+import com.supwisdom.auxscreen.AuxScreenController
+import com.supwisdom.utils.CommonUtil
+import com.supwisdom.utils.SoundUtil
+import java.util.*
+
+/**
+ ** create by zzq on 2019/7/26
+ ** @desc
+ **/
+class CheckShoppwdActivity : BaseActivity() {
+ private var tmpPwd: String = ""
+ private lateinit var vTitle: TextView
+ private lateinit var vContent: TextView
+ private var keyActive = true
+ private var transdtlType: String? = null
+ private val pos = SPApplication.getInstance().getPos()
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ this.setContentView(R.layout.activity_check_mngpwd)
+ initView()
+ }
+
+ private fun initView() {
+ vTitle = findViewById<TextView>(R.id.title)
+ vContent = findViewById<TextView>(R.id.content)
+ }
+
+ override fun dispatchKeyEvent(event: KeyEvent): Boolean {
+ if (event.action == KeyEvent.ACTION_DOWN) {
+ if (!keyActive) {
+ return super.dispatchKeyEvent(event)
+ }
+ resetCounter(200)
+
+ val keyCode = event.keyCode
+ when (keyCode) {
+ KeyEvent.KEYCODE_0,
+ KeyEvent.KEYCODE_1,
+ KeyEvent.KEYCODE_2,
+ KeyEvent.KEYCODE_3,
+ KeyEvent.KEYCODE_4,
+ KeyEvent.KEYCODE_5,
+ KeyEvent.KEYCODE_6,
+ KeyEvent.KEYCODE_7,
+ KeyEvent.KEYCODE_8,
+ KeyEvent.KEYCODE_9 -> {
+ tmpPwd += keyCode - KeyEvent.KEYCODE_0
+ if (tmpPwd.length >= 6) {
+ if (checkMngPwd(tmpPwd)) {
+ doReverse()
+ } else {
+ AuxScreenController.getInstance().refreshContent(Arrays.asList<String>("商户密码:", "密码错误"))
+ }
+ tmpPwd = ""
+ } else {
+ AuxScreenController.getInstance()
+ .refreshContent(Arrays.asList("商户密码:", CommonUtil.getPasswordStar(tmpPwd.length)))
+ }
+ }
+ KeyEvent.KEYCODE_DEL -> {
+ //cancel
+ val len = tmpPwd.length
+ when {
+ len == 1 -> {
+ tmpPwd = ""
+ AuxScreenController.getInstance()
+ .refreshContent(Arrays.asList("商户密码:", CommonUtil.getPasswordStar(tmpPwd.length)))
+ }
+ len > 1 -> {
+ tmpPwd = tmpPwd.substring(0, len - 1)
+ AuxScreenController.getInstance()
+ .refreshContent(Arrays.asList("商户密码:", CommonUtil.getPasswordStar(tmpPwd.length)))
+ }
+ else -> finish()
+ }
+ }
+ }
+ }
+ return super.dispatchKeyEvent(event)
+ }
+
+ override fun onResume() {
+ super.onResume()
+ keyActive = true
+ transdtlType = this.intent.getStringExtra("transdtlType")
+ refresh()
+ }
+
+ override fun onNewIntent(intent: Intent) {
+ super.onNewIntent(intent)
+ this.intent.putExtra("transdtlType", intent.getStringExtra("transdtlType"))
+ }
+
+ private fun refresh() {
+ tmpPwd = ""
+ vTitle.text = "手工冲正"
+ vContent.text = ""
+ AuxScreenController.getInstance().refreshTitle("商户密码验证")
+ AuxScreenController.getInstance().refreshBottom("取消键撤销输入")
+ AuxScreenController.getInstance().refreshContent(Arrays.asList<String>("商户密码:", " "))
+ }
+
+ private fun checkMngPwd(inputPwd: String): Boolean {
+ return inputPwd == pos.getConfigPara()!!.shopPwd
+ }
+
+ private fun doReverse() {
+
+ }
+
+ private fun showRvsSuc(info: CardUserInfoBean) {
+ val tmp = String.format("金额: %.02f元", info.payamt / 100.0f)
+ vContent.text = "冲正成功\n$tmp"
+ SoundUtil.playMusic(applicationContext, R.raw.reversal_suc)
+ AuxScreenController.getInstance().refreshContent(Arrays.asList<String>("冲正成功", tmp))
+ jumpActivity(ConsumeActivity::class.java)
+ }
+
+ private fun showRvsFail(errmsg: String) {
+ vContent.text = "冲正失败\n$errmsg"
+ SoundUtil.playMusic(applicationContext, R.raw.reversal_fail)
+ AuxScreenController.getInstance().refreshContent(Arrays.asList<String>("冲正失败", errmsg))
+ jumpActivity(ConsumeActivity::class.java)
+ }
+
+ private var counter: ContinuePressTimer? = null
+
+ private fun resetCounter(timems: Long) {
+ counter?.cancel()
+ if (counter == null) {
+ counter = ContinuePressTimer(timems, 100)
+ }
+ keyActive = false
+ counter!!.start()
+ }
+
+ private inner class ContinuePressTimer internal constructor(millisInFuture: Long, countDownInterval: Long) :
+ CountDownTimer(millisInFuture, countDownInterval) {
+
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ keyActive = true
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/communicate/CommunicateActivity.kt b/app/src/main/java/com/supwisdom/activities/communicate/CommunicateActivity.kt
new file mode 100644
index 0000000..e511752
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/communicate/CommunicateActivity.kt
@@ -0,0 +1,114 @@
+package com.supwisdom.activities.communicate
+
+import android.os.Bundle
+import android.text.TextUtils
+import android.view.KeyEvent
+import android.view.View
+import android.widget.EditText
+import android.widget.TextView
+import com.supwisdom.R
+import com.supwisdom.activities.BaseActivity
+import com.supwisdom.activities.SPApplication
+import com.supwisdom.auxscreen.AuxScreenController
+import com.supwisdom.utils.CommonUtil
+import com.supwisdom.utils.PublicDef
+import com.supwisdom.view.SWToast
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc 通讯参数配置
+ **/
+class CommunicateActivity : BaseActivity() {
+ private val pos = SPApplication.getInstance().getPos()
+ private lateinit var vDevphyid: TextView
+ private lateinit var vEpayUrl: EditText
+ private lateinit var vEpayUri: EditText
+ private lateinit var vEpayPort: EditText
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_communicate)
+ initView()
+ initData()
+ }
+
+ private fun initView() {
+ vDevphyid = findViewById<View>(R.id.comm_devphyid) as TextView
+ vEpayUrl = findViewById<View>(R.id.comm_epay_url) as EditText
+ vEpayUri = findViewById<View>(R.id.comm_epay_uri) as EditText
+ vEpayPort = findViewById<View>(R.id.comm_epay_port) as EditText
+
+ this.findViewById<View>(R.id.btn_cancel).setOnClickListener { finish() }
+ this.findViewById<View>(R.id.btn_confirm).setOnClickListener(View.OnClickListener {
+ val record = pos.getConfigPara()
+ val url = CommonUtil.getEditView(vEpayUrl)
+ if (TextUtils.isEmpty(url)) {
+ showSWToastInfo("服务器地址不能为空", PublicDef.TOAST_SHOW_CRY)
+ return@OnClickListener
+ }
+ record!!.epayIP = url
+
+ val uri = CommonUtil.getEditView(vEpayUri)
+ if (TextUtils.isEmpty(uri)) {
+ showSWToastInfo("服务器标识不对", PublicDef.TOAST_SHOW_CRY)
+ return@OnClickListener
+ }
+ record.epayUri = uri
+
+ try {
+ val port = Integer.valueOf(CommonUtil.getEditView(vEpayPort))
+ if (port > 0xFFFF) {
+ showSWToastInfo("服务器端口太大", PublicDef.TOAST_SHOW_CRY)
+ return@OnClickListener
+ }
+ record.epayPort = port
+ } catch (e: Exception) {
+ showSWToastInfo("服务器端口不对", PublicDef.TOAST_SHOW_CRY)
+ return@OnClickListener
+ }
+
+ if (!pos.replaceConfigPara(record)) {
+ showSWToastInfo("保存失败", PublicDef.TOAST_SHOW_CRY)
+ return@OnClickListener
+ }
+ showSWToastInfo("保存成功", PublicDef.TOAST_SHOW_SMILE)
+ finish()
+ })
+ }
+
+ public override fun onResume() {
+ super.onResume()
+ refresh()
+ }
+
+ private fun initData() {
+ val record = pos.getConfigPara()
+ vDevphyid.text = record!!.devphyid
+ vEpayUrl.setText(record.epayIP)
+ vEpayUri.setText(record.epayUri)
+ vEpayPort.setText(record.epayPort.toString())
+ }
+
+ private fun refresh() {
+ AuxScreenController.getInstance().refreshTitle("通讯参数设置")
+ AuxScreenController.getInstance().refreshBottom("确定键返回上页")
+ AuxScreenController.getInstance().refreshContent(listOf<String>("请到大屏进行配置"))
+ }
+
+ override fun dispatchKeyEvent(event: KeyEvent): Boolean {
+ if (event.action == KeyEvent.ACTION_DOWN) {
+ when (event.keyCode) {
+ KeyEvent.KEYCODE_DEL -> {
+ }
+ KeyEvent.KEYCODE_ENTER -> finish()
+ }//cancel
+ //和触屏删除键冲突
+ // finish();
+ }
+ return super.dispatchKeyEvent(event)
+ }
+
+ private fun showSWToastInfo(msg: String, showway: Int) {
+ SWToast.show(applicationContext, msg, showway)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/consume/BeepManager.kt b/app/src/main/java/com/supwisdom/activities/consume/BeepManager.kt
new file mode 100644
index 0000000..4973200
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/consume/BeepManager.kt
@@ -0,0 +1,109 @@
+package com.supwisdom.activities.consume
+
+import android.app.Activity
+import android.content.Context
+import android.media.AudioManager
+import android.media.MediaPlayer
+import android.os.Vibrator
+import com.newcapec.zxinglib.PreferencesSetting
+import com.supwisdom.R
+import java.io.Closeable
+import java.io.IOException
+
+
+/**
+ * @author zzq
+ * @date 2018/4/25.
+ * @version 1.0.1
+ * @desc 滴滴声
+ */
+@Suppress("DEPRECATION")
+class BeepManager constructor(context: Context) : MediaPlayer.OnErrorListener, Closeable {
+ private val context = context
+
+ private val BEEP_VOLUME = 0.10f
+ private val VIBRATE_DURATION = 200L
+
+ private var mediaPlayer: MediaPlayer? = null
+ private var playBeep: Boolean = false
+ private var vibrate: Boolean = false
+
+ init {
+ updatePrefs()
+ }
+
+ @Synchronized
+ fun updatePrefs() {
+ //SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
+ playBeep = shouldBeep(context)
+ vibrate = PreferencesSetting.PREFER_VIBRATE
+ if (playBeep && mediaPlayer == null) {
+ // The volume on STREAM_SYSTEM is not adjustable, and users found it too loud,
+ // so we now play on the music stream.
+ (context as Activity).volumeControlStream = AudioManager.STREAM_MUSIC
+ mediaPlayer = buildMediaPlayer(context)
+ }
+ }
+
+ @Synchronized
+ fun playBeepSoundAndVibrate() {
+ if (playBeep && mediaPlayer != null) {
+ mediaPlayer!!.start()
+ }
+ if (vibrate) {
+ val vibrator = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
+ vibrator.vibrate(VIBRATE_DURATION)
+ }
+ }
+
+ private fun shouldBeep(activity: Context): Boolean {
+ var shouldPlayBeep = PreferencesSetting.PREFER_PLAY_BEEP
+ if (shouldPlayBeep) {
+ // See if sound settings overrides this
+ val audioService = activity.getSystemService(Context.AUDIO_SERVICE) as AudioManager
+ if (audioService.ringerMode != AudioManager.RINGER_MODE_NORMAL) {
+ shouldPlayBeep = false
+ }
+ }
+ return shouldPlayBeep
+ }
+
+ private fun buildMediaPlayer(activity: Context): MediaPlayer? {
+ val mediaPlayer = MediaPlayer()
+ return try {
+ activity.resources.openRawResourceFd(R.raw.beep).use { it ->
+ mediaPlayer.setDataSource(it.fileDescriptor, it.startOffset, it.length)
+ }
+ mediaPlayer.setOnErrorListener(this)
+ mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC)
+ mediaPlayer.isLooping = false
+ mediaPlayer.setVolume(BEEP_VOLUME, BEEP_VOLUME)
+ mediaPlayer.prepare()
+ mediaPlayer
+ } catch (ex: IOException) {
+ mediaPlayer.release()
+ null
+ }
+ }
+
+ @Synchronized
+ override fun onError(mp: MediaPlayer, what: Int, extra: Int): Boolean {
+ if (what == MediaPlayer.MEDIA_ERROR_SERVER_DIED) {
+ // we are finished, so put up an appropriate error toast if required and finish
+ (context as Activity).finish()
+ } else {
+ // possibly media player error, so release and recreate
+ close()
+ updatePrefs()
+ }
+ return true
+ }
+
+ @Synchronized
+ override fun close() {
+ if (mediaPlayer != null) {
+ mediaPlayer!!.release()
+ mediaPlayer = null
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/consume/ConsumeActivity.kt b/app/src/main/java/com/supwisdom/activities/consume/ConsumeActivity.kt
new file mode 100644
index 0000000..6308775
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/consume/ConsumeActivity.kt
@@ -0,0 +1,547 @@
+package com.supwisdom.activities.consume
+
+import android.annotation.SuppressLint
+import android.app.Activity
+import android.content.Intent
+import android.graphics.Color
+import android.os.Bundle
+import android.os.CountDownTimer
+import android.view.KeyEvent
+import android.view.View
+import android.widget.ImageView
+import android.widget.LinearLayout
+import android.widget.TextView
+import com.supwisdom.R
+import com.supwisdom.activities.BaseActivity
+import com.supwisdom.activities.SPApplication
+import com.supwisdom.activities.consume.bean.CardUserInfoBean
+import com.supwisdom.activities.menu.MenuActivity
+import com.supwisdom.activities.transdtl.TransdtlActivity
+import com.supwisdom.auxscreen.AuxScreenController
+import com.supwisdom.entity.PayStatus
+import com.supwisdom.entity.ReversalFlag
+import com.supwisdom.entity.TransdtlUnionRecord
+import com.supwisdom.utils.CommonUtil
+import com.supwisdom.utils.DateUtil
+import com.supwisdom.utils.PublicDef
+import com.supwisdom.utils.SoundUtil
+import com.supwisdom.view.DialogPurchase
+import java.util.*
+import java.util.concurrent.locks.ReentrantLock
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+@Suppress("DEPRECATION")
+@SuppressLint("NewApi")
+class ConsumeActivity : BaseActivity(), IConsumeView {
+ private lateinit var amountTxt: TextView
+ private lateinit var presenter: ConsumePresenter
+ private lateinit var vLinkstat: TextView
+ private lateinit var vShopname: TextView
+ private lateinit var vCustname: TextView
+ private lateinit var vStuempno: TextView
+ private lateinit var vCardstatus: TextView
+ private lateinit var vBalance: TextView
+ private lateinit var vTime: TextView
+ private lateinit var vLinkLogo: ImageView
+ private lateinit var vLastResult: TextView
+ private lateinit var vLastPayamt: TextView
+ private lateinit var vLastPayway: TextView
+ private lateinit var vLastPayday: TextView
+ private lateinit var vLastPaytime: TextView
+ private lateinit var vLastPayFailreason: TextView
+ private lateinit var vLastPayFailll: LinearLayout
+ private lateinit var vLastPayamtll: LinearLayout
+ private var beepManager: BeepManager? = null
+ private val scanLock = ReentrantLock()
+ @Volatile
+ private var codeSwitchEnable = false
+ @Volatile
+ private var payStatusEnable = false
+ @Volatile
+ private var isBackRuning = false
+ private var addAmount: Int = 0
+ @Volatile
+ private var amount: Int = 0
+ private var payWay: String? = null
+ private var counter: LastPayShowTimer? = null
+ private var lastPayInfo: CardUserInfoBean? = null
+ private var dialogPurchase: DialogPurchase? = null
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_consume)
+
+ initView()
+ initData()
+ }
+
+ private fun initData() {
+ presenter = ConsumePresenter(this)
+ presenter.start()
+ beepManager = BeepManager(this)
+ dialogPurchase = DialogPurchase(this, object : DialogPurchase.ICallBack {
+ override fun callback(isManualCancel: Boolean) {
+ presenter.clickNoPay()
+ amountTxt.text = ""
+ }
+
+ override fun callback(code: String) {
+ //扫码和寻卡消费互斥
+ if (!codeSwitchEnable) {
+ return
+ }
+ if (!scanLock.tryLock()) {
+ return
+ }
+ try {
+ //正在扣款
+ if (dialogPurchase!!.codePaying) {
+ return
+ }
+ //已扣款
+ if (!payStatusEnable) {
+ return
+ }
+ beepManager!!.playBeepSoundAndVibrate()
+ presenter.clickNoPay()
+ dialogPurchase!!.codePaying = true
+ dialogPurchase!!.codePayingNoCancelEnable = true
+ payStatusEnable = false
+ presenter.codeToPay(code, amount)
+ } finally {
+ scanLock.unlock()
+ }
+ }
+ })
+ }
+
+ private fun initView() {
+ vShopname = this.findViewById<TextView>(R.id.consume_shopname)
+ vLinkLogo = this.findViewById<ImageView>(R.id.consume_linklogo)
+ vLinkstat = this.findViewById<TextView>(R.id.consume_linkstat)
+ amountTxt = this.findViewById<TextView>(R.id.consume_amt)
+ vCustname = this.findViewById<TextView>(R.id.consume_custname)
+ vStuempno = this.findViewById<TextView>(R.id.consume_stuempno)
+ vCardstatus = this.findViewById<TextView>(R.id.consume_cardstatus)
+ vBalance = this.findViewById<TextView>(R.id.consume_balance)
+ vTime = this.findViewById<TextView>(R.id.consume_time)
+ vLastResult = this.findViewById<TextView>(R.id.consume_last_result)
+ vLastPayamt = this.findViewById<TextView>(R.id.consume_last_payamt)
+ vLastPayway = this.findViewById<TextView>(R.id.consume_last_payway)
+ vLastPayday = this.findViewById<TextView>(R.id.consume_last_payday)
+ vLastPaytime = this.findViewById<TextView>(R.id.consume_last_paytime)
+ vLastPayFailreason = this.findViewById<TextView>(R.id.consume_last_failreason)
+ vLastPayFailll = this.findViewById<LinearLayout>(R.id.ll_consume_last_failreason)
+ vLastPayamtll = this.findViewById<LinearLayout>(R.id.ll_consume_last_payamt)
+ }
+
+ override fun onStop() {
+ super.onStop()
+ isBackRuning = true
+ }
+
+ override fun onDestroy() {
+ SoundUtil.releaseMusic()
+ presenter.stop()
+ beepManager!!.close()
+ super.onDestroy()
+ }
+
+ @SuppressLint("SetTextI18n")
+ override fun dispatchKeyEvent(event: KeyEvent): Boolean {
+ if (event.action == KeyEvent.ACTION_DOWN) {
+ val keyCode = event.keyCode
+ when (keyCode) {
+ KeyEvent.KEYCODE_BACK -> {
+ amountTxt.text = "0"
+ presenter.clickNoPay()
+ }
+ KeyEvent.KEYCODE_0,
+ KeyEvent.KEYCODE_1,
+ KeyEvent.KEYCODE_2,
+ KeyEvent.KEYCODE_3,
+ KeyEvent.KEYCODE_4,
+ KeyEvent.KEYCODE_5,
+ KeyEvent.KEYCODE_6,
+ KeyEvent.KEYCODE_7,
+ KeyEvent.KEYCODE_8,
+ KeyEvent.KEYCODE_9 -> {
+ presenter.clickNoPay()
+ addValueToEdit(keyCode - KeyEvent.KEYCODE_0)
+ }
+ KeyEvent.KEYCODE_POUND, KeyEvent.KEYCODE_PERIOD -> {
+ presenter.clickNoPay()
+ val str = amountTxt.text.toString()
+ if (str.length < 8 && str.indexOf('.') < 0) {
+ amountTxt.text = "$str."
+ showScreenAmount()
+ }
+ }
+ KeyEvent.KEYCODE_NUMPAD_ADD -> {
+ //'+'
+ addAmount += getCurAmount()
+ amountTxt.text = ""
+ showScreenAmount()
+ }
+ KeyEvent.KEYCODE_DPAD_LEFT -> {
+ //'F1'
+ isBackRuning = true
+ jumpActivity(MenuActivity::class.java)
+ }
+// KeyEvent.KEYCODE_DPAD_UP ->
+ //'F2'
+// KeyEvent.KEYCODE_DPAD_DOWN ->
+ //'F3'
+ KeyEvent.KEYCODE_DPAD_RIGHT -> {
+ //'F4'
+ jumpActivity(TransdtlActivity::class.java)
+ }
+ KeyEvent.KEYCODE_DEL -> {
+ //cancel
+ presenter.clickNoPay()
+ delValueToEdit()
+ }
+ KeyEvent.KEYCODE_ENTER -> {
+ checkAmtToPay()
+ }
+ }
+ }
+ return super.dispatchKeyEvent(event)
+ }
+
+ override fun showUserInfo(info: CardUserInfoBean) {
+ CommonUtil.acquireWakeLock(this)
+ vCustname.text = info.username
+ if (info.retcode == PublicDef.SUCCESS) {
+ vCardstatus.text = "暂未实现"//PublicDef.CARD_STAT_MAP[info.cardstat]
+ if (info.cardstatus != 0) {
+ vCardstatus.setTextColor(Color.RED)
+ } else {
+ vCardstatus.setTextColor(resources.getColor(R.color.blue))
+ }
+ if (info.balance == null) {
+ vBalance.text = null
+ } else {
+ vBalance.text = String.format("%.02f 元", info.balance!! / 100.0f)
+ }
+ } else {
+ vCardstatus.text = info.retmsg
+ vCardstatus.setTextColor(Color.RED)
+ vBalance.text = null
+ }
+ }
+
+ private var lastshowtime: String? = null
+ override fun clearUserInfo(datetime: String) {
+ if (!isBackRuning) {
+ vCustname.text = null
+ vStuempno.text = null
+ vCardstatus.text = null
+ vBalance.text = null
+ val tmptime = datetime.substring(0, 16)
+ if (lastshowtime != tmptime) {
+ lastshowtime = tmptime
+ vTime.text = tmptime
+ AuxScreenController.getInstance().refreshBottom(tmptime)
+ }
+ if (dialogPurchase!!.isShowing &&
+ !dialogPurchase!!.isFixPay &&
+ payStatusEnable
+ ) {
+ beepManager!!.playBeepSoundAndVibrate()
+ }
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ isBackRuning = false
+ beepManager!!.updatePrefs()
+ dealIntent()
+ refresh()
+ refreshRecentDtl(lastPayInfo)
+ }
+
+ private fun dealIntent() {
+ amount = this.intent.getIntExtra("amount", 0)
+ payWay = this.intent.getStringExtra("payway")
+ this.intent.putExtra("amount", "0")
+ this.intent.putExtra("payway", "")
+ }
+
+ override fun onNewIntent(intent: Intent) {
+ this.intent.putExtra("amount", intent.getStringExtra("amount"))
+ this.intent.putExtra("payway", intent.getStringExtra("payway"))
+ }
+
+ private fun refresh() {
+ addAmount = 0
+ amountTxt.text = "0"
+ var shopname = SPApplication.getInstance().getPos().getDynamicPara()!!.shopname
+ if (shopname == null || shopname.length < 9) {
+ vShopname.textSize = resources.getDimension(R.dimen.consume_shopname_text_size_normal)
+ } else {
+ vShopname.textSize = resources.getDimension(R.dimen.consume_shopname_text_size_middle)
+ if (shopname.length > 10) {
+ val len = shopname.length / 2
+ shopname = shopname.substring(0, len) + "\n" + shopname.substring(len)
+ }
+ }
+ vShopname.text = shopname
+
+ refreshLinkStatus(SPApplication.getInstance().isOnline())
+ AuxScreenController.getInstance().refreshBottom(DateUtil.getNowDateTime().substring(0, 16))
+ AuxScreenController.getInstance().refreshContent(Arrays.asList(" 欢迎光临!", " 请刷卡..."))
+
+ val record = SPApplication.getInstance().getPos().getControlPara(PublicDef.CONTROL_FIXAMT)
+ if (record != null && PublicDef.CONTROL_NO_FIXPAY_FLAG != record.paraval) {
+ try {
+ amount = Integer.parseInt(record.paraval)
+ amountTxt.text = String.format("%.02f", amount / 100.0f)
+ presenter.clickToPay(amount)
+ showDialogPay()
+ } catch (ex: Exception) {
+ ex.printStackTrace()
+ }
+ }
+ }
+
+ override fun refreshLinkStatus(isOnline: Boolean) {
+ if (isOnline) {
+ vLinkLogo.setImageDrawable(getDrawable(R.drawable.wireless_on))
+ vLinkstat.text = "联机"
+ vLinkstat.setTextColor(resources.getColor(R.color.blue))
+ AuxScreenController.getInstance().refreshTitle("联机 F4查看上笔记录")
+ } else {
+ vLinkLogo.setImageDrawable(getDrawable(R.drawable.wireless_off))
+ vLinkstat.text = "脱机"
+ vLinkstat.setTextColor(Color.RED)
+ AuxScreenController.getInstance().refreshTitle("脱机 F4查看上笔记录")
+ }
+ }
+
+ override fun showConsumeSuc(info: CardUserInfoBean) {
+ dialogPurchase!!.showPaySuccess(info)
+ val auxList = ArrayList<String>()
+ auxList.add(info.retmsg!!)
+ auxList.add(CommonUtil.showFormatAmount("金额", info.payamt))
+ when {
+ info.amount > info.payamt -> {
+ auxList.add(CommonUtil.showFormatAmount("折扣", info.amount - info.payamt))
+ }
+ info.amount < info.payamt -> {
+ auxList.add(CommonUtil.showFormatAmount("搭伙", info.payamt - info.amount))
+ }
+ }
+ if (info.balance != null) {
+ auxList.add(CommonUtil.showFormatAmount("余额", info.balance!!))
+ }
+ AuxScreenController.getInstance().refreshContent(auxList)
+ SoundUtil.playMusic(applicationContext, R.raw.consume_suc)
+ }
+
+ override fun showConsumeHint(hint: String) {
+ val amountStr = CommonUtil.showFormatAmount("金额", amount)
+ dialogPurchase!!.showProcess(hint, amountStr)
+ AuxScreenController.getInstance().refreshContent(Arrays.asList(hint, amountStr))
+ }
+
+ override fun showConsumeFail(info: CardUserInfoBean) {
+ dialogPurchase!!.showPayFail(info)
+ SoundUtil.playMusic(applicationContext, R.raw.consume_fail)
+ AuxScreenController.getInstance().refreshContent(Arrays.asList<String>("消费失败", "原因:", info.retmsg))
+ }
+
+ override fun showReverseSuc(info: CardUserInfoBean) {
+ dialogPurchase!!.showReverseSuccess(info)
+ AuxScreenController.getInstance()
+ .refreshContent(Arrays.asList<String>(info.retmsg, CommonUtil.showFormatAmount("金额", info.payamt)))
+ SoundUtil.playMusic(applicationContext, R.raw.reversal_suc)
+ }
+
+ override fun showReverseFail(info: CardUserInfoBean) {
+ dialogPurchase!!.showReverseFail(info)
+ SoundUtil.playMusic(applicationContext, R.raw.reversal_fail)
+ AuxScreenController.getInstance().refreshContent(Arrays.asList<String>("冲正失败", "原因:", info.retmsg))
+ }
+
+ private var lastShowRecentDatetime: String? = null
+ private fun refreshRecentDtl(info: CardUserInfoBean?) {
+ if (info != null) {
+ lastPayInfo = info
+ //已显示过不在显示
+ if (lastShowRecentDatetime == info.datetime) {
+ return
+ }
+ lastShowRecentDatetime = info.datetime
+
+ if (info.status == PayStatus.SUC) {
+ when {
+ info.reversalFlag == ReversalFlag.AUTO -> vLastResult.text = "自动冲正"
+ info.reversalFlag == ReversalFlag.MANUAL -> vLastResult.text = "手动撤销"
+ else -> vLastResult.text = "消费成功"
+ }
+ vLastPayFailll.visibility = View.GONE
+ vLastPayamtll.visibility = View.VISIBLE
+ vLastPayamt.text = String.format("%.02f元", info.payamt / 100.0f)
+ } else {
+ if (info.reversalFlag == ReversalFlag.AUTO ||
+ info.reversalFlag == ReversalFlag.MANUAL
+ ) {
+ vLastResult.text = "冲正失败"
+ } else {
+ vLastResult.text = "消费失败"
+ }
+ vLastPayFailll.visibility = View.VISIBLE
+ vLastPayamtll.visibility = View.GONE
+ vLastPayFailreason.text = info.retmsg
+ }
+
+ vLastPayway.text = if (info.payway == "code") {
+ "二维码"
+ } else {
+ "市民卡"
+ }
+ val sb = StringBuilder()
+ sb.append(info.datetime!!.substring(0, 4)).append("/")
+ .append(info.datetime!!.substring(4, 6)).append("/")
+ .append(info.datetime!!.substring(6, 8))
+ vLastPayday.text = sb.toString()
+ sb.setLength(0)
+ sb.append(info.datetime!!.substring(8, 10)).append(":")
+ .append(info.datetime!!.substring(10, 12)).append(":").append(info.datetime!!.substring(12))
+ vLastPaytime.text = sb.toString()
+ resetPayShowCounter(10 * 1000)
+ }
+ }
+
+ private fun delValueToEdit() {
+ presenter.clickNoPay()
+ val str = amountTxt.text.toString()
+ val len = str.length
+ when {
+ len == 0 ||
+ len == 1 -> {
+ refresh()
+ }
+ len > 1 -> {
+ amountTxt.text = str.substring(0, len - 1)
+ showScreenAmount()
+ }
+ }
+ }
+
+ private fun checkAmtToPay() {
+ amount = getCurAmount() + addAmount
+ if (amount > 0) {
+ amountTxt.text = String.format("%.02f", amount / 100.0f)
+ presenter.clickToPay(amount)
+ showDialogPay()
+ } else {
+ AuxScreenController.getInstance().refreshContent(Arrays.asList("请先输入金额:", "金额不能为0"))
+ }
+ }
+
+ private fun showDialogPay() {
+ dialogPurchase!!.codePaying = false
+ dialogPurchase!!.isFixPay = false
+ dialogPurchase!!.codePayingNoCancelEnable = false
+ dialogPurchase!!.show("请刷卡", CommonUtil.showFormatAmount("金额", amount))
+ }
+
+ private fun getCurAmount(): Int {
+ return try {
+ CommonUtil.YuanToFen(java.lang.Double.parseDouble(amountTxt.text.toString().trim { it <= ' ' }))
+ } catch (ex: Exception) {
+ ex.printStackTrace()
+ 0
+ }
+ }
+
+ private fun addValueToEdit(value: Int) {
+ var str = amountTxt.text.toString()
+ if ("0" == str) {
+ str = ""
+ }
+ //如果已经有小数点,则小数点后面不能超过两位
+ if (str.indexOf(".") > 0) {
+ if (str.length - str.indexOf(".") <= 2) {
+ amountTxt.text = "$str$value"
+ }
+ } else {
+ //限制消费金额<1000
+ if (str.length < 3) {
+ amountTxt.text = "$str$value"
+ }
+ }
+ showScreenAmount()
+ }
+
+ private fun clearLastPayResult() {
+ vLastResult.text = null
+ vLastPayamt.text = null
+ vLastPayway.text = null
+ vLastPayday.text = null
+ vLastPaytime.text = null
+ vLastPayFailreason.text = null
+ }
+
+ private fun showScreenAmount() {
+ if (addAmount > 0) {
+ AuxScreenController.getInstance().refreshContent(
+ Arrays.asList(
+ "输入金额: +" + String.format("%.02f", addAmount / 100.0f),
+ amountTxt.text.toString()
+ )
+ )
+ } else {
+ AuxScreenController.getInstance().refreshContent(Arrays.asList("输入金额:", amountTxt.text.toString()))
+ }
+ }
+
+ override fun getActivity(): Activity {
+ return this
+ }
+
+ override fun isBackRuning(): Boolean {
+ return isBackRuning
+ }
+
+ override fun showRecentDtl(record: TransdtlUnionRecord?) {
+ if (record != null) {
+ val info = CardUserInfoBean(PublicDef.SUCCESS, "")
+ info.datetime = record.transdate + record.transtime
+ info.username = record.username
+ info.payamt = record.payamt
+ info.status = record.status
+ info.payway = record.payway
+ info.reversalFlag = record.reversalflag
+ refreshRecentDtl(info)
+ }
+ }
+
+ override fun codeScannerEnable(enable: Boolean) {
+ codeSwitchEnable = enable
+ }
+
+ private fun resetPayShowCounter(timems: Long) {
+ counter?.cancel()
+ counter = LastPayShowTimer(timems, 500)
+ counter?.start()
+ }
+
+ private inner class LastPayShowTimer(millisInFuture: Long, countDownInterval: Long) :
+ CountDownTimer(millisInFuture, countDownInterval) {
+
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ clearLastPayResult()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/consume/ConsumePresenter.kt b/app/src/main/java/com/supwisdom/activities/consume/ConsumePresenter.kt
new file mode 100644
index 0000000..268a67f
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/consume/ConsumePresenter.kt
@@ -0,0 +1,102 @@
+package com.supwisdom.activities.consume
+
+import android.os.Handler
+import android.os.Looper
+import android.os.Message
+import com.supwisdom.activities.consume.bean.CardUserInfoBean
+import com.supwisdom.activities.consume.mode.CardPayService
+import com.supwisdom.activities.consume.mode.CodePayService
+import com.supwisdom.utils.LogUtil
+import com.supwisdom.utils.PublicDef
+import com.supwisdom.utils.ThreadPool
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class ConsumePresenter constructor(iConsumeView: IConsumeView) {
+ private val TAG = "ConsumePresenter"
+ private val iConsumeView = iConsumeView
+ private val codePayRunnable = CodePayRunnable()
+ private lateinit var handler: Handler
+ private var cardPayService: CardPayService
+ private var codePayService: CodePayService
+ @Volatile
+ private var code: String? = null
+ @Volatile
+ private var amount: Int = 0
+
+ init {
+ createHandler()
+ cardPayService = CardPayService(iConsumeView, handler)
+ codePayService = CodePayService(iConsumeView, handler)
+ }
+
+ private fun createHandler() {
+ handler = object : android.os.Handler(Looper.getMainLooper()) {
+ override fun handleMessage(msg: Message) {
+ when (msg.what) {
+ PublicDef.MSG_CARD_PAY_SUC -> iConsumeView.showConsumeSuc(msg.obj as CardUserInfoBean)
+ PublicDef.MSG_CARD_PAYING,
+ PublicDef.MSG_CARD_READ_AGAIN -> iConsumeView.showConsumeHint(msg.obj as String)
+ PublicDef.MSG_CARD_PAY_FAIL -> {
+ val ret = msg.obj as CardUserInfoBean
+ LogUtil.d(TAG, "pay fail,reason=${ret.retmsg}")
+ iConsumeView.showConsumeFail(ret)
+ }
+ PublicDef.MSG_CARD_REVERSE_FAIL -> {
+ val ret = msg.obj as CardUserInfoBean
+ LogUtil.d(TAG, "reverse fail,reason=${ret.retmsg}")
+ iConsumeView.showReverseFail(msg.obj as CardUserInfoBean)
+ }
+ PublicDef.MSG_CARD_REVERSE_SUC -> iConsumeView.showReverseSuc(msg.obj as CardUserInfoBean)
+ PublicDef.MSG_USER_INFO_SHOW -> iConsumeView.showUserInfo(msg.obj as CardUserInfoBean)
+ PublicDef.MSG_USER_INFO_CLEAR -> iConsumeView.clearUserInfo(msg.obj as String)
+ PublicDef.MSG_LINK_STATUS -> iConsumeView.refreshLinkStatus(msg.obj as Boolean)
+ }
+ }
+ }
+ }
+
+ fun start() {
+ cardPayService.start()
+ }
+
+ fun stop() {
+ cardPayService.stop()
+ }
+
+ fun clickNoPay() {
+ cardPayService.clickNoPay()
+ }
+
+ fun clickToPay(amount: Int) {
+ cardPayService.clickToPay(amount)
+ }
+
+ fun clickToReverse(amount: Int) {
+ cardPayService.clickToReverse(amount)
+ }
+
+ fun codeToPay(code: String, amount: Int) {
+ this.code = code
+ this.amount = amount
+ ThreadPool.getShortPool().execute(codePayRunnable)
+ }
+
+ fun interruptCodePay() {
+ code = null
+ amount = 0
+ /**
+ *不能暴力取消工作线程,可能存在后台已消费而本地未收到答复
+ */
+// ThreadPool.getShortPool().cancel(scanRunnable)
+ codePayService.interruptPay()
+ }
+
+ private inner class CodePayRunnable : Runnable {
+ override fun run() {
+ codePayService.pay(code!!, amount)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/consume/IConsumeView.kt b/app/src/main/java/com/supwisdom/activities/consume/IConsumeView.kt
new file mode 100644
index 0000000..b633d51
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/consume/IConsumeView.kt
@@ -0,0 +1,35 @@
+package com.supwisdom.activities.consume
+
+import android.app.Activity
+import com.supwisdom.activities.consume.bean.CardUserInfoBean
+import com.supwisdom.entity.TransdtlUnionRecord
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+interface IConsumeView {
+ fun getActivity(): Activity
+
+ fun isBackRuning(): Boolean
+
+ fun showConsumeSuc(info: CardUserInfoBean)
+
+ fun showConsumeHint(hint: String)
+
+ fun showConsumeFail(info: CardUserInfoBean)
+
+ fun showReverseSuc(info: CardUserInfoBean)
+
+ fun showReverseFail(info: CardUserInfoBean)
+
+ fun showUserInfo(info: CardUserInfoBean)
+
+ fun clearUserInfo(datetime: String)
+
+ fun refreshLinkStatus(isOnline: Boolean)
+
+ fun showRecentDtl(record: TransdtlUnionRecord?)
+
+ fun codeScannerEnable(enable: Boolean)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/consume/bean/CardAccountRetBean.kt b/app/src/main/java/com/supwisdom/activities/consume/bean/CardAccountRetBean.kt
new file mode 100644
index 0000000..461c16d
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/consume/bean/CardAccountRetBean.kt
@@ -0,0 +1,14 @@
+package com.supwisdom.activities.consume.bean
+
+import com.supwisdom.bean.BaseResp
+
+/**
+ ** create by zzq on 2019/7/26
+ ** @desc
+ **/
+class CardAccountRetBean : BaseResp() {
+ var username: String? = null
+ var userid: Int = 0
+ var balance: Int = 0
+ var status: String? = null
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/consume/bean/CardBean.kt b/app/src/main/java/com/supwisdom/activities/consume/bean/CardBean.kt
new file mode 100644
index 0000000..f68486f
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/consume/bean/CardBean.kt
@@ -0,0 +1,18 @@
+package com.supwisdom.activities.consume.bean
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class CardBean {
+ var cardphyid: String? = null
+ var cardNo: String? = null
+ var idCard: String? = null
+ var expireDate: String? = null
+ var datetime: String? = null
+ var amount: Int = 0
+ var username: String? = null
+ var userid: Int = 0
+ var balance: Int? = null
+ var cardstatus: Int = 0
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/consume/bean/CardPayConfirmRetBean.kt b/app/src/main/java/com/supwisdom/activities/consume/bean/CardPayConfirmRetBean.kt
new file mode 100644
index 0000000..c879a8a
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/consume/bean/CardPayConfirmRetBean.kt
@@ -0,0 +1,16 @@
+package com.supwisdom.activities.consume.bean
+
+import com.supwisdom.bean.BaseResp
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class CardPayConfirmRetBean : BaseResp() {
+ var amount: Int = 0
+ var extraamt: Int = 0
+ var balance: Int? = null
+ var require_query: Boolean = false
+// var username: String? = null
+// var userid: Int = 0
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/consume/bean/CardPayInitRetBean.kt b/app/src/main/java/com/supwisdom/activities/consume/bean/CardPayInitRetBean.kt
new file mode 100644
index 0000000..2b50e3f
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/consume/bean/CardPayInitRetBean.kt
@@ -0,0 +1,16 @@
+package com.supwisdom.activities.consume.bean
+
+import com.supwisdom.bean.BaseResp
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class CardPayInitRetBean : BaseResp() {
+ var billno: String? = null
+ var username: String? = null
+ var userid: String? = null
+ var anonymous: Boolean = false
+ var sourcetype: String? = null
+ var needpwdconfirm: Boolean = false
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/consume/bean/CardUserInfoBean.kt b/app/src/main/java/com/supwisdom/activities/consume/bean/CardUserInfoBean.kt
new file mode 100644
index 0000000..ebaf647
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/consume/bean/CardUserInfoBean.kt
@@ -0,0 +1,22 @@
+package com.supwisdom.activities.consume.bean
+
+import com.supwisdom.bean.BaseResp
+import com.supwisdom.entity.PayStatus
+import com.supwisdom.entity.ReversalFlag
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class CardUserInfoBean constructor(retcode: Int, retmsg: String) : BaseResp(retcode, retmsg) {
+ var username: String? = null
+ var showtime: Int = 3
+ var balance: Int? = null
+ var cardstatus: Int = 0
+ var amount: Int = 0
+ var payamt: Int = 0
+ var status: PayStatus? = null
+ var reversalFlag: ReversalFlag? = null
+ var datetime: String? = null
+ var payway: String? = null //card,code
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/consume/mode/CardPayService.kt b/app/src/main/java/com/supwisdom/activities/consume/mode/CardPayService.kt
new file mode 100644
index 0000000..3972fe6
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/consume/mode/CardPayService.kt
@@ -0,0 +1,415 @@
+package com.supwisdom.activities.consume.mode
+
+import android.os.Handler
+import android.os.Message
+import com.supwisdom.activities.SPApplication
+import com.supwisdom.activities.consume.IConsumeView
+import com.supwisdom.activities.consume.bean.*
+import com.supwisdom.entity.PayStatus
+import com.supwisdom.entity.ReversalFlag
+import com.supwisdom.entity.TransdtlOfflineRecord
+import com.supwisdom.entity.TransdtlOnlineRecord
+import com.supwisdom.epaycard.Cardlib
+import com.supwisdom.exception.CardNotFoundError
+import com.supwisdom.exception.CardPayCancelFailError
+import com.supwisdom.exception.CardPayFailError
+import com.supwisdom.okhttp.TransResp
+import com.supwisdom.utils.CommonUtil
+import com.supwisdom.utils.DateUtil
+import com.supwisdom.utils.GsonUtil
+import com.supwisdom.utils.PublicDef
+import org.apache.http.HttpStatus
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc 刷卡消费
+ **/
+class CardPayService constructor(iConsumeView: IConsumeView, handler: Handler) {
+ private val TAG = "CardPayService"
+ private val iConsumeView = iConsumeView
+ private val handler = handler
+ private val pos = SPApplication.getInstance().getPos()
+ private val runnable = CardPayRunnable()
+ private val consumeApi = ConsumeApi()
+ @Volatile
+ private var isExist = false
+ @Volatile
+ private var clickStat = ClickStat.INIT
+ @Volatile
+ private var amount: Int = 0
+ private var thread: Thread? = null
+ private lateinit var cardBean: CardBean
+
+ fun start() {
+ isExist = false
+ if (thread == null) {
+ thread = Thread(runnable)
+ thread!!.start()
+ }
+ }
+
+ fun stop() {
+ isExist = true
+ thread?.interrupt()
+ thread = null
+ }
+
+ fun clickNoPay() {
+ clickStat = ClickStat.INIT
+ amount = 0
+ }
+
+ fun clickToPay(amount: Int) {
+ clickStat = ClickStat.PAY
+ this.amount = amount
+ }
+
+ fun clickToReverse(amount: Int) {
+ clickStat = ClickStat.REVERSE
+ this.amount = amount
+ }
+
+ private inner class CardPayRunnable : Runnable {
+ private lateinit var onlRecord: TransdtlOnlineRecord
+ private lateinit var offRecord: TransdtlOfflineRecord
+ private var oldcardphyid: String? = null
+ private var onlineBalance = false
+ private var curLinkStatus = false
+ private var lastShowTime: Long = 0
+ private var lastUserInfoTime: Long = 0
+ private var curLinkRefreshTime: Long = 0
+ override fun run() {
+ while (!isExist) {
+ if (iConsumeView.isBackRuning()) {
+ CommonUtil.doSleep(1000)
+ doClear()
+ continue
+ }
+ iConsumeView.codeScannerEnable(true)
+ CommonUtil.doSleep(100)
+ try {
+ val cardphyid = Cardlib.instance.requestCard()
+ iConsumeView.codeScannerEnable(false)
+ if (oldcardphyid != cardphyid) {
+ readCard()
+ cardBean.cardphyid = cardphyid
+ oldcardphyid = cardphyid
+ }
+ when (clickStat) {
+ ClickStat.PAY -> {
+ try {
+ doConsume()
+ } catch (ex: CardPayFailError) {
+ sendMsg(PublicDef.MSG_CARD_PAY_FAIL, getErrorInfo(ex.message))
+ }
+ clickStat = ClickStat.INIT
+ }
+ ClickStat.REVERSE -> {
+ try {
+ doReverse()
+ } catch (ex: CardPayCancelFailError) {
+ sendMsg(PublicDef.MSG_CARD_REVERSE_FAIL, getErrorInfo(ex.message))
+ }
+ clickStat = ClickStat.INIT
+ }
+ ClickStat.INIT -> {
+ if (SPApplication.getInstance().isOnline() && !onlineBalance) {
+ onlineBalance = true
+ getAccountInfoByCard()
+ }
+ val curtime = System.currentTimeMillis()
+ if (curtime < lastUserInfoTime ||
+ curtime - lastUserInfoTime > 1000
+ ) {
+ lastUserInfoTime = curtime
+ showCardUserInfo()
+ }
+ }
+ }
+ } catch (ex: CardNotFoundError) {
+ ex.printStackTrace()
+ doClear()
+ } catch (ex: Exception) {
+ ex.printStackTrace()
+ doClear()
+ }
+ }
+ }
+
+ private fun getAccountInfoByCard() {
+ val resp = consumeApi.accQuery(
+ pos.getConfigPara()!!.devphyid!!,
+ cardBean.cardphyid!!,
+ cardBean.cardNo!!
+ )
+ if (resp != null && resp.retcode == HttpStatus.SC_OK) {
+ val retBean = GsonUtil.GsonToBean(resp.retjson!!, CardAccountRetBean::class.java)
+ if (retBean.retcode == PublicDef.SUCCESS) {
+ cardBean.username = retBean.username
+ cardBean.userid = retBean.userid
+ cardBean.balance = retBean.balance
+ cardBean.cardstatus = 1 //TODO
+ }
+ }
+ }
+
+ private fun showCardUserInfo() {
+ val info = CardUserInfoBean(PublicDef.SUCCESS, "账户信息")
+ info.username = cardBean.username
+ info.balance = cardBean.balance
+ info.cardstatus = cardBean.cardstatus
+ sendMsg(PublicDef.MSG_USER_INFO_SHOW, info)
+ }
+
+ private fun readCard() {
+ val cardinfo = Cardlib.instance.readCard()
+ cardBean = CardBean()
+ cardBean.cardNo = cardinfo.cardNo
+ cardBean.idCard = cardinfo.idCard
+ cardBean.expireDate = cardinfo.expireDate
+ cardBean.amount = amount
+ cardBean.datetime = DateUtil.getNowDateTimeFormat()
+ /**
+ * 用户名默认用卡号代替,在线查询更新为用户名
+ */
+ cardBean.username = cardBean.cardNo
+ }
+
+ private fun doConsume() {
+ sendMsg(PublicDef.MSG_CARD_PAYING, "正在扣款...")
+ if (SPApplication.getInstance().isOnline()) {
+ if (!doOnlineConsume()) {
+ /**
+ * 由于不写卡,联机消费失败直接转离线
+ */
+ doOfflineConsume()
+ }
+ } else {
+ doOfflineConsume()
+ }
+ }
+
+ private fun doReverse() {
+ throw CardPayCancelFailError("暂不支持")
+ }
+
+ private fun doOnlineConsume(): Boolean {
+ initTransdtlOnline()
+ var resp = consumeApi.payInit(onlRecord)
+ var result = parseInitResult(resp)
+ if (!result) {
+ return result
+ }
+ resp = consumeApi.payConfirm(onlRecord)
+ result = parseConfirmResult(resp)
+ if (result) {
+ showSucInfo()
+ }
+ updateTransdtlOnline(result)
+ return result
+ }
+
+ private fun parseInitResult(resp: TransResp?): Boolean {
+ if (resp == null || resp.retcode != HttpStatus.SC_OK) {
+ SPApplication.getInstance().setEpayLinking(false)
+ return false
+ }
+ val retBean = GsonUtil.GsonToBean(resp.retjson!!, CardPayInitRetBean::class.java)
+ if (retBean.retcode != PublicDef.SUCCESS) {
+ throw CardPayFailError(retBean.retmsg!!)
+ }
+ onlRecord.billno = retBean.billno
+ onlRecord.username = retBean.username
+// onlRecord.userid = retBean.userid
+ return true
+ }
+
+ private fun parseConfirmResult(resp: TransResp?): Boolean {
+ if (resp == null || resp.retcode != HttpStatus.SC_OK) {
+ SPApplication.getInstance().setEpayLinking(false)
+ return false
+ }
+ val retBean = GsonUtil.GsonToBean(resp.retjson!!, CardPayConfirmRetBean::class.java)
+ if (retBean.retcode != PublicDef.SUCCESS) {
+ throw CardPayFailError(retBean.retmsg!!)
+ }
+ if (retBean.require_query) {
+ //TODO
+ throw CardPayFailError("查询未实现")
+ }
+ onlRecord.payamt = retBean.amount
+ onlRecord.extraamt = retBean.extraamt
+ onlRecord.balance = retBean.balance
+ return true
+ }
+
+ private fun initTransdtlOnline() {
+ onlRecord = TransdtlOnlineRecord()
+ var seqno = pos.getTransdtlOnlineMaxSeqno()
+ if (seqno == 0) {
+ seqno = pos.getDynamicPara()?.onlineseqno ?: 0
+ }
+ onlRecord.devphyid = pos.getConfigPara()!!.devphyid
+ onlRecord.transdate = cardBean.datetime!!.substring(0, 8)
+ onlRecord.transtime = cardBean.datetime!!.substring(8)
+ onlRecord.devseqno = seqno + 1
+ onlRecord.cardno = cardBean.cardNo
+ onlRecord.cardphyid = cardBean.cardphyid
+ onlRecord.payamt = cardBean.amount
+ onlRecord.reversalflag = ReversalFlag.NONE
+ onlRecord.extraamt = 0
+ onlRecord.transtype = "card"
+ onlRecord.status = PayStatus.INIT
+ onlRecord.upflag = 1
+ if (!pos.saveTransdtlOnline(onlRecord)) {
+ throw CardPayFailError("保存流水失败")
+ }
+ }
+
+ private fun updateTransdtlOnline(issuccess: Boolean) {
+ if (issuccess) {
+ onlRecord.status = PayStatus.SUC
+ } else {
+ onlRecord.status = PayStatus.FAIL
+ }
+ onlRecord.upflag = 1
+ pos.updateTransdtlOnline(onlRecord)
+ }
+
+ private fun doOfflineConsume() {
+ initTransdtlOffline()
+ checkCardValid()
+ updateTransdtlOffline(true)
+ }
+
+ private fun checkCardValid() {
+ val sysRecord = pos.getSysPara()
+ if (!sysRecord!!.offlineEnable) {
+ throw CardPayFailError("禁止离线交易")
+ }
+ val ctlRecord = pos.getControlPara(PublicDef.CONTROL_OFFLINE_DAY_DISABLE)
+ if (ctlRecord == null || ctlRecord.paraval != "1") {
+ val offdate = DateUtil.getDayDateNoFormatBefore(sysRecord.maxOfflineDays)
+ val validdate = pos.getDynamicPara()!!.jwtExpire?.substring(0, 8) ?: "00000000"
+ if (offdate > validdate) {
+ throw CardPayFailError("设备已脱机${sysRecord.maxOfflineDays}天")
+ }
+ }
+
+ val whiteRecord =
+ pos.getWhiteList(offRecord.cardphyid!!, offRecord.cardno!!) ?: throw CardPayFailError("卡无权限")
+ if (whiteRecord.flag == 1) {
+ throw CardPayFailError("卡已锁定")
+ }
+ if (whiteRecord.balance < offRecord.payamt) {
+ throw CardPayFailError("请到联机设备使用")
+ }
+ }
+
+ private fun initTransdtlOffline() {
+ offRecord = TransdtlOfflineRecord()
+ var seqno = pos.getTransdtlOfflineMaxSeqno()
+ if (seqno == 0) {
+ seqno = pos.getDynamicPara()?.offlineseqno ?: 0
+ }
+ offRecord.devphyid = pos.getConfigPara()!!.devphyid
+ offRecord.transdate = cardBean.datetime!!.substring(0, 8)
+ offRecord.transtime = cardBean.datetime!!.substring(8)
+ offRecord.devseqno = seqno + 1
+ offRecord.cardno = cardBean.cardNo
+ offRecord.cardphyid = cardBean.cardphyid
+ offRecord.payamt = cardBean.amount
+ offRecord.reversalflag = ReversalFlag.NONE
+ offRecord.extraamt = 0
+ offRecord.managefeetype = "none"
+ offRecord.status = PayStatus.INIT
+ offRecord.upflag = 1
+ if (!pos.saveTransdtlOffline(offRecord)) {
+ throw CardPayFailError("保存流水失败")
+ }
+ }
+
+ private fun updateTransdtlOffline(issuccess: Boolean) {
+ if (issuccess) {
+ offRecord.status = PayStatus.SUC
+ } else {
+ offRecord.status = PayStatus.FAIL
+ }
+ offRecord.upflag = 0
+ if (!pos.updateTransdtlOffline(offRecord)) {
+ throw CardPayFailError("更新流水失败")
+ }
+ }
+
+ private fun doClear() {
+ oldcardphyid = null
+ onlineBalance = false
+ val curtime = System.currentTimeMillis()
+ if (curtime < lastShowTime ||
+ curtime - lastShowTime > 1000
+ ) {
+ lastShowTime = curtime
+ sendMsg(PublicDef.MSG_USER_INFO_CLEAR, DateUtil.getNowDateTime())
+ showLinkStatus()
+ }
+ }
+
+ private fun showLinkStatus() {
+ if (SPApplication.getInstance().isOnline()) {
+ if (!curLinkStatus) {
+ curLinkRefreshTime = System.currentTimeMillis()
+ curLinkStatus = true
+ sendMsg(PublicDef.MSG_LINK_STATUS, true)
+ return
+ }
+ } else {
+ if (curLinkStatus) {
+ curLinkStatus = false
+ curLinkRefreshTime = System.currentTimeMillis()
+ sendMsg(PublicDef.MSG_LINK_STATUS, false)
+ return
+ }
+ }
+ val t = System.currentTimeMillis()
+ if (t < curLinkRefreshTime ||
+ t - curLinkRefreshTime > 30000
+ ) {
+ curLinkRefreshTime = t
+ sendMsg(PublicDef.MSG_LINK_STATUS, SPApplication.getInstance().isOnline())
+ }
+ }
+
+ private fun showSucInfo() {
+ val info = CardUserInfoBean(PublicDef.SUCCESS, "消费成功")
+ info.showtime = pos.getSysPara()!!.sucShowtime
+ info.amount = onlRecord.payamt
+ info.payamt = onlRecord.payamt
+ info.username = onlRecord.username
+ info.datetime = onlRecord.transdate + onlRecord.transtime
+ info.payway = onlRecord.transtype
+ info.status = PayStatus.SUC
+ info.balance = onlRecord.balance
+ sendMsg(PublicDef.MSG_CARD_PAY_SUC, info)
+ }
+
+ private fun getErrorInfo(errmsg: String?): CardUserInfoBean {
+ val info = CardUserInfoBean(PublicDef.ERROR, errmsg ?: "null")
+ info.showtime = pos.getSysPara()!!.failShowtime
+ info.status = PayStatus.FAIL
+ return info
+ }
+
+ private fun sendMsg(code: Int, obj: Any) {
+ val msg = Message()
+ msg.what = code
+ msg.obj = obj
+ handler.sendMessage(msg)
+ }
+ }
+}
+
+enum class ClickStat {
+ INIT,
+ PAY,
+ REVERSE
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/consume/mode/CodePayService.kt b/app/src/main/java/com/supwisdom/activities/consume/mode/CodePayService.kt
new file mode 100644
index 0000000..f69e698
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/consume/mode/CodePayService.kt
@@ -0,0 +1,195 @@
+package com.supwisdom.activities.consume.mode
+
+import android.os.Handler
+import android.os.Message
+import com.supwisdom.activities.SPApplication
+import com.supwisdom.activities.consume.IConsumeView
+import com.supwisdom.activities.consume.bean.CardPayConfirmRetBean
+import com.supwisdom.activities.consume.bean.CardPayInitRetBean
+import com.supwisdom.activities.consume.bean.CardUserInfoBean
+import com.supwisdom.entity.PayStatus
+import com.supwisdom.entity.ReversalFlag
+import com.supwisdom.entity.TransdtlOnlineRecord
+import com.supwisdom.exception.CardPayFailError
+import com.supwisdom.okhttp.TransResp
+import com.supwisdom.utils.*
+import org.apache.http.HttpStatus
+
+/**
+ ** create by zzq on 2019/7/30
+ ** @desc 二维码消费
+ **/
+class CodePayService constructor(iConsumeView: IConsumeView, handler: Handler) {
+ private val TAG = "CodePayService"
+ private val iConsumeView = iConsumeView
+ private val handler = handler
+ private val pos = SPApplication.getInstance().getPos()
+ private lateinit var codeRecord: TransdtlOnlineRecord
+ private val consumeApi = ConsumeApi()
+ /**
+ * 消费过程中可按键主动取消
+ * 手动取消后不冲正,以手机消费结果为准
+ */
+ @Volatile
+ private var interruptedPay: Boolean = false
+
+ fun interruptPay() {
+ interruptedPay = true
+ }
+
+ fun pay(code: String, amount: Int) {
+ interruptedPay = false
+ try {
+ initTransdtlOnline(code, amount)
+ var resp = consumeApi.payInit(codeRecord)
+ parseInitResult(resp)
+ resp = consumeApi.payConfirm(codeRecord)
+ var result = parseConfirmResult(resp)
+ if (!result) {
+ result = payResultQuery()
+ }
+ if (result) {
+ showSucInfo()
+ }
+ updateTransdtlOnline(result)
+ } catch (ex: CardPayFailError) {
+ sendMsg(PublicDef.MSG_CARD_PAY_FAIL, getErrorInfo(ex.message))
+ }
+ }
+
+ private fun payResultQuery(): Boolean {
+ sendMsg(PublicDef.MSG_CODE_PAYING_CANCEL, "谨慎操作查询取消")
+ LogUtil.d(TAG, "扫码消费确认超时,进行查询操作:billno=${codeRecord.billno}")
+ sleepWithCancel(1500)
+ var searchCnt = 1
+ while (!interruptedPay) {
+ sendMsg(PublicDef.MSG_CARD_PAYING, String.format("正在%d次查询...", searchCnt))
+ val resp = consumeApi.payQuery(codeRecord)
+ if (resp != null) {
+ val result = parseConfirmResult(resp)
+ if (!result) {
+ searchCnt++
+ sendMsg(PublicDef.MSG_CARD_PAYING, String.format("等待%d次查询...", searchCnt))
+ sleepWithCancel(5000)
+ continue
+ }
+ return result
+ } else {
+ searchCnt++
+ sendMsg(PublicDef.MSG_CARD_PAYING, String.format("等待%d次查询...", searchCnt))
+ sleepWithCancel(3000)
+ }
+ }
+ LogUtil.d(TAG, "扫码消费确认超时,操作员手工取消查询:billno=${codeRecord.billno}")
+ return false
+ }
+
+ private fun parseConfirmResult(resp: TransResp?): Boolean {
+ if (resp == null) {
+ SPApplication.getInstance().setEpayLinking(false)
+ return false
+ }
+ if (resp.retcode != HttpStatus.SC_OK) {
+ throw CardPayFailError("错误码=${resp.retcode}")
+ }
+ val retBean = GsonUtil.GsonToBean(resp.retjson!!, CardPayConfirmRetBean::class.java)
+ if (retBean.retcode != PublicDef.SUCCESS) {
+ throw CardPayFailError(retBean.retmsg!!)
+ }
+ if (retBean.require_query) {
+ // 等待查询
+ return false
+ }
+ codeRecord.payamt = retBean.amount
+ codeRecord.extraamt = retBean.extraamt
+ codeRecord.balance = retBean.balance
+ return true
+ }
+
+ private fun parseInitResult(resp: TransResp?): Boolean {
+ if (resp == null) {
+ SPApplication.getInstance().setEpayLinking(false)
+ throw CardPayFailError("请求超时")
+ }
+ if (resp.retcode != HttpStatus.SC_OK) {
+ throw CardPayFailError("错误码=${resp.retcode}")
+ }
+ val retBean = GsonUtil.GsonToBean(resp.retjson!!, CardPayInitRetBean::class.java)
+ if (retBean.retcode != PublicDef.SUCCESS) {
+ throw CardPayFailError(retBean.retmsg!!)
+ }
+ codeRecord.billno = retBean.billno
+ codeRecord.username = retBean.username
+ return true
+ }
+
+ private fun initTransdtlOnline(code: String, amount: Int) {
+ codeRecord = TransdtlOnlineRecord()
+ var seqno = pos.getTransdtlOnlineMaxSeqno()
+ if (seqno == 0) {
+ seqno = pos.getDynamicPara()?.onlineseqno ?: 0
+ }
+ codeRecord.devphyid = pos.getConfigPara()!!.devphyid
+ codeRecord.transdate = DateUtil.getNowDateNoFormat()
+ codeRecord.transtime = DateUtil.getNowTimeNoFormat()
+ codeRecord.devseqno = seqno + 1
+ codeRecord.qrcode = code
+ codeRecord.payamt = amount
+ codeRecord.reversalflag = ReversalFlag.NONE
+ codeRecord.extraamt = 0
+ codeRecord.transtype = "code"
+ codeRecord.status = PayStatus.INIT
+ codeRecord.upflag = 1
+ if (!pos.saveTransdtlOnline(codeRecord)) {
+ throw CardPayFailError("保存流水失败")
+ }
+ }
+
+ private fun updateTransdtlOnline(issuccess: Boolean) {
+ if (issuccess) {
+ codeRecord.status = PayStatus.SUC
+ } else {
+ codeRecord.status = PayStatus.FAIL
+ }
+ codeRecord.upflag = 1
+ pos.updateTransdtlOnline(codeRecord)
+ }
+
+ private fun sleepWithCancel(ms: Long) {
+ var sum: Long = 0
+ while (!interruptedPay) {
+ CommonUtil.doSleep(100)
+ sum += 100
+ if (sum > ms) {
+ break
+ }
+ }
+ }
+
+ private fun showSucInfo() {
+ val info = CardUserInfoBean(PublicDef.SUCCESS, "消费成功")
+ info.showtime = pos.getSysPara()!!.sucShowtime
+ info.amount = codeRecord.payamt
+ info.payamt = codeRecord.payamt
+ info.username = codeRecord.username
+ info.datetime = codeRecord.transdate + codeRecord.transtime
+ info.payway = codeRecord.transtype
+ info.status = PayStatus.SUC
+ info.balance = codeRecord.balance
+ sendMsg(PublicDef.MSG_CARD_PAY_SUC, info)
+ }
+
+ private fun getErrorInfo(errmsg: String?): CardUserInfoBean {
+ val info = CardUserInfoBean(PublicDef.ERROR, errmsg ?: "null")
+ info.showtime = pos.getSysPara()!!.failShowtime
+ info.status = PayStatus.FAIL
+ return info
+ }
+
+ private fun sendMsg(code: Int, obj: Any) {
+ val msg = Message()
+ msg.what = code
+ msg.obj = obj
+ handler.sendMessage(msg)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/consume/mode/ConsumeApi.kt b/app/src/main/java/com/supwisdom/activities/consume/mode/ConsumeApi.kt
new file mode 100644
index 0000000..54e6a8a
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/consume/mode/ConsumeApi.kt
@@ -0,0 +1,69 @@
+package com.supwisdom.activities.consume.mode
+
+import com.supwisdom.activities.YktSession
+import com.supwisdom.entity.TransdtlOnlineRecord
+import com.supwisdom.okhttp.TransResp
+import com.supwisdom.okhttp.WebParams
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+class ConsumeApi {
+ fun payInit(record: TransdtlOnlineRecord): TransResp? {
+// val feetype = when {
+// record.transflag and 0x60 == 0x40 -> "mealer"
+// record.transflag and 0x60 == 0x20 -> "discount"
+// else -> "none"
+// }
+ val params = WebParams()
+ params.setParameter("cardno", record.cardno)
+ .setParameter("cardphyid", record.cardphyid)
+ .setParameter("qrcode", record.qrcode)
+ .setParameter("devphyid", record.devphyid)
+ .setParameter("termseqno", record.devseqno)
+ .setParameter("termdate", record.transdate)
+ .setParameter("termtime", record.transtime)
+ .setParameter("transtype", record.transtype)
+
+ return YktSession.getInstance().sendYktRequestPost("/api/pos/payinit", "", params)
+ }
+
+ fun payConfirm(record: TransdtlOnlineRecord): TransResp? {
+ val params = WebParams()
+ params.setParameter("devphyid", record.devphyid)
+ .setParameter("billno", record.billno)
+ .setParameter("amount", record.payamt)
+ .setParameter("termdate", record.transdate)
+ .setParameter("termtime", record.transtime)
+
+ return YktSession.getInstance().sendYktRequestPost("/api/pos/payconfirm", "", params)
+ }
+
+ fun payQuery(record: TransdtlOnlineRecord): TransResp? {
+ val params = WebParams()
+ params.setParameter("devphyid", record.devphyid)
+ .setParameter("billno", record.billno)
+ .setParameter("termdate", record.transdate)
+ .setParameter("termtime", record.transtime)
+
+ return YktSession.getInstance().sendYktRequestPost("/api/pos/payquery", "", params)
+ }
+
+ fun accQuery(devphyid: String, cardphyid: String, cardno: String): TransResp? {
+ val params = WebParams()
+ params.setParameter("devphyid", devphyid)
+ .setParameter("cardphyid", cardphyid)
+ .setParameter("cardno", cardno)
+
+ return YktSession.getInstance().sendYktRequestPost("/api/pos/accquery", "", params)
+ }
+
+ fun queryRevenue(devphyid: String, date: String): TransResp? {
+ val params = WebParams()
+ params.setParameter("devphyid", devphyid)
+ .setParameter("termdate", date)
+
+ return YktSession.getInstance().sendYktRequestPost("/api/pos/querysales", "", params)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/consumeMode/ConsumeModeActivity.kt b/app/src/main/java/com/supwisdom/activities/consumeMode/ConsumeModeActivity.kt
new file mode 100644
index 0000000..d7f5e32
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/consumeMode/ConsumeModeActivity.kt
@@ -0,0 +1,237 @@
+package com.supwisdom.activities.consumeMode
+
+import android.annotation.SuppressLint
+import android.os.Bundle
+import android.os.CountDownTimer
+import android.view.KeyEvent
+import android.widget.TextView
+import com.supwisdom.R
+import com.supwisdom.activities.BaseActivity
+import com.supwisdom.activities.SPApplication
+import com.supwisdom.activities.menu.MenuActivity
+import com.supwisdom.auxscreen.AuxScreenController
+import com.supwisdom.utils.CommonUtil
+import com.supwisdom.utils.DateUtil
+import com.supwisdom.utils.PublicDef
+import java.util.*
+
+/**
+ ** create by zzq on 2019/7/26
+ ** @desc
+ **/
+class ConsumeModeActivity : BaseActivity() {
+ private lateinit var vPayamt: TextView
+ private val pos = SPApplication.getInstance().getPos()
+ private var keyActive = true
+ private var shoppwdPass = false
+ private var tmpPwd = ""
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ this.setContentView(R.layout.activity_consume_mode)
+ initView()
+ }
+
+ private fun initView() {
+ vPayamt = findViewById<TextView>(R.id.tv_consume_mode_payamt)
+ }
+
+ private fun checkShopPwd(keyCode: Int) {
+ when (keyCode) {
+ KeyEvent.KEYCODE_0,
+ KeyEvent.KEYCODE_1,
+ KeyEvent.KEYCODE_2,
+ KeyEvent.KEYCODE_3,
+ KeyEvent.KEYCODE_4,
+ KeyEvent.KEYCODE_5,
+ KeyEvent.KEYCODE_6,
+ KeyEvent.KEYCODE_7,
+ KeyEvent.KEYCODE_8,
+ KeyEvent.KEYCODE_9 -> {
+ tmpPwd += keyCode - KeyEvent.KEYCODE_0
+ if (tmpPwd.length >= 6) {
+ if (checkShoPwdValid(tmpPwd)) {
+ shoppwdPass = true
+ refreshToSetAmount()
+ } else {
+ AuxScreenController.getInstance().refreshContent(Arrays.asList<String>("请输入商户密码:", "密码错误"))
+ }
+ tmpPwd = ""
+ } else {
+ AuxScreenController.getInstance()
+ .refreshContent(Arrays.asList("请输入商户密码:", CommonUtil.getPasswordStar(tmpPwd.length)))
+ }
+ }
+ KeyEvent.KEYCODE_DEL -> {
+ //cancel
+ val len = tmpPwd.length
+ when {
+ len == 1 -> {
+ tmpPwd = ""
+ AuxScreenController.getInstance()
+ .refreshContent(Arrays.asList("请输入商户密码:", CommonUtil.getPasswordStar(tmpPwd.length)))
+ }
+ len > 1 -> {
+ tmpPwd = tmpPwd.substring(0, len - 1)
+ AuxScreenController.getInstance()
+ .refreshContent(Arrays.asList("请输入商户密码:", CommonUtil.getPasswordStar(tmpPwd.length)))
+ }
+ else -> finish()
+ }
+ }
+ }
+ }
+
+ private fun checkShoPwdValid(inputPwd: String): Boolean {
+ return inputPwd == pos.getConfigPara()!!.shopPwd
+ }
+
+ private fun setFixAmount(keyCode: Int) {
+ when (keyCode) {
+ KeyEvent.KEYCODE_0,
+ KeyEvent.KEYCODE_1,
+ KeyEvent.KEYCODE_2,
+ KeyEvent.KEYCODE_3,
+ KeyEvent.KEYCODE_4,
+ KeyEvent.KEYCODE_5,
+ KeyEvent.KEYCODE_6,
+ KeyEvent.KEYCODE_7,
+ KeyEvent.KEYCODE_8,
+ KeyEvent.KEYCODE_9 -> addValueToEdit(keyCode - KeyEvent.KEYCODE_0)
+ KeyEvent.KEYCODE_DEL ->
+ //cancel
+ delValueToEdit()
+ KeyEvent.KEYCODE_POUND, KeyEvent.KEYCODE_PERIOD -> {
+ val str = vPayamt.text.toString()
+ if (str.length < 8 && str.indexOf('.') < 0) {
+ vPayamt.text = "$str."
+ screenShowAmt()
+ }
+ }
+ KeyEvent.KEYCODE_ENTER -> {
+ pos.replaceControlPara(PublicDef.CONTROL_FIXAMT, getFixAmount())
+ jumpActivity(MenuActivity::class.java)
+ }
+ }
+ }
+
+ @SuppressLint("SetTextI18n")
+ override fun dispatchKeyEvent(event: KeyEvent): Boolean {
+ if (event.action == KeyEvent.ACTION_DOWN) {
+ if (!keyActive) {
+ return super.dispatchKeyEvent(event)
+ }
+ resetCounter(200)
+ if (shoppwdPass) {
+ setFixAmount(event.keyCode)
+ } else {
+ checkShopPwd(event.keyCode)
+ }
+ }
+ return super.dispatchKeyEvent(event)
+ }
+
+ override fun onResume() {
+ super.onResume()
+ shoppwdPass = false
+ keyActive = true
+ refreshToCheckPasswd()
+ }
+
+ private fun refreshToCheckPasswd() {
+ AuxScreenController.getInstance().refreshTitle("消费模式设置")
+ AuxScreenController.getInstance().refreshBottom(DateUtil.getNowDateTime())
+ AuxScreenController.getInstance().refreshContent(Arrays.asList<String>("请输入商户密码:", " "))
+ }
+
+ private fun refreshToSetAmount() {
+ val record = pos.getControlPara(PublicDef.CONTROL_FIXAMT)
+ if (record != null && PublicDef.CONTROL_NO_FIXPAY_FLAG != record.paraval) {
+ vPayamt.text = String.format("%.02f", Integer.parseInt(record.paraval) / 100.0f)
+ } else {
+ vPayamt.text = PublicDef.CONTROL_NO_FIXPAY_FLAG
+ }
+ screenShowAmt()
+ }
+
+ private fun getFixAmount(): String {
+ try {
+ return Integer.toString(CommonUtil.YuanToFen(java.lang.Double.parseDouble(vPayamt.text.toString())))
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+
+ return PublicDef.CONTROL_NO_FIXPAY_FLAG
+ }
+
+ private fun addValueToEdit(value: Int) {
+ var str = vPayamt.text.toString()
+ if ("0" == str || PublicDef.CONTROL_NO_FIXPAY_FLAG == str) {
+ str = ""
+ }
+ //如果已经有小数点,则小数点后面不能超过两位
+ if (str.indexOf(".") > 0) {
+ if (str.length - str.indexOf(".") <= 2) {
+ vPayamt.text = "$str$value"
+ } else {
+ vPayamt.text = value.toString()
+ }
+ } else {
+ //限制消费金额<1000
+ if (str.length < 3) {
+ vPayamt.text = "$str$value"
+ }
+ }
+ screenShowAmt()
+ }
+
+ private fun delValueToEdit() {
+ val str = vPayamt.text.toString()
+ if (PublicDef.CONTROL_NO_FIXPAY_FLAG != str) {
+ if (str.length <= 1) {
+ vPayamt.text = PublicDef.CONTROL_NO_FIXPAY_FLAG
+ } else {
+ vPayamt.text = str.substring(0, str.length - 1)
+ }
+ }
+ screenShowAmt()
+ }
+
+ private fun screenShowAmt() {
+ AuxScreenController.getInstance().refreshContent(
+ Arrays.asList<String>(
+ PublicDef.CONTROL_NO_FIXPAY_FLAG + "-普通消费",
+ "值-定额消费(元)",
+ String.format("金额:%s", vPayamt.text.toString())
+ )
+ )
+
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ }
+
+ private var counter: ContinuePressTimer? = null
+
+ private fun resetCounter(timems: Long) {
+ counter?.cancel()
+ if (counter == null) {
+ counter = ContinuePressTimer(timems, 100)
+ }
+ keyActive = false
+ counter!!.start()
+ }
+
+ private inner class ContinuePressTimer internal constructor(millisInFuture: Long, countDownInterval: Long) :
+ CountDownTimer(millisInFuture, countDownInterval) {
+
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ keyActive = true
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/control/ControlActivity.kt b/app/src/main/java/com/supwisdom/activities/control/ControlActivity.kt
new file mode 100644
index 0000000..0ab3436
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/control/ControlActivity.kt
@@ -0,0 +1,118 @@
+package com.supwisdom.activities.control
+
+import android.os.Bundle
+import android.view.KeyEvent
+import android.view.View
+import android.widget.RadioButton
+import android.widget.TextView
+import com.supwisdom.R
+import com.supwisdom.activities.BaseActivity
+import com.supwisdom.activities.SPApplication
+import com.supwisdom.auxscreen.AuxScreenController
+import com.supwisdom.entity.ControlParaRecord
+import com.supwisdom.utils.PublicDef
+import com.supwisdom.view.SWToast
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class ControlActivity : BaseActivity() {
+ private val pos = SPApplication.getInstance().getPos()
+ private lateinit var vDebugDisable: RadioButton
+ private lateinit var vDebugEnable: RadioButton
+ private lateinit var vOfflineEnable: RadioButton
+ private lateinit var vOfflineDisable: RadioButton
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_control)
+ initView()
+ }
+
+ private fun initData() {
+ var record = pos.getControlPara(PublicDef.CONTROL_OFFLINE_DAY_DISABLE)
+ if (record != null && "1" == record.paraval) {
+ vOfflineDisable.isChecked = true
+ } else {
+ vOfflineEnable.isChecked = true
+ }
+ record = pos.getControlPara(PublicDef.CONTROL_DEBUG_ENABLE)
+ if (record != null && "1" == record.paraval) {
+ vDebugEnable.isChecked = true
+ } else {
+ vDebugDisable.isChecked = true
+ }
+ }
+
+ private fun initView() {
+ vOfflineEnable = this.findViewById<View>(R.id.rb_offline_enable) as RadioButton
+ vOfflineDisable = this.findViewById<View>(R.id.rb_offline_disable) as RadioButton
+ vDebugDisable = this.findViewById<View>(R.id.rb_debug_enable) as RadioButton
+ vDebugEnable = this.findViewById<View>(R.id.rb_debug_disable) as RadioButton
+ val ivBtn = this.findViewById<View>(R.id.btn_cancel) as TextView
+ ivBtn.setOnClickListener { this@ControlActivity.finish() }
+ //确定按钮
+ this.findViewById<TextView>(R.id.btn_save).setOnClickListener {
+ var flag = if (vOfflineDisable.isChecked) {
+ "1"
+ } else {
+ "0"
+ }
+ if (!pos.replaceControlPara(PublicDef.CONTROL_OFFLINE_DAY_DISABLE, flag)) {
+ showSWToastInfo("脱机天数判断保存失败", PublicDef.TOAST_SHOW_CRY)
+ return@setOnClickListener
+ }
+
+ flag = if (vDebugEnable.isChecked) {
+ "1"
+ } else {
+ "0"
+ }
+ if (!pos.replaceControlPara(PublicDef.CONTROL_DEBUG_ENABLE, flag)) {
+ showSWToastInfo("日志调试保存失败", PublicDef.TOAST_SHOW_CRY)
+ return@setOnClickListener
+ }
+ showSWToastInfo("保存成功", PublicDef.TOAST_SHOW_SMILE)
+ this@ControlActivity.finish()
+ }
+
+ }
+
+ override fun dispatchKeyEvent(event: KeyEvent): Boolean {
+ if (event.action == KeyEvent.ACTION_DOWN) {
+ when (event.keyCode) {
+ KeyEvent.KEYCODE_DEL -> {
+ }
+ KeyEvent.KEYCODE_ENTER -> finish()
+ }//cancel
+ //和触屏删除键冲突
+ // finish();
+ }
+ return super.dispatchKeyEvent(event)
+ }
+
+ private fun showSWToastInfo(msg: String, showway: Int) {
+ SWToast.show(applicationContext, msg, showway)
+ }
+
+ override fun onResume() {
+ super.onResume()
+ refresh()
+ initData()
+ }
+
+ override fun onStop() {
+ super.onStop()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ }
+
+ private fun refresh() {
+ AuxScreenController.getInstance().refreshTitle("控制参数设置")
+ AuxScreenController.getInstance().refreshBottom("确定键返回上页")
+ AuxScreenController.getInstance().refreshContent(listOf<String>("请到大屏进行配置"))
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/init/IInitView.kt b/app/src/main/java/com/supwisdom/activities/init/IInitView.kt
new file mode 100644
index 0000000..1f989f0
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/init/IInitView.kt
@@ -0,0 +1,15 @@
+package com.supwisdom.activities.init
+
+import android.app.Activity
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+interface IInitView {
+ fun getActivity(): Activity
+
+ fun showSWToastInfo(msg: String, showway: Int)
+
+ fun jumpToNextActivity()
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/init/InitActivity.kt b/app/src/main/java/com/supwisdom/activities/init/InitActivity.kt
new file mode 100644
index 0000000..1d773f5
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/init/InitActivity.kt
@@ -0,0 +1,243 @@
+package com.supwisdom.activities.init
+
+import android.app.Activity
+import android.net.nsd.NsdServiceInfo
+import android.os.Bundle
+import android.support.v7.widget.LinearLayoutManager
+import android.support.v7.widget.RecyclerView
+import android.widget.Button
+import android.widget.EditText
+import android.widget.RadioButton
+import android.widget.TextView
+import com.supwisdom.R
+import com.supwisdom.activities.BaseActivity
+import com.supwisdom.activities.SPApplication
+import com.supwisdom.activities.init.adapter.NsdServerConfigAdapter
+import com.supwisdom.activities.init.mode.NsdClient
+import com.supwisdom.activities.init.mode.NsdClientApi
+import com.supwisdom.activities.load.LoadActivity
+import com.supwisdom.auxscreen.AuxScreenController
+import com.supwisdom.entity.ConfigParaRecord
+import com.supwisdom.service.NtpClient
+import com.supwisdom.utils.CommonUtil
+import com.supwisdom.utils.DateUtil
+import com.supwisdom.utils.PublicDef
+import com.supwisdom.utils.ThreadPool
+import com.supwisdom.view.BigSwDialog
+import com.supwisdom.view.SWToast
+import java.util.*
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+@Suppress("DEPRECATION")
+class InitActivity : BaseActivity(), IInitView {
+ private lateinit var presenter: InitPresenter
+ private lateinit var vDevphyid: EditText
+ private lateinit var vServerIp: EditText
+ private lateinit var vUri: EditText
+ private lateinit var vPort: EditText
+ private lateinit var vNsdResult: TextView
+ private lateinit var vRadioPayMode: RadioButton
+ private lateinit var vRadioDepositMode: RadioButton
+ private lateinit var vRadioThirdPayMode: RadioButton
+ private lateinit var vRadioThirdLoginMode: RadioButton
+ private var nsdClient: NsdClient? = null
+ private var nsdServiceIp: String? = null
+ private var nsdServicePort: Int = 0
+ private var dialogNsdConfig: BigSwDialog? = null
+ private var nsdConfigAdapter: NsdServerConfigAdapter? = null
+ private val pos = SPApplication.getInstance().getPos()
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_init)
+ initView()
+ initData()
+ }
+
+ private fun initData() {
+ presenter = InitPresenter(this)
+ var record = pos.getConfigPara()
+ if (record == null) {
+ record = ConfigParaRecord()
+ record.mode = 0
+ record.devphyid = "12345678"
+ record.epayIP = "127.0.0.1"
+ record.epayPort = 8080
+ record.epayUri = "restaurant"
+ }
+ record.initOK = false
+ pos.replaceConfigPara(record)
+ val cfgRecord = pos.getConfigPara()
+
+// when {
+// cfgRecord.mode == PublicDef.TERMINAL_DEPOSIT_MODE -> vRadioDepositMode.isChecked = true
+// cfgRecord.mode == PublicDef.TERMINAL_THIRD_PAY_MODE -> vRadioThirdPayMode.isChecked = true
+// cfgRecord.mode == PublicDef.TERMINAL_GATE_MODE -> vRadioGateMode.isChecked = true
+// cfgRecord.mode == PublicDef.TERMINAL_THIRD_LOGIN_MODE -> vRadioThirdLoginMode.isChecked = true
+// else -> vRadioPayMode.isChecked = true
+// }
+ vDevphyid.setText(cfgRecord!!.devphyid)
+ vServerIp.setText(cfgRecord.epayIP)
+ vUri.setText(cfgRecord.epayUri)
+ vPort.setText(cfgRecord.epayPort.toString())
+
+ nsdClient = NsdClient(this, "epay-reg-server", object : NsdClient.IServerFound {
+ override fun onServerFound(serviceInfo: NsdServiceInfo) {
+ nsdServiceIp = serviceInfo.host?.hostAddress
+ nsdServicePort = serviceInfo.port
+ if (nsdServiceIp != null) {
+ asyncGetConfigName()
+ }
+ }
+
+ override fun onServerFail() {
+
+ }
+ })
+ }
+
+ private fun initView() {
+ this.findViewById<Button>(R.id.tv_settings).setOnClickListener {
+ // CommonUtil.sendBroadcast(applicationContext, false)
+ CommonUtil.startNetSetting(this@InitActivity)
+ }
+ this.findViewById<TextView>(R.id.btn_save).setOnClickListener {
+ // val mode = when {
+// vRadioDepositMode.isChecked -> PublicDef.TERMINAL_DEPOSIT_MODE
+// vRadioThirdPayMode.isChecked -> PublicDef.TERMINAL_THIRD_PAY_MODE
+// vRadioThirdLoginMode.isChecked -> PublicDef.TERMINAL_THIRD_LOGIN_MODE
+// vRadioGateMode.isChecked -> PublicDef.TERMINAL_GATE_MODE
+// else -> PublicDef.TERMINAL_PAY_MODE
+// }
+ presenter.saveConfigParam(
+ 0,
+ CommonUtil.getEditView(vDevphyid), CommonUtil.getEditView(vServerIp),
+ CommonUtil.getEditView(vUri), CommonUtil.getEditView(vPort)
+ )
+ }
+ this.findViewById<Button>(R.id.tv_nsd_query).setOnClickListener {
+ if (nsdServiceIp == null) {
+ showSWToastInfo("nsd未连接", PublicDef.TOAST_SHOW_DOUBT)
+ return@setOnClickListener
+ }
+ asyncGetConfigName()
+ }
+ vNsdResult = this.findViewById(R.id.tv_nsd_result) as TextView
+ vRadioPayMode = this.findViewById(R.id.rb_pay_mode) as RadioButton
+ vRadioDepositMode = this.findViewById(R.id.rb_deposit_mode) as RadioButton
+ vRadioThirdPayMode = this.findViewById(R.id.rb_third_pay_mode) as RadioButton
+ vRadioThirdLoginMode = this.findViewById(R.id.rb_third_login_mode) as RadioButton
+ vDevphyid = this.findViewById(R.id.tv_devphyid) as EditText
+ vServerIp = this.findViewById(R.id.tv_server_ip) as EditText
+ vUri = this.findViewById(R.id.tv_uri_root) as EditText
+ vPort = this.findViewById(R.id.tv_server_port) as EditText
+ }
+
+ override fun onResume() {
+ super.onResume()
+ nsdClient!!.start()
+ refresh()
+ }
+
+ override fun onStop() {
+ super.onStop()
+ nsdClient!!.stop()
+ }
+
+ private fun refresh() {
+ AuxScreenController.getInstance().refreshTitle("通讯参数设置")
+ AuxScreenController.getInstance().refreshBottom(DateUtil.getNowDateTime())
+ AuxScreenController.getInstance().refreshContent(Arrays.asList("设备第一次使用", "请联系管理员", "在大屏配置参数"))
+ }
+
+ private fun asyncGetConfigName() {
+ ThreadPool.getShortPool().execute(Runnable {
+ try {
+ val ret = NsdClientApi(nsdServiceIp!!, nsdServicePort).getNsdServerConfigList()
+ runOnUiThread {
+ vNsdResult.text = ret.retmsg
+ if (ret.retcode == PublicDef.SUCCESS) {
+ if (ret.list!!.isEmpty()) {
+ vNsdResult.text = "未找到配置项"
+ return@runOnUiThread
+ } else if (ret.list!!.size == 1) {
+ asyncGetConfigFromNsdServer(ret.list!![0])
+ return@runOnUiThread
+ }
+ vNsdResult.setTextColor(resources.getColor(R.color.light_blue2))
+ if (dialogNsdConfig == null) {
+ dialogNsdConfig = BigSwDialog(this, PublicDef.DIALOG_TYPE_NSD_CONFIG)
+ val vConfigList = dialogNsdConfig!!.findViewById(R.id.rv_config_list) as RecyclerView
+ vConfigList.layoutManager = LinearLayoutManager(this)
+ vConfigList.addItemDecoration(NsdServerConfigAdapter.ItemDecoration(10))
+ nsdConfigAdapter =
+ NsdServerConfigAdapter(this, object : NsdServerConfigAdapter.ConfigNameListener {
+ override fun callback(configName: String) {
+ asyncGetConfigFromNsdServer(configName)
+ dialogNsdConfig!!.dismiss()
+ }
+ })
+ vConfigList.adapter = nsdConfigAdapter
+ }
+ nsdConfigAdapter!!.setList(ret.list)
+ nsdConfigAdapter!!.notifyDataSetChanged()
+ dialogNsdConfig!!.show()
+ } else {
+ vNsdResult.setTextColor(resources.getColor(R.color.cl_red))
+ }
+ }
+ } catch (ex: Exception) {
+ runOnUiThread {
+ vNsdResult.text = "异常:${ex.message}"
+ vNsdResult.setTextColor(resources.getColor(R.color.cl_red))
+ }
+ }
+ })
+ }
+
+ private fun asyncGetConfigFromNsdServer(configName: String) {
+ ThreadPool.getShortPool().execute(Runnable {
+ try {
+ val ret = NsdClientApi(nsdServiceIp!!, nsdServicePort).getEcardConfigParam(configName)
+ NtpClient().startCalibrateTime(ret.systime)
+ runOnUiThread {
+ vNsdResult.text = ret.retmsg
+ if (ret.retcode == PublicDef.SUCCESS) {
+ vNsdResult.setTextColor(resources.getColor(R.color.light_blue2))
+ if (ret.mode == 0) {
+ vRadioPayMode.isChecked = true
+ } else {
+ vRadioDepositMode.isChecked = true
+ }
+ vDevphyid.setText(ret.devphyid)
+ vServerIp.setText(ret.epayIP)
+ vUri.setText(ret.epayUri)
+ vPort.setText(ret.epayPort.toString())
+ } else {
+ vNsdResult.setTextColor(resources.getColor(R.color.cl_red))
+ }
+ }
+ } catch (ex: Exception) {
+ runOnUiThread {
+ vNsdResult.text = "异常:${ex.message}"
+ vNsdResult.setTextColor(resources.getColor(R.color.cl_red))
+ }
+ }
+ })
+ }
+
+ override fun jumpToNextActivity() {
+ jumpActivity(LoadActivity::class.java)
+ }
+
+ override fun getActivity(): Activity {
+ return this
+ }
+
+ override fun showSWToastInfo(msg: String, showway: Int) {
+ SWToast.show(applicationContext, msg, showway)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/init/InitPresenter.kt b/app/src/main/java/com/supwisdom/activities/init/InitPresenter.kt
new file mode 100644
index 0000000..0b46818
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/init/InitPresenter.kt
@@ -0,0 +1,78 @@
+package com.supwisdom.activities.init
+
+import android.text.TextUtils
+import com.supwisdom.activities.SPApplication
+import com.supwisdom.activities.YktSession
+import com.supwisdom.entity.ConfigParaRecord
+import com.supwisdom.entity.ControlParaRecord
+import com.supwisdom.entity.DynamicParaRecord
+import com.supwisdom.utils.CommonUtil
+import com.supwisdom.utils.PublicDef
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+class InitPresenter constructor(iInitView: IInitView) {
+ private val iInitView = iInitView
+ private val pos = SPApplication.getInstance().getPos()
+
+ fun saveConfigParam(mode: Int, devphyid: String, serverip: String, uri: String, port: String) {
+ val record = pos.getConfigPara() ?: ConfigParaRecord()
+ record.mode = mode
+ record.devphyid = devphyid
+ if (TextUtils.isEmpty(devphyid)) {
+ iInitView.showSWToastInfo("终端机编号不能为空!", PublicDef.TOAST_SHOW_DOUBT)
+ return
+ }
+ record.devphyid = devphyid
+
+ if (TextUtils.isEmpty(serverip)) {
+ iInitView.showSWToastInfo("服务器IP不能为空!", PublicDef.TOAST_SHOW_DOUBT)
+ return
+ }
+ record.epayIP = if (serverip.startsWith("http")) {
+ serverip
+ } else {
+ "http://$serverip"
+ }
+
+ try {
+ val tmpPort = Integer.valueOf(port)
+ if (tmpPort > 65535) {
+ iInitView.showSWToastInfo("端口不能大于65535", PublicDef.TOAST_SHOW_DOUBT)
+ return
+ }
+ record.epayPort = tmpPort
+ } catch (e: Exception) {
+ iInitView.showSWToastInfo("端口不合法,请确认!", PublicDef.TOAST_SHOW_DOUBT)
+ return
+ }
+
+ if (TextUtils.isEmpty(uri)) {
+ iInitView.showSWToastInfo("URI不能为空!", PublicDef.TOAST_SHOW_DOUBT)
+ return
+ }
+ record.initOK = false
+ record.epayUri = uri.replace(" ", "")
+ record.shopPwd = PublicDef.PASSWD_SHOP_DEFAULT
+ pos.replaceConfigPara(record)
+
+ val dyRecord = DynamicParaRecord()
+ dyRecord.cardverno = "000000000000"
+ dyRecord.appid = PublicDef.APP_ID
+ dyRecord.appsecret = PublicDef.APP_SECRET
+ pos.replaceDynamicPara(dyRecord)
+
+ YktSession.getInstance().setWebAPISession(
+ record.epayIP!!,
+ record.epayPort,
+ record.epayUri!!,
+ record.devphyid!!,
+ CommonUtil.getCommunicateTime()
+ )
+ iInitView.jumpToNextActivity()
+ }
+
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/init/adapter/NsdServerConfigAdapter.kt b/app/src/main/java/com/supwisdom/activities/init/adapter/NsdServerConfigAdapter.kt
new file mode 100644
index 0000000..8f6e4f9
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/init/adapter/NsdServerConfigAdapter.kt
@@ -0,0 +1,70 @@
+package com.supwisdom.activities.init.adapter
+
+import android.content.Context
+import android.graphics.Rect
+import android.support.v7.widget.RecyclerView
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.LinearLayout
+import android.widget.TextView
+import com.supwisdom.R
+
+/**
+ * @author zzq
+ * @date 2018/7/12
+ * @desc nsd server 参数配置列表
+ */
+class NsdServerConfigAdapter constructor(context: Context, callback: ConfigNameListener) :
+ RecyclerView.Adapter<NsdServerConfigAdapter.Holder>() {
+ private val context = context
+ private val list = ArrayList<String>()
+ private val listener = callback
+ fun setList(data: List<String>?) {
+ list.clear()
+ if (data != null) {
+ list.addAll(data)
+ }
+ }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
+ return Holder(LayoutInflater.from(context).inflate(R.layout.item_init_nsd_config_list, parent, false))
+ }
+
+ override fun getItemCount(): Int {
+ return list.size
+ }
+
+ override fun onBindViewHolder(holder: Holder, position: Int) {
+ holder.vConfigId.text = "配置$position:"
+ holder.vConfigName.text = list[position]
+ holder.vConfig.setOnClickListener {
+ listener.callback(list[position])
+ }
+ }
+
+ inner class Holder constructor(itemView: View) : RecyclerView.ViewHolder(itemView) {
+ var vConfigName: TextView
+ var vConfigId: TextView
+ var vConfig: LinearLayout
+
+ init {
+ vConfigId = itemView.findViewById(R.id.tv_config_id) as TextView
+ vConfigName = itemView.findViewById(R.id.tv_config_name) as TextView
+ vConfig = itemView.findViewById(R.id.ll_config) as LinearLayout
+ }
+ }
+
+ class ItemDecoration constructor(space: Int) : RecyclerView.ItemDecoration() {
+ private val space = space
+ override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
+ outRect.left = space
+ outRect.right = space
+ outRect.bottom = space
+ }
+ }
+
+ interface ConfigNameListener {
+ fun callback(configName: String)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/init/bean/EcardConfigParamBean.kt b/app/src/main/java/com/supwisdom/activities/init/bean/EcardConfigParamBean.kt
new file mode 100644
index 0000000..538dbb3
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/init/bean/EcardConfigParamBean.kt
@@ -0,0 +1,17 @@
+package com.supwisdom.activities.init.bean
+
+import com.supwisdom.bean.BaseResp
+
+/**
+ * @author zzq
+ * @date 2018/7/11
+ * @desc 配置结果
+ */
+class EcardConfigParamBean constructor(retcode: Int, retmsg: String) : BaseResp(retcode, retmsg) {
+ var mode: Int = 0
+ var devphyid: String? = null
+ var epayIP: String? = null
+ var epayUri: String? = null
+ var epayPort: Int = 0
+ var systime: Long = 0
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/init/bean/EcardConfigParamRetBean.java b/app/src/main/java/com/supwisdom/activities/init/bean/EcardConfigParamRetBean.java
new file mode 100644
index 0000000..184c457
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/init/bean/EcardConfigParamRetBean.java
@@ -0,0 +1,54 @@
+package com.supwisdom.activities.init.bean;
+
+/**
+ * @author zzq
+ * @date 2018/7/12
+ * @desc nsd server返回结果
+ */
+public class EcardConfigParamRetBean {
+ private String _id;
+ private String name;
+ private String timestamp;
+ private String url;
+ private long system;
+
+ public String get_id() {
+ return _id;
+ }
+
+ public void set_id(String _id) {
+ this._id = _id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getTimestamp() {
+ return timestamp;
+ }
+
+ public void setTimestamp(String timestamp) {
+ this.timestamp = timestamp;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ public long getSystem() {
+ return system;
+ }
+
+ public void setSystem(long system) {
+ this.system = system;
+ }
+}
diff --git a/app/src/main/java/com/supwisdom/activities/init/bean/NsdServerConfigRetBean.kt b/app/src/main/java/com/supwisdom/activities/init/bean/NsdServerConfigRetBean.kt
new file mode 100644
index 0000000..d6caa8f
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/init/bean/NsdServerConfigRetBean.kt
@@ -0,0 +1,12 @@
+package com.supwisdom.activities.init.bean
+
+import com.supwisdom.bean.BaseResp
+
+/**
+ * @author zzq
+ * @date 2018/7/12
+ * @desc nsd server 返回配置列表
+ */
+class NsdServerConfigRetBean constructor(retcode: Int, retmsg: String) : BaseResp(retcode, retmsg) {
+ var list: List<String>? = null
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/init/mode/NsdClient.kt b/app/src/main/java/com/supwisdom/activities/init/mode/NsdClient.kt
new file mode 100644
index 0000000..2f3bf18
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/init/mode/NsdClient.kt
@@ -0,0 +1,106 @@
+package com.supwisdom.activities.init.mode
+
+import android.content.Context
+import android.net.nsd.NsdManager
+import android.net.nsd.NsdServiceInfo
+import android.util.Log
+
+class NsdClient constructor(context: Context, serviceName: String, callback: IServerFound) {
+ private val TAG = NsdClient::class.java.simpleName
+ /**
+ * NSD_SERVICE_NAME和NSD_SERVER_TYPE需要与服务器端完全一致
+ */
+ private val NSD_SERVER_TYPE = "_http._tcp."
+ private val context = context
+ private val serviceName = serviceName
+ private val mIServerFound = callback
+
+ private var mDiscoveryListener: NsdManager.DiscoveryListener? = null
+ private var mResolverListener: NsdManager.ResolveListener? = null
+ private var mNsdManager: NsdManager? = null
+ private var singleFlag = false
+
+
+ fun start() {
+ mNsdManager = context.getSystemService(Context.NSD_SERVICE) as NsdManager
+ initializeDiscoveryListener()
+ mNsdManager!!.discoverServices(NSD_SERVER_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener)
+ initializeResolveListener()
+ }
+
+ /**
+ * 扫描未被解析前的 NsdServiceInfo
+ * 用于服务发现的回调调用接口
+ */
+ private fun initializeDiscoveryListener() {
+ mDiscoveryListener = object : NsdManager.DiscoveryListener {
+ override fun onStartDiscoveryFailed(serviceType: String, errorCode: Int) {
+ mNsdManager!!.stopServiceDiscovery(this)
+ Log.e(TAG, "onStartDiscoveryFailed():")
+ }
+
+ override fun onStopDiscoveryFailed(serviceType: String, errorCode: Int) {
+ mNsdManager!!.stopServiceDiscovery(this)
+ Log.e(TAG, "onStopDiscoveryFailed():")
+ }
+
+ override fun onDiscoveryStarted(serviceType: String) {
+ Log.e(TAG, "onDiscoveryStarted():")
+ }
+
+ override fun onDiscoveryStopped(serviceType: String) {
+ Log.e(TAG, "onDiscoveryStopped():")
+ }
+
+ /**
+ *
+ * @param serviceInfo
+ */
+ override fun onServiceFound(serviceInfo: NsdServiceInfo) {
+
+ //根据咱服务器的定义名称,指定解析该 NsdServiceInfo
+ if (serviceInfo.serviceName == serviceName) {
+ if (!singleFlag) {
+ singleFlag = true
+ mNsdManager!!.resolveService(serviceInfo, mResolverListener)
+ }
+ }
+ }
+
+ override fun onServiceLost(serviceInfo: NsdServiceInfo) {
+ Log.e(TAG, "onServiceLost(): serviceInfo=$serviceInfo")
+ }
+ }
+ }
+
+ /**
+ * 解析未 调用未被解析的 NsdServiceInfo
+ */
+ private fun initializeResolveListener() {
+ mResolverListener = object : NsdManager.ResolveListener {
+ override fun onResolveFailed(serviceInfo: NsdServiceInfo, errorCode: Int) {}
+
+ override fun onServiceResolved(serviceInfo: NsdServiceInfo) {
+ mIServerFound.onServerFound(serviceInfo)
+ }
+ }
+ }
+
+
+ fun stop() {
+ mNsdManager!!.stopServiceDiscovery(mDiscoveryListener)
+ singleFlag = false
+ }
+
+ interface IServerFound {
+ /**
+ * 回調 指定解析的结果
+ */
+ fun onServerFound(serviceInfo: NsdServiceInfo)
+
+ /**
+ * 無合適 回調失敗
+ */
+ fun onServerFail()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/init/mode/NsdClientApi.kt b/app/src/main/java/com/supwisdom/activities/init/mode/NsdClientApi.kt
new file mode 100644
index 0000000..5b1785c
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/init/mode/NsdClientApi.kt
@@ -0,0 +1,80 @@
+package com.supwisdom.activities.init.mode
+
+import com.beust.klaxon.JsonArray
+import com.beust.klaxon.Parser
+import com.supwisdom.activities.init.bean.EcardConfigParamBean
+import com.supwisdom.activities.init.bean.EcardConfigParamRetBean
+import com.supwisdom.activities.init.bean.NsdServerConfigRetBean
+import com.supwisdom.okhttp.NetworkHandler
+import com.supwisdom.utils.CommonUtil
+import com.supwisdom.utils.GsonUtil
+import com.supwisdom.utils.PublicDef
+import org.apache.http.HttpStatus
+
+/**
+ * @author zzq
+ * @date 2018/7/11
+ * @desc 从nsd-server获取数据
+ */
+class NsdClientApi constructor(ip: String, port: Int) {
+ private var url: String = "http://$ip:$port"
+
+ fun getEcardConfigParam(configName: String): EcardConfigParamBean {
+ val resp = NetworkHandler.getInstance().get("$url/ns/$configName", null)
+ ?: return EcardConfigParamBean(PublicDef.ERROR, "请求超时")
+ if (resp.retcode != HttpStatus.SC_OK) {
+ return EcardConfigParamBean(resp.retcode, "错误码=${resp.retcode},${resp.retmsg}")
+ }
+ try {
+ val retBean = GsonUtil.GsonToBean(resp.retjson!!, EcardConfigParamRetBean::class.java)
+ val ret = EcardConfigParamBean(PublicDef.SUCCESS, "获取成功")
+ ret.systime = retBean.system
+ retBean.url!!.split("&", " ").forEach {
+ val keyValue = it.split("=")
+ when {
+ keyValue[0].compareTo("mode", ignoreCase = true) == 0 -> {
+ if (!CommonUtil.isNumeric(keyValue[1])) {
+ return EcardConfigParamBean(PublicDef.ERROR, "mode不是数字")
+ }
+ ret.mode = keyValue[1].toInt()
+ }
+ keyValue[0].compareTo("id", ignoreCase = true) == 0 -> {
+ if (!CommonUtil.isNumeric(keyValue[1])) {
+ return EcardConfigParamBean(PublicDef.ERROR, "id不是数字")
+ }
+ ret.devphyid = keyValue[1]
+ }
+ keyValue[0].compareTo("ip", ignoreCase = true) == 0 -> {
+ ret.epayIP = keyValue[1]
+ }
+ keyValue[0].compareTo("uri", ignoreCase = true) == 0 -> {
+ ret.epayUri = keyValue[1]
+ }
+ keyValue[0].compareTo("port", ignoreCase = true) == 0 -> {
+ if (!CommonUtil.isNumeric(keyValue[1])) {
+ return EcardConfigParamBean(PublicDef.ERROR, "port不是数字")
+ }
+ ret.epayPort = keyValue[1].toInt()
+ }
+ }
+ }
+ return ret
+ } catch (ex: Exception) {
+ ex.printStackTrace()
+ return EcardConfigParamBean(PublicDef.ERROR, "异常:${ex.message}")
+ }
+ }
+
+ fun getNsdServerConfigList(): NsdServerConfigRetBean {
+ val resp = NetworkHandler.getInstance().get("$url/list", null)
+ ?: return NsdServerConfigRetBean(PublicDef.ERROR, "请求超时")
+ if (resp.retcode != HttpStatus.SC_OK) {
+ return NsdServerConfigRetBean(resp.retcode, "错误码=${resp.retcode},${resp.retmsg}")
+ }
+ return NsdServerConfigRetBean(PublicDef.SUCCESS, "成功").apply {
+ this.list = (Parser().parse(StringBuilder(resp.retjson)) as JsonArray<String>).map {
+ it
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/load/ILoadView.kt b/app/src/main/java/com/supwisdom/activities/load/ILoadView.kt
new file mode 100644
index 0000000..e94d5c0
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/load/ILoadView.kt
@@ -0,0 +1,17 @@
+package com.supwisdom.activities.load
+
+import android.app.Activity
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+interface ILoadView {
+ fun getActivity(): Activity
+
+ fun showProgress(hint: String, clearlast: Boolean)
+
+ fun showFinish()
+
+ fun jumpToUnregister(errmsg: String)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/load/LoadActivity.kt b/app/src/main/java/com/supwisdom/activities/load/LoadActivity.kt
new file mode 100644
index 0000000..1e71cf2
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/load/LoadActivity.kt
@@ -0,0 +1,100 @@
+package com.supwisdom.activities.load
+
+import android.app.Activity
+import android.content.Intent
+import android.os.Bundle
+import android.view.View
+import android.widget.TextView
+import android.widget.Toast
+import com.supwisdom.R
+import com.supwisdom.activities.BaseActivity
+import com.supwisdom.activities.consume.ConsumeActivity
+import com.supwisdom.activities.unregister.UnregisterActivity
+import com.supwisdom.auxscreen.AuxScreenController
+import com.supwisdom.utils.DateUtil
+import java.util.*
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+class LoadActivity : BaseActivity(), ILoadView {
+ private lateinit var presenter: LoadPresenter
+ private lateinit var vLoadPro: TextView
+ private val procontent = StringBuilder()
+ private val auxList = ArrayList<String>()
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_load)
+
+ initView()
+ initData()
+ }
+
+ override fun onResume() {
+ super.onResume()
+ presenter.start()
+ refresh()
+ }
+
+ private fun refresh() {
+ procontent.setLength(0)
+ auxList.clear()
+ AuxScreenController.getInstance().refreshTitle("设备参数加载")
+ AuxScreenController.getInstance().refreshBottom(DateUtil.getNowDateTime())
+ AuxScreenController.getInstance().refreshContent(auxList)
+ }
+
+ private fun initData() {
+ presenter = LoadPresenter(this)
+ }
+
+ private fun initView() {
+ this.findViewById<View>(R.id.btn_back).setOnClickListener {
+ if (presenter.isLoading()) {
+ Toast.makeText(applicationContext, "正在加载信息", Toast.LENGTH_SHORT).show()
+ } else {
+ this@LoadActivity.finish()
+ }
+ }
+ vLoadPro = findViewById<View>(R.id.tv_load_pro) as TextView
+ }
+
+ override fun getActivity(): Activity {
+ return this
+ }
+
+ override fun showProgress(hint: String, clearlast: Boolean) {
+ procontent.append("\n").append(hint)
+ vLoadPro.text = procontent.toString()
+ if (clearlast) {
+ if (auxList.size > 0) {
+ auxList.removeAt(auxList.size - 1)
+ }
+ }
+ auxList.add(hint)
+ AuxScreenController.getInstance().refreshContent(showFormatAux())
+ }
+
+ override fun showFinish() {
+ jumpActivity(ConsumeActivity::class.java)
+ }
+
+ override fun jumpToUnregister(errmsg: String) {
+ val intent = Intent()
+ intent.putExtra("errmsg", errmsg)
+ intent.setClass(this, UnregisterActivity::class.java)
+ startActivity(intent)
+ }
+
+ private fun showFormatAux(): List<String> {
+ val list = ArrayList<String>()
+ val size = auxList.size
+ list.addAll(auxList)
+ for (i in size..4) {
+ list.add(" ")
+ }
+ return list
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/load/LoadPresenter.kt b/app/src/main/java/com/supwisdom/activities/load/LoadPresenter.kt
new file mode 100644
index 0000000..f6d0578
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/load/LoadPresenter.kt
@@ -0,0 +1,138 @@
+package com.supwisdom.activities.load
+
+import android.os.Handler
+import android.os.Looper
+import android.os.Message
+import com.supwisdom.activities.SPApplication
+import com.supwisdom.activities.YktSession
+import com.supwisdom.bean.AuthRetBean
+import com.supwisdom.exception.AuthEpayError
+import com.supwisdom.service.AuthEpay
+import com.supwisdom.service.EpayApiImpl
+import com.supwisdom.utils.CommonUtil
+import com.supwisdom.utils.PublicDef
+import com.supwisdom.utils.ThreadPool
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+class LoadPresenter constructor(iLoadView: ILoadView) {
+ private val iLoadView = iLoadView
+ private val pos = SPApplication.getInstance().getPos()
+ private lateinit var handler: Handler
+
+ init {
+ createHandler()
+ }
+
+ private val LOAD_SUCCESS = 1
+ private val JUMP_TO_UNREGISTER = 2
+ private val LOAD_PROGRESS = 3
+ private val LOAD_DONE = 3
+
+ private var hasInit: Boolean = false
+ @Volatile
+ private var loading: Boolean = false
+
+ fun isLoading(): Boolean {
+ return loading
+ }
+
+ fun start() {
+ loading = true
+ var cfgRecord = pos.getConfigPara()
+ hasInit = cfgRecord?.initOK ?: false
+
+ YktSession.getInstance().setWebAPISession(
+ cfgRecord!!.epayIP!!,
+ cfgRecord.epayPort,
+ cfgRecord.epayUri!!,
+ cfgRecord.devphyid!!,
+ CommonUtil.getCommunicateTime()
+ )
+
+ ThreadPool.getShortPool().execute(Runnable {
+ sendMessage(LOAD_PROGRESS, "正在系统签到...")
+ val bean = try {
+ AuthEpay().login()
+ } catch (ex: AuthEpayError) {
+ AuthRetBean(PublicDef.ERROR, ex.message ?: "null")
+ }
+ if (bean.retcode != PublicDef.SUCCESS) {
+ sendMessage(LOAD_DONE, bean.retmsg!!)
+ loading = false
+ if (!hasInit) {
+ sendMessage(JUMP_TO_UNREGISTER, "签到失败:${bean.retmsg}")
+ return@Runnable
+ }
+ } else {
+ val dyRecord = pos.getDynamicPara()
+ dyRecord!!.deviceid = bean.deviceid
+ dyRecord.merchaccno = bean.merchaccno
+ dyRecord.shopname = bean.shopname
+ dyRecord.onlineseqno = bean.onlineseqno
+ dyRecord.offlineseqno = bean.offlineseqno
+ dyRecord.paragroupid = bean.paragroupid
+ pos.replaceDynamicPara(dyRecord)
+
+ SPApplication.getInstance().setEpayLinking(true)
+ sendMessage(LOAD_DONE, "系统签到成功")
+ }
+
+ // 设置通讯参数
+ val apiInterface = EpayApiImpl()
+ try {
+ sendMessage(LOAD_PROGRESS, "加载系统参数...")
+ apiInterface.downloadSyspara(bean.paragroupid, bean.paraverno)
+ sendMessage(LOAD_DONE, "加载系统参数成功")
+ } catch (ex: Exception) {
+ sendMessage(LOAD_DONE, "加载系统参数失败:${ex.message}")
+ if (!hasInit) {
+ loading = false
+ return@Runnable
+ }
+ }
+
+ try {
+ sendMessage(LOAD_PROGRESS, "加载白名单...")
+ apiInterface.downloadWhitelist(bean.cardverno!!)
+ sendMessage(LOAD_DONE, "加载白名单成功")
+ } catch (ex: Exception) {
+ sendMessage(LOAD_DONE, "加载白名单失败:${ex.message}")
+ if (!hasInit) {
+ loading = false
+ return@Runnable
+ }
+ }
+
+ cfgRecord = pos.getConfigPara()
+ cfgRecord!!.initOK = true
+ pos.replaceConfigPara(cfgRecord!!)
+ sendMessage(LOAD_SUCCESS, "加载成功")
+ })
+ }
+
+ private fun createHandler() {
+ handler = object : Handler(Looper.getMainLooper()) {
+ override fun handleMessage(msg: Message) {
+ when (msg.what) {
+ LOAD_DONE -> iLoadView.showProgress(msg.obj as String, true)
+ LOAD_PROGRESS -> iLoadView.showProgress(msg.obj as String, false)
+ JUMP_TO_UNREGISTER -> iLoadView.jumpToUnregister(msg.obj as String)
+ LOAD_SUCCESS -> {
+ CommonUtil.doSleep(3000)
+ iLoadView.showFinish()
+ }
+ }
+ }
+ }
+ }
+
+ private fun sendMessage(code: Int, info: String) {
+ val msg = Message()
+ msg.what = code
+ msg.obj = info
+ handler.sendMessage(msg)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/manage/IManageView.kt b/app/src/main/java/com/supwisdom/activities/manage/IManageView.kt
new file mode 100644
index 0000000..27bb27f
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/manage/IManageView.kt
@@ -0,0 +1,11 @@
+package com.supwisdom.activities.manage
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+interface IManageView {
+ fun showOperHint(hint: String, result: String)
+
+ fun showOperResult(hint: String, result: String)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/manage/ManageActivity.kt b/app/src/main/java/com/supwisdom/activities/manage/ManageActivity.kt
new file mode 100644
index 0000000..ec4b7be
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/manage/ManageActivity.kt
@@ -0,0 +1,170 @@
+package com.supwisdom.activities.manage
+
+import android.os.Bundle
+import android.os.CountDownTimer
+import android.view.KeyEvent
+import com.supwisdom.R
+import com.supwisdom.activities.BaseActivity
+import com.supwisdom.activities.SPApplication
+import com.supwisdom.activities.communicate.CommunicateActivity
+import com.supwisdom.activities.control.ControlActivity
+import com.supwisdom.activities.menu.MenuActivity
+import com.supwisdom.activities.upgrade.UpgradeActivity
+import com.supwisdom.auxscreen.AuxScreenController
+import com.supwisdom.utils.AppExitUtil
+import com.supwisdom.utils.CommonUtil
+import com.supwisdom.utils.DateUtil
+import java.util.*
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class ManageActivity : BaseActivity(), IManageView {
+ private var presenter: ManagePresenter? = null
+ private var flag: Boolean = false
+ private var isRunning: Boolean = false
+ private val pos = SPApplication.getInstance().getPos()
+ @Volatile
+ private var keyActive = true
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_manage)
+ initView()
+ initData()
+ }
+
+ private fun initView() {
+
+ }
+
+ private fun initData() {
+ presenter = ManagePresenter(this)
+ }
+
+ override fun dispatchKeyEvent(event: KeyEvent): Boolean {
+ if (event.action == KeyEvent.ACTION_DOWN) {
+ if (isRunning || !keyActive) {
+ return super.dispatchKeyEvent(event)
+ }
+ resetCounter(200)
+
+ val keyCode = event.keyCode
+ if (flag) {
+ return if (KeyEvent.KEYCODE_DEL == keyCode) {
+ refresh()
+ true
+ } else {
+ false
+ }
+ }
+ when (keyCode) {
+ KeyEvent.KEYCODE_1 -> {
+ flag = true
+ showShopPassword()
+ }
+ KeyEvent.KEYCODE_2 -> jumpActivity(CommunicateActivity::class.java)
+ KeyEvent.KEYCODE_3 -> {
+ //查询流水
+ flag = true
+ AuxScreenController.getInstance().refreshContent(Arrays.asList<String>("流水查询:", "暂不支持"))
+ }
+ KeyEvent.KEYCODE_4 -> {
+ flag = true
+ isRunning = true
+ AuxScreenController.getInstance()
+ .refreshContent(Arrays.asList<String>("正在导出流水", "请稍等..."))
+ presenter!!.outTransdtl()
+ }
+ KeyEvent.KEYCODE_5 -> jumpActivity(UpgradeActivity::class.java)
+ KeyEvent.KEYCODE_6 -> {
+ AuxScreenController.getInstance()
+ .refreshContent(Arrays.asList<String>("应用程序已退出", "请到大屏操作"))
+ AppExitUtil.exit()
+ }
+ KeyEvent.KEYCODE_7 -> {
+ AuxScreenController.getInstance()
+ .refreshContent(Arrays.asList<String>("应用程序已退出", "请到大屏操作"))
+ CommonUtil.startNetSetting(this)
+ }
+ KeyEvent.KEYCODE_8 -> {
+ flag = true
+ isRunning = true
+ AuxScreenController.getInstance()
+ .refreshContent(Arrays.asList<String>("正在清空白名单", "请稍等..."))
+ presenter!!.clearAndUpdateWhitelist()
+ }
+ KeyEvent.KEYCODE_9 -> jumpActivity(ControlActivity::class.java)
+ KeyEvent.KEYCODE_DEL ->
+ //cancel
+ jumpActivity(MenuActivity::class.java)
+ }
+ }
+ return super.dispatchKeyEvent(event)
+ }
+
+ override fun showOperHint(hint: String, result: String) {
+ AuxScreenController.getInstance().refreshContent(Arrays.asList<String>(hint, result))
+ }
+
+ override fun showOperResult(hint: String, result: String) {
+ flag = true
+ isRunning = false
+ AuxScreenController.getInstance().refreshContent(Arrays.asList<String>(hint, result))
+ }
+
+ override fun onResume() {
+ super.onResume()
+ keyActive = true
+ refresh()
+ }
+
+ private fun refresh() {
+ flag = false
+ isRunning = false
+ AuxScreenController.getInstance().refreshTitle("设备管理界面")
+ AuxScreenController.getInstance().refreshBottom(DateUtil.getNowDateTime())
+ AuxScreenController.getInstance().refreshContent(
+ Arrays.asList(
+ getString(R.string.consume_menu_shop_passwd),
+ getString(R.string.consume_menu_comm_set),
+ getString(R.string.consume_menu_unconfirm_transdtl),
+ getString(R.string.consume_menu_out_dtl),
+ getString(R.string.consume_menu_upgrade),
+ getString(R.string.consume_menu_app_exit),
+ getString(R.string.consume_menu_setting),
+ getString(R.string.consume_menu_clear_blklist),
+ getString(R.string.consume_menu_control_set)
+ )
+ )
+ }
+
+ private fun showShopPassword() {
+ AuxScreenController.getInstance()
+ .refreshContent(Arrays.asList<String>("商户密码:", pos.getConfigPara()!!.shopPwd))
+ }
+
+ private var counter: ContinuePressTimer? = null
+
+ private fun resetCounter(timems: Long) {
+ counter?.cancel()
+ if (counter == null) {
+ counter = ContinuePressTimer(timems, 100)
+ }
+ keyActive = false
+ counter!!.start()
+ }
+
+ private inner class ContinuePressTimer internal constructor(millisInFuture: Long, countDownInterval: Long) :
+ CountDownTimer(millisInFuture, countDownInterval) {
+
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ keyActive = true
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/manage/ManagePresenter.kt b/app/src/main/java/com/supwisdom/activities/manage/ManagePresenter.kt
new file mode 100644
index 0000000..cfc459c
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/manage/ManagePresenter.kt
@@ -0,0 +1,93 @@
+package com.supwisdom.activities.manage
+
+import android.os.AsyncTask
+import com.supwisdom.activities.SPApplication
+import com.supwisdom.bean.BaseResp
+import com.supwisdom.service.EpayApiImpl
+import com.supwisdom.utils.PublicDef
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class ManagePresenter constructor(iManageView: IManageView) {
+ private val iManageView = iManageView
+ private val pos = SPApplication.getInstance().getPos()
+
+ fun clearAndUpdateWhitelist() {
+ if (!SPApplication.getInstance().isOnline()) {
+ iManageView.showOperHint("重置黑名单失败", "网络未联通")
+ return
+ }
+ ClearWhiteList().execute()
+ }
+
+ fun reloadTransdtl() {
+ if (!SPApplication.getInstance().isOnline()) {
+ iManageView.showOperHint("补采流水失败", "网络未联通")
+ return
+ }
+ iManageView.showOperHint("正在补采流水", "请稍等...")
+ ReloadTransdtl().execute()
+ }
+
+ fun outTransdtl() {
+ iManageView.showOperHint("正在导出流水", "请稍等...")
+ OutTransdtl().execute()
+ }
+
+ private inner class ReloadTransdtl : AsyncTask<Void, Int, BaseResp>() {
+ override fun onPostExecute(resp: BaseResp) {
+ if (resp.retcode == PublicDef.SUCCESS) {
+ iManageView.showOperResult("补采流水成功", resp.retmsg!!)
+ } else {
+ iManageView.showOperResult("补采流水失败", resp.retmsg!!)
+ }
+ }
+
+ override fun doInBackground(vararg params: Void): BaseResp {
+ return BaseResp(PublicDef.ERROR, "暂未实现")
+ }
+ }
+
+ private inner class ClearWhiteList : AsyncTask<Void, Int, BaseResp>() {
+ override fun onPostExecute(resp: BaseResp) {
+ if (resp.retcode == PublicDef.SUCCESS) {
+ iManageView.showOperResult("黑名单更新成功", "")
+ } else {
+ iManageView.showOperResult("黑名单更新失败", resp.retmsg!!)
+ }
+ }
+
+ override fun doInBackground(vararg params: Void): BaseResp {
+ return try {
+ EpayApiImpl().downloadWhitelist("0")
+ BaseResp(PublicDef.ERROR, "更新成功")
+ } catch (ex: Exception) {
+ BaseResp(PublicDef.ERROR, ex.message)
+ }
+ }
+ }
+
+ private inner class OutTransdtl : AsyncTask<Void, Int, BaseResp>() {
+ override fun doInBackground(vararg params: Void): BaseResp {
+ var num = 0
+// val bm1List = pos.getTransdtlBM1(null)
+// if (bm1List != null) {
+// num += bm1List!!.size
+// for (i in bm1List!!.indices) {
+// FileUtil.writeDtlFile(bm1List!!.get(i).toString())
+// }
+// }
+ return BaseResp(PublicDef.SUCCESS, "共导出" + num + "笔")
+ }
+
+ override fun onPostExecute(resp: BaseResp) {
+ if (resp.retcode == PublicDef.SUCCESS) {
+ iManageView.showOperResult("导出流水成功", resp.retmsg!!)
+ } else {
+ iManageView.showOperResult("导出流水失败", resp.retmsg!!)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/menu/IMenuView.kt b/app/src/main/java/com/supwisdom/activities/menu/IMenuView.kt
new file mode 100644
index 0000000..ff202b4
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/menu/IMenuView.kt
@@ -0,0 +1,15 @@
+package com.supwisdom.activities.menu
+
+import android.app.Activity
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+interface IMenuView {
+ fun getActivity(): Activity
+
+ fun showOperHint(title: String, result: String)
+
+ fun showOperResult(title: String, result: String)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/menu/MenuActivity.kt b/app/src/main/java/com/supwisdom/activities/menu/MenuActivity.kt
new file mode 100644
index 0000000..4c92368
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/menu/MenuActivity.kt
@@ -0,0 +1,172 @@
+package com.supwisdom.activities.menu
+
+import android.app.Activity
+import android.content.Intent
+import android.os.Bundle
+import android.os.CountDownTimer
+import android.view.KeyEvent
+import android.view.View
+import android.widget.TextView
+import com.supwisdom.R
+import com.supwisdom.activities.BaseActivity
+import com.supwisdom.activities.SPApplication
+import com.supwisdom.activities.checkMngpwd.CheckMngpwdActivity
+import com.supwisdom.activities.consume.ConsumeActivity
+import com.supwisdom.activities.consumeMode.ConsumeModeActivity
+import com.supwisdom.activities.passwd.PasswdActivity
+import com.supwisdom.activities.revenue.RevenueActivity
+import com.supwisdom.activities.syspara.SysparaActivity
+import com.supwisdom.auxscreen.AuxScreenController
+import com.supwisdom.utils.DateUtil
+import java.util.*
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class MenuActivity : BaseActivity(), IMenuView {
+ private lateinit var presenter: MenuPresenter
+ private val pos = SPApplication.getInstance().getPos()
+ private var isRunning: Boolean = false
+ private var flag: Boolean = false
+ private lateinit var vReverse: TextView
+ private var keyActive = true
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ this.setContentView(R.layout.activity_menu)
+ initView()
+ initData()
+ }
+
+ private fun initData() {
+ presenter = MenuPresenter(this)
+ }
+
+ private fun initView() {
+ vReverse = this.findViewById<View>(R.id.tv_reverse) as TextView
+ }
+
+ override fun dispatchKeyEvent(event: KeyEvent): Boolean {
+ if (event.action == KeyEvent.ACTION_DOWN) {
+ if (isRunning || !keyActive) {
+ return super.dispatchKeyEvent(event)
+ }
+ resetCounter(200)
+
+ val keyCode = event.keyCode
+ if (flag) {
+ return if (KeyEvent.KEYCODE_DEL == keyCode) {
+ refresh()
+ true
+ } else {
+ false
+ }
+ }
+ when (keyCode) {
+ KeyEvent.KEYCODE_1 -> jumpActivity(RevenueActivity::class.java)
+ KeyEvent.KEYCODE_2 -> {
+ isRunning = true
+ presenter.uploadTransdtl()
+ }
+ KeyEvent.KEYCODE_3 -> {
+ isRunning = true
+ presenter.linkCheck()
+ }
+ KeyEvent.KEYCODE_4 -> {
+ isRunning = true
+ presenter.manualAuth()
+ }
+ KeyEvent.KEYCODE_5 -> jumpActivity(SysparaActivity::class.java)
+ KeyEvent.KEYCODE_6 -> {
+ val intent = Intent()
+ intent.putExtra("password", pos.getSysPara()!!.mngPasswd)
+ intent.setClass(this, CheckMngpwdActivity::class.java)
+ startActivity(intent)
+ }
+ KeyEvent.KEYCODE_7 -> jumpActivity(PasswdActivity::class.java)
+ KeyEvent.KEYCODE_8 -> jumpActivity(ConsumeModeActivity::class.java)
+ KeyEvent.KEYCODE_9 -> if (isSupportReverse()) {
+ presenter.doReverse()
+ }
+ KeyEvent.KEYCODE_DEL -> {
+ //cancel
+ jumpActivity(ConsumeActivity::class.java)
+ }
+ KeyEvent.KEYCODE_ENTER -> jumpActivity(ConsumeActivity::class.java)
+ }
+ }
+ return super.dispatchKeyEvent(event)
+ }
+
+ override fun onResume() {
+ super.onResume()
+ keyActive = true
+ refresh()
+ }
+
+ override fun showOperHint(title: String, result: String) {
+ AuxScreenController.getInstance().refreshContent(Arrays.asList<String>(title, result))
+ }
+
+ override fun showOperResult(title: String, result: String) {
+ flag = true
+ isRunning = false
+ AuxScreenController.getInstance().refreshContent(Arrays.asList<String>(title, result))
+ }
+
+ override fun getActivity(): Activity {
+ return this
+ }
+
+ private fun refresh() {
+ isRunning = false
+ flag = false
+ val secList = ArrayList<String>()
+ secList.add(getString(R.string.consume_menu_revenue))
+ secList.add(getString(R.string.consume_menu_transdtl_upload))
+ secList.add(getString(R.string.consume_menu_link_check))
+ secList.add(getString(R.string.consume_menu_auth))
+ secList.add(getString(R.string.consume_menu_syspara_query))
+ secList.add(getString(R.string.consume_menu_manage))
+ secList.add(getString(R.string.consume_menu_shop_password_set))
+ secList.add(getString(R.string.consume_menu_consume_mode))
+ if (isSupportReverse()) {
+ vReverse.visibility = View.VISIBLE
+ secList.add(getString(R.string.consume_menu_reverse))
+ } else {
+ vReverse.visibility = View.GONE
+ }
+ AuxScreenController.getInstance().refreshTitle("设备管理界面")
+ AuxScreenController.getInstance().refreshBottom(DateUtil.getNowDateTime())
+ AuxScreenController.getInstance().refreshContent(secList)
+ }
+
+ private fun isSupportReverse(): Boolean {
+ val sysRecord = SPApplication.getInstance().getPos().getSysPara()
+ return sysRecord != null && sysRecord.returnFlag and 0x1 == 1
+ }
+
+ private var counter: ContinuePressTimer? = null
+
+ private fun resetCounter(timems: Long) {
+ counter?.cancel()
+ if (counter == null) {
+ counter = ContinuePressTimer(timems, 100)
+ }
+ keyActive = false
+ counter!!.start()
+ }
+
+ private inner class ContinuePressTimer internal constructor(millisInFuture: Long, countDownInterval: Long) :
+ CountDownTimer(millisInFuture, countDownInterval) {
+
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ keyActive = true
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/menu/MenuPresenter.kt b/app/src/main/java/com/supwisdom/activities/menu/MenuPresenter.kt
new file mode 100644
index 0000000..cbfac25
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/menu/MenuPresenter.kt
@@ -0,0 +1,151 @@
+package com.supwisdom.activities.menu
+
+import android.content.Intent
+import android.os.AsyncTask
+import com.supwisdom.activities.SPApplication
+import com.supwisdom.activities.consume.ConsumeActivity
+import com.supwisdom.bean.AuthRetBean
+import com.supwisdom.bean.BaseResp
+import com.supwisdom.entity.PayStatus
+import com.supwisdom.entity.ReversalFlag
+import com.supwisdom.exception.AuthEpayError
+import com.supwisdom.exception.HeartBeatError
+import com.supwisdom.exception.TransdtlUploadError
+import com.supwisdom.service.AuthEpay
+import com.supwisdom.service.EpayApiImpl
+import com.supwisdom.utils.CommonUtil
+import com.supwisdom.utils.DateUtil
+import com.supwisdom.utils.PublicDef
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class MenuPresenter constructor(iMenuView: IMenuView) {
+ private val iMenuView = iMenuView
+ private val pos = SPApplication.getInstance().getPos()
+ fun manualAuth() {
+ iMenuView.showOperHint("正在签到", "请稍等...")
+ AsyncAuth().execute()
+ }
+
+ fun linkCheck() {
+ iMenuView.showOperHint("正在链路检测", "请稍等...")
+ AsyncLink().execute()
+ }
+
+ private inner class AsyncAuth : AsyncTask<Void, Void, AuthRetBean>() {
+ override fun doInBackground(vararg voids: Void): AuthRetBean {
+ val retBean = try {
+ AuthEpay().login()
+ } catch (ex: AuthEpayError) {
+ AuthRetBean(PublicDef.ERROR, ex.message ?: "null")
+ }
+ if (retBean.retcode == PublicDef.SUCCESS) {
+ val record = pos.getDynamicPara()
+ record!!.deviceid = retBean.deviceid
+ record.merchaccno = retBean.merchaccno
+ record.shopname = retBean.shopname
+ record.paragroupid = retBean.paragroupid
+ pos.replaceDynamicPara(record)
+
+ SPApplication.getInstance().setEpayLinking(true)
+ } else {
+ SPApplication.getInstance().setEpayLinking(false)
+ }
+ return retBean
+ }
+
+ override fun onPostExecute(retBean: AuthRetBean?) {
+ when {
+ retBean == null -> iMenuView.showOperResult("签到失败", "请求超时")
+ retBean.retcode != PublicDef.SUCCESS -> iMenuView.showOperResult("签到失败", retBean.retmsg ?: "null")
+ else -> iMenuView.showOperResult("签到成功", " ")
+ }
+ }
+ }
+
+ private inner class AsyncLink : AsyncTask<Void, Void, BaseResp>() {
+ override fun doInBackground(vararg voids: Void): BaseResp {
+ return try {
+ EpayApiImpl().linkCheck()
+ BaseResp(PublicDef.SUCCESS, "连接成功")
+ } catch (ex: HeartBeatError) {
+ BaseResp(PublicDef.ERROR, ex.message)
+ }
+ }
+
+ override fun onPostExecute(baseResp: BaseResp) {
+ SPApplication.getInstance().setEpayLinking(baseResp.retcode == PublicDef.SUCCESS)
+ iMenuView.showOperResult("检测结果", baseResp.retmsg!!)
+ }
+ }
+
+ fun doReverse() {
+ val list = pos.getTransdtlUnion(DateUtil.getNowDateNoFormat(), 0, 0, 1)
+ if (list.isEmpty()) {
+ iMenuView.showOperResult("冲正失败", "未找到消费记录")
+ return
+ }
+ val record = list[0]
+ if (record.reversalflag == ReversalFlag.AUTO ||
+ record.reversalflag == ReversalFlag.MANUAL
+ ) {
+ iMenuView.showOperResult("冲正失败", "已冲正")
+ return
+ }
+ if (record.status != PayStatus.SUC) {
+ iMenuView.showOperResult("冲正失败", "消费失败不能冲正")
+ return
+ }
+ val t1 = DateUtil.dateFormatConvertToLong(record.transdate + record.transtime)
+ val t2 = System.currentTimeMillis()
+ if (t2 - t1 > PublicDef.REVERSE_MS_GAP) {
+ iMenuView.showOperResult("冲正失败", "消费已过期")
+ return
+ }
+ val intent = Intent()
+ intent.putExtra("datetime", DateUtil.getNowDateNoFormat())
+ intent.putExtra("amount", record.payamt.toString())
+ intent.putExtra("payway", record.payway)
+ intent.setClass(iMenuView.getActivity(), ConsumeActivity::class.java)
+ iMenuView.getActivity().startActivity(intent)
+ }
+
+ fun uploadTransdtl() {
+ iMenuView.showOperHint("正在上传流水", "请稍等...")
+ UploadTransdtl().execute()
+ }
+
+ private inner class UploadTransdtl : AsyncTask<Void, Void, BaseResp>() {
+ override fun doInBackground(vararg voids: Void): BaseResp {
+ val apiInterface = EpayApiImpl()
+ var num = 0
+ try {
+ pos.getTransdtlOfflineUnconfirm().forEach {
+ apiInterface.uploadTransdtl(it)
+ it.upflag = 1
+ pos.updateTransdtlOffline(it)
+ num += 1
+ }
+ pos.getTransdtlOnlineUnconfirm().forEach {
+ apiInterface.uploadTransdtl(it)
+ it.upflag = 1
+ pos.updateTransdtlOnline(it)
+ num += 1
+ }
+ return BaseResp(PublicDef.SUCCESS, "上传共" + num + "条")
+ } catch (ex: TransdtlUploadError) {
+ return BaseResp(PublicDef.ERROR, ex.message)
+ }
+ }
+
+ override fun onPostExecute(resp: BaseResp) {
+ if (resp.retcode == PublicDef.SUCCESS) {
+ iMenuView.showOperResult("上传流水成功", resp.retmsg!!)
+ } else {
+ iMenuView.showOperResult("上传流水失败", resp.retmsg!!)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/passwd/PasswdActivity.kt b/app/src/main/java/com/supwisdom/activities/passwd/PasswdActivity.kt
new file mode 100644
index 0000000..a288b3f
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/passwd/PasswdActivity.kt
@@ -0,0 +1,189 @@
+package com.supwisdom.activities.passwd
+
+import android.os.Bundle
+import android.os.CountDownTimer
+import android.view.KeyEvent
+import com.supwisdom.R
+import com.supwisdom.activities.BaseActivity
+import com.supwisdom.activities.SPApplication
+import com.supwisdom.auxscreen.AuxScreenController
+import com.supwisdom.utils.CommonUtil
+import com.supwisdom.utils.DateUtil
+import java.util.*
+
+/**
+ ** create by zzq on 2019/7/26
+ ** @desc 商户密码修改
+ **/
+class PasswdActivity : BaseActivity() {
+ private lateinit var oldPwd: String
+ private lateinit var newPwd: String
+ private lateinit var newPwd1: String
+ private lateinit var tmpPwd: String
+ private lateinit var passwdHint: String
+ private val pos = SPApplication.getInstance().getPos()
+ private var step = 0
+ private var keyActive = true
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ this.setContentView(R.layout.activity_password)
+ }
+
+ override fun dispatchKeyEvent(event: KeyEvent): Boolean {
+ if (event.action == KeyEvent.ACTION_DOWN) {
+ if (!keyActive) {
+ return super.dispatchKeyEvent(event)
+ }
+ resetCounter(200)
+
+ if (step == 3) {
+ refresh()
+ }
+ val keyCode = event.keyCode
+ when (keyCode) {
+ KeyEvent.KEYCODE_0,
+ KeyEvent.KEYCODE_1,
+ KeyEvent.KEYCODE_2,
+ KeyEvent.KEYCODE_3,
+ KeyEvent.KEYCODE_4,
+ KeyEvent.KEYCODE_5,
+ KeyEvent.KEYCODE_6,
+ KeyEvent.KEYCODE_7,
+ KeyEvent.KEYCODE_8,
+ KeyEvent.KEYCODE_9 -> {
+ if (step == 4) {
+ step = 0
+ passwdHint = "输入原密码:"
+ }
+ tmpPwd += keyCode - KeyEvent.KEYCODE_0
+ if (tmpPwd.length == 6) {
+ when (step) {
+ 0 -> {
+ oldPwd = tmpPwd
+ tmpPwd = ""
+ if (checkOldPasswd()) {
+ step = 1
+ passwdHint = "输入新密码:"
+ AuxScreenController.getInstance().refreshContent(Arrays.asList<String>(passwdHint, " "))
+ return true
+ } else {
+ step = 4
+ }
+ return true
+ }
+ 1 -> {
+ newPwd = tmpPwd
+ tmpPwd = ""
+ step = 2
+ passwdHint = "确认新密码:"
+ AuxScreenController.getInstance().refreshContent(Arrays.asList<String>(passwdHint, " "))
+ return true
+ }
+ 2 -> {
+ newPwd1 = tmpPwd
+ step = 3
+ tmpPwd = ""
+ if (checkAndUpdate()) {
+ AuxScreenController.getInstance()
+ .refreshContent(Arrays.asList<String>("密码修改成功", " "))
+ step = 3
+ return true
+ }
+ step = 4
+ return true
+ }
+ else -> tmpPwd = ""
+ }
+ }
+ AuxScreenController.getInstance()
+ .refreshContent(Arrays.asList(passwdHint, CommonUtil.getPasswordStar(tmpPwd.length)))
+ return true
+ }
+ KeyEvent.KEYCODE_ENTER -> {
+ }
+ KeyEvent.KEYCODE_DEL -> {
+ val len = tmpPwd.length
+ when {
+ len == 1 -> {
+ tmpPwd = ""
+ AuxScreenController.getInstance()
+ .refreshContent(Arrays.asList(passwdHint, CommonUtil.getPasswordStar(tmpPwd.length)))
+ }
+ len > 1 -> {
+ tmpPwd = tmpPwd.substring(0, len - 1)
+ AuxScreenController.getInstance()
+ .refreshContent(Arrays.asList(passwdHint, CommonUtil.getPasswordStar(tmpPwd.length)))
+ }
+ else -> finish()
+ }
+ return true
+ }
+ }
+ }
+ return super.dispatchKeyEvent(event)
+ }
+
+ override fun onResume() {
+ super.onResume()
+ keyActive = true
+ refresh()
+ }
+
+ private fun refresh() {
+ step = 0
+ oldPwd = ""
+ newPwd = ""
+ newPwd1 = ""
+ tmpPwd = ""
+ passwdHint = "输入原密码"
+ AuxScreenController.getInstance().refreshTitle("商户密码修改")
+ AuxScreenController.getInstance().refreshBottom(DateUtil.getNowDateTime())
+ AuxScreenController.getInstance().refreshContent(Arrays.asList<String>(passwdHint, " "))
+ }
+
+ private fun checkOldPasswd(): Boolean {
+ if (oldPwd != pos.getConfigPara()!!.shopPwd) {
+ AuxScreenController.getInstance().refreshContent(Arrays.asList<String>("修改密码错误", "原密码错误"))
+ return false
+ }
+ return true
+ }
+
+ private fun checkAndUpdate(): Boolean {
+ if (newPwd != newPwd1) {
+ AuxScreenController.getInstance().refreshContent(Arrays.asList<String>("修改密码错误", "新密码不一致"))
+ return false
+ }
+ val record = pos.getConfigPara()
+ record!!.shopPwd = newPwd
+ if (!pos.replaceConfigPara(record)) {
+ AuxScreenController.getInstance().refreshContent(Arrays.asList<String>("修改密码错误", "密码保存失败"))
+ return false
+ }
+ return true
+ }
+
+ private var counter: ContinuePressTimer? = null
+
+ private fun resetCounter(timems: Long) {
+ if (counter == null) {
+ counter = ContinuePressTimer(timems, 100)
+ }
+ counter!!.cancel()
+ keyActive = false
+ counter!!.start()
+ }
+
+ private inner class ContinuePressTimer internal constructor(millisInFuture: Long, countDownInterval: Long) :
+ CountDownTimer(millisInFuture, countDownInterval) {
+
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ keyActive = true
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/revenue/IRevenueView.kt b/app/src/main/java/com/supwisdom/activities/revenue/IRevenueView.kt
new file mode 100644
index 0000000..74b4227
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/revenue/IRevenueView.kt
@@ -0,0 +1,13 @@
+package com.supwisdom.activities.revenue
+
+import com.supwisdom.activities.revenue.bean.RevenueAmtRetBean
+
+/**
+ ** create by zzq on 2019/7/26
+ ** @desc
+ **/
+interface IRevenueView {
+ fun showRevenueFail(msg: String)
+
+ fun showRevenueSuc(record: RevenueAmtRetBean)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/revenue/RevenueActivity.kt b/app/src/main/java/com/supwisdom/activities/revenue/RevenueActivity.kt
new file mode 100644
index 0000000..895d5b4
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/revenue/RevenueActivity.kt
@@ -0,0 +1,148 @@
+package com.supwisdom.activities.revenue
+
+import android.os.Bundle
+import android.view.KeyEvent
+import android.widget.TextView
+import com.supwisdom.R
+import com.supwisdom.activities.BaseActivity
+import com.supwisdom.activities.menu.MenuActivity
+import com.supwisdom.activities.revenue.bean.RevenueAmtRetBean
+import com.supwisdom.auxscreen.AuxScreenController
+import com.supwisdom.utils.DateUtil
+import java.util.*
+
+/**
+ ** create by zzq on 2019/7/26
+ ** @desc
+ **/
+class RevenueActivity : BaseActivity(), IRevenueView {
+ private lateinit var vContent: TextView
+ private lateinit var vSearchDate: TextView
+ private lateinit var presenter: RevenuePresenter
+ private var isSearching: Boolean = false
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ this.setContentView(R.layout.activity_revenue)
+ initView()
+ initData()
+ }
+
+ private fun initData() {
+ presenter = RevenuePresenter(this)
+ }
+
+ private fun initView() {
+ vContent = this.findViewById<TextView>(R.id.revenue_content)
+ vSearchDate = this.findViewById<TextView>(R.id.revenue_date)
+ }
+
+ private fun refresh() {
+ AuxScreenController.getInstance().refreshTitle("营业额查询")
+ AuxScreenController.getInstance().refreshBottom("F3/F4 切换日期")
+ AuxScreenController.getInstance()
+ .refreshContent(Arrays.asList<String>("查询日期:" + DateUtil.getNowDateSpecFormat(), "正在查询.", "请稍等...", " "))
+
+ val searchDate = DateUtil.getNowDateNoFormat()
+ vSearchDate.text = searchDate
+ isSearching = false
+ presenter.queryRevenue(searchDate)
+ }
+
+ override fun dispatchKeyEvent(event: KeyEvent): Boolean {
+ if (event.action == KeyEvent.ACTION_DOWN) {
+ if (isSearching) {
+ return false
+ }
+ when (event.keyCode) {
+ //case KeyEvent.KEYCODE_DPAD_UP:
+ //F2
+ KeyEvent.KEYCODE_DPAD_DOWN -> {
+ //F3
+ movePredate()
+ return true
+ }
+ KeyEvent.KEYCODE_DPAD_RIGHT -> {
+ //F4
+ moveNextDate()
+ return true
+ }
+ KeyEvent.KEYCODE_DEL -> {
+ //cancel
+ jumpActivity(MenuActivity::class.java)
+ return true
+ }
+ }//case KeyEvent.KEYCODE_ENTER:
+ //ok
+ // return true;
+ }
+ return super.dispatchKeyEvent(event)
+ }
+
+ private fun moveNextDate() {
+ val date = getSearchDate()
+ if (date >= DateUtil.getNowDateNoFormat()) {
+ return
+ }
+ isSearching = true
+ val nextdate = DateUtil.getSpecifiedDayAfter(date)
+ vSearchDate.text = nextdate
+ AuxScreenController.getInstance()
+ .refreshContent(Arrays.asList<String>("查询日期:" + convertDateToShow(nextdate), "正在查询", "请稍等...", " "))
+ presenter.queryRevenue(nextdate)
+ }
+
+ private fun movePredate() {
+ isSearching = true
+ val predate = DateUtil.getSpecifiedDayBefore(getSearchDate())
+ vSearchDate.text = predate
+ AuxScreenController.getInstance()
+ .refreshContent(Arrays.asList<String>("查询日期:" + convertDateToShow(predate), "正在查询", "请稍等...", " "))
+ presenter.queryRevenue(predate)
+ }
+
+ private fun convertDateToShow(date: String): String {
+ return date.substring(0, 4) + "/" + date.substring(4, 6) + "/" + date.substring(6)
+ }
+
+ override fun onResume() {
+ super.onResume()
+ refresh()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ }
+
+ override fun showRevenueFail(msg: String) {
+ isSearching = false
+ vContent.text = "查询失败\n原因: $msg"
+ AuxScreenController.getInstance().refreshContent(
+ Arrays.asList<String>(
+ "查询日期:" + convertDateToShow(getSearchDate()),
+ "查询失败:", "原因:$msg", " "
+ )
+ )
+ }
+
+ override fun showRevenueSuc(record: RevenueAmtRetBean) {
+ isSearching = false
+ val sb = StringBuilder("查询成功\n")
+ sb.append("有效笔数 : ").append(record.salescnt).append("笔\n")
+ .append("营业汇总 : ").append(String.format("%.02f 元", record.salesamt / 100.0f))
+ vContent.text = sb.toString()
+
+ AuxScreenController.getInstance().refreshContent(
+ Arrays.asList<String>(
+ "查询日期:" + convertDateToShow(getSearchDate()),
+ "查询成功:",
+ "有效笔数:" + record.salescnt + "笔",
+ "营业汇总:" + String.format("%.02f元", record.salesamt / 100.0f)
+ )
+ )
+ }
+
+ private fun getSearchDate(): String {
+ return vSearchDate.text.toString()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/revenue/RevenuePresenter.kt b/app/src/main/java/com/supwisdom/activities/revenue/RevenuePresenter.kt
new file mode 100644
index 0000000..4ee5bd2
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/revenue/RevenuePresenter.kt
@@ -0,0 +1,42 @@
+package com.supwisdom.activities.revenue
+
+import android.os.AsyncTask
+import com.supwisdom.activities.SPApplication
+import com.supwisdom.activities.consume.mode.ConsumeApi
+import com.supwisdom.activities.revenue.bean.RevenueAmtRetBean
+import com.supwisdom.utils.GsonUtil
+import com.supwisdom.utils.PublicDef
+import org.apache.http.HttpStatus
+
+/**
+ ** create by zzq on 2019/7/26
+ ** @desc
+ **/
+class RevenuePresenter constructor(iRevenueView: IRevenueView) {
+ private val iRevenueView = iRevenueView
+ private val pos = SPApplication.getInstance().getPos()
+
+ fun queryRevenue(date: String) {
+ AsyncRevenue().execute(pos.getConfigPara()!!.devphyid, date)
+ }
+
+ private inner class AsyncRevenue : AsyncTask<String, Void, RevenueAmtRetBean>() {
+ override fun onPostExecute(retBean: RevenueAmtRetBean) {
+ if (retBean.retcode != PublicDef.SUCCESS) {
+ iRevenueView.showRevenueFail(retBean.retmsg!!)
+ } else {
+ iRevenueView.showRevenueSuc(retBean)
+ }
+ }
+
+ override fun doInBackground(vararg strings: String): RevenueAmtRetBean {
+ val devphyid = strings[0]
+ val date = strings[1]
+ val resp = ConsumeApi().queryRevenue(devphyid, date) ?: return RevenueAmtRetBean(PublicDef.ERROR, "请求超时")
+ if (resp.retcode != HttpStatus.SC_OK) {
+ return RevenueAmtRetBean(resp.retcode, "错误码=" + resp.retcode)
+ }
+ return GsonUtil.GsonToBean(resp.retjson!!, RevenueAmtRetBean::class.java)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/revenue/bean/RevenueAmtRetBean.kt b/app/src/main/java/com/supwisdom/activities/revenue/bean/RevenueAmtRetBean.kt
new file mode 100644
index 0000000..f18160c
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/revenue/bean/RevenueAmtRetBean.kt
@@ -0,0 +1,15 @@
+package com.supwisdom.activities.revenue.bean
+
+import com.supwisdom.bean.BaseResp
+
+/**
+ ** create by zzq on 2019/7/26
+ ** @desc 营业额返回
+ **/
+class RevenueAmtRetBean constructor(retcode: Int, retmsg: String) : BaseResp(retcode, retmsg) {
+ var salesdate: String? = null
+ var salesamt: Int = 0
+ var salescnt: Int = 0
+ var managefeecnt: Int = 0
+ var managefeeamt: Int = 0
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/splash/SplashActivity.kt b/app/src/main/java/com/supwisdom/activities/splash/SplashActivity.kt
new file mode 100644
index 0000000..fd80a3a
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/splash/SplashActivity.kt
@@ -0,0 +1,84 @@
+package com.supwisdom.activities.splash
+
+import android.Manifest
+import android.content.pm.PackageManager
+import android.os.Build
+import android.os.Bundle
+import android.view.View
+import android.widget.TextView
+import com.supwisdom.R
+import com.supwisdom.activities.BaseActivity
+import com.supwisdom.activities.cardlib.CardlibActivity
+import com.supwisdom.auxscreen.AuxScreenController
+import com.supwisdom.utils.CommonUtil
+import com.supwisdom.utils.DateUtil
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class SplashActivity : BaseActivity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_splash)
+ initView()
+ }
+
+ override fun onResume() {
+ super.onResume()
+ refresh()
+ if (hasSdcardPermession()) {
+ processStart()
+ }
+ }
+
+ private fun processStart() {
+ CommonUtil.writeLinnuuxParams()
+ jumpActivity(CardlibActivity::class.java)
+ }
+
+ private fun refresh() {
+ AuxScreenController.getInstance().refreshTitle("新开普智能设备")
+ AuxScreenController.getInstance().refreshBottom(DateUtil.getNowDateTime())
+ AuxScreenController.getInstance().refreshContent(listOf<String>("欢迎使用智能设备"))
+ }
+
+ private fun initView() {
+ val tv = findViewById<View>(R.id.versionNumber) as TextView
+ tv.text = CommonUtil.getVersionName(applicationContext)
+ AuxScreenController.getInstance().open()
+ }
+
+ private val REQUEST_RETCODE = 99
+
+ private fun hasSdcardPermession(): Boolean {
+ /**
+ * 动态获取权限,Android 6.0 新特性,一些保护权限,除了要在AndroidManifest中声明权限,还要使用如下代码动态获取
+ */
+ if (Build.VERSION.SDK_INT >= 23) {
+ val permissions = arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA)
+ //验证是否许可权限
+ for (str in permissions) {
+ if (this.checkSelfPermission(str) != PackageManager.PERMISSION_GRANTED) {
+ //申请权限
+ this.requestPermissions(permissions, REQUEST_RETCODE)
+ return false
+ }
+ }
+ }
+ return true
+ }
+
+ override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults)
+ if (requestCode == REQUEST_RETCODE) {
+ for (i in grantResults.indices) {
+ if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
+ return
+ }
+ }
+ // 请求权限的结果 true代表用户同意了
+ processStart()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/syspara/SysparaActivity.kt b/app/src/main/java/com/supwisdom/activities/syspara/SysparaActivity.kt
new file mode 100644
index 0000000..f2dba5f
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/syspara/SysparaActivity.kt
@@ -0,0 +1,177 @@
+package com.supwisdom.activities.syspara
+
+import android.os.Bundle
+import android.os.CountDownTimer
+import android.view.KeyEvent
+import android.widget.ListView
+import com.supwisdom.R
+import com.supwisdom.activities.BaseActivity
+import com.supwisdom.activities.SPApplication
+import com.supwisdom.activities.menu.MenuActivity
+import com.supwisdom.activities.syspara.adapter.SysparaAdapter
+import com.supwisdom.auxscreen.AuxScreenController
+import com.supwisdom.entity.ControlParaRecord
+import com.supwisdom.utils.CommonUtil
+import java.util.*
+
+/**
+ ** create by zzq on 2019/7/26
+ ** @desc
+ **/
+class SysparaActivity : BaseActivity() {
+ private var pageno: Int = 0
+ private val PAGENUM = 3
+ private val kvMap = hashMapOf<Int, ControlParaRecord>()
+ private var index: Int = 0
+ private val pos = SPApplication.getInstance().getPos()
+ private var keyActive = true
+ private var adapter: SysparaAdapter? = null
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_syspara)
+ initView()
+ initData()
+ }
+
+ private fun initData() {
+ index = 0
+ kvMap[index++] = ControlParaRecord("软件版本>>", CommonUtil.getVersionName(applicationContext))
+ val cfgRecord = pos.getConfigPara()
+ val sysRecord = pos.getSysPara()
+ val dyRecord = pos.getDynamicPara()
+ kvMap[index++] = ControlParaRecord("物理编号>>", cfgRecord!!.devphyid!!)
+ kvMap[index++] = ControlParaRecord("服务器地址>>", cfgRecord.epayIP!!)
+ kvMap[index++] = ControlParaRecord("服务器标识>>", cfgRecord.epayUri!!)
+ kvMap[index++] = ControlParaRecord("服务器端口>>", "" + cfgRecord.epayPort)
+ kvMap[index++] =
+ ControlParaRecord("参数版本号>>", "no:" + dyRecord!!.paraverno + ",id:" + dyRecord.paragroupid)
+ kvMap[index++] = ControlParaRecord("白名单版本>>", dyRecord.cardverno!!)
+ kvMap[index++] = ControlParaRecord("通讯超时>>", String.format("%ds", CommonUtil.getCommunicateTime()))
+ if (sysRecord!!.returnFlag and 0x1 == 1) {
+ kvMap[index++] = ControlParaRecord("冲正使能>>", "启用")
+ } else {
+ kvMap[index++] = ControlParaRecord("冲正使能>>", "禁止")
+ }
+// if (sysRecord.getSocketSwitch() === 0) {
+// kvMap[index++] = ControlParaRecord("长连接使能>>", "禁止")
+// } else {
+// kvMap[index++] = ControlParaRecord("长连接使能>>", "启用")
+// }
+ if (SPApplication.getInstance().isOnline()) {
+ kvMap[index++] = ControlParaRecord("网络状态>>", "联机")
+ } else {
+ kvMap[index++] = ControlParaRecord("网络状态>>", "脱机")
+ }
+ kvMap[index++] = ControlParaRecord("成功显时间>>", String.format("%ds", sysRecord!!.sucShowtime))
+ kvMap[index++] = ControlParaRecord("失败显时间>>", String.format("%ds", sysRecord.failShowtime))
+ kvMap[index++] = ControlParaRecord("联机流水号>>", String.format("%d", pos.getTransdtlOnlineMaxSeqno()))
+ kvMap[index++] = ControlParaRecord("离线流水号>>", String.format("%d", pos.getTransdtlOfflineMaxSeqno()))
+ kvMap[index++] = ControlParaRecord(
+ "未上传流水>>", String.format(
+ "%d", pos.getTransdtlOnlineUnconfirm()
+ + pos.getTransdtlOfflineUnconfirm()
+ )
+ )
+ kvMap[index++] = ControlParaRecord("定额间隔时间(s)>>", "" + sysRecord.fixpayGap)
+ kvMap[index++] = ControlParaRecord("心跳间隔>>", "${sysRecord.heatBeat}s")
+ }
+
+ private fun initView() {
+ val vParamList = this.findViewById<ListView>(R.id.lv_param) as ListView
+ adapter = SysparaAdapter(this)
+ vParamList.adapter = adapter
+ }
+
+ override fun dispatchKeyEvent(event: KeyEvent): Boolean {
+ if (event.action == KeyEvent.ACTION_DOWN) {
+ if (!keyActive) {
+ return super.dispatchKeyEvent(event)
+ }
+ resetCounter(200)
+
+ when (event.keyCode) {
+ KeyEvent.KEYCODE_DPAD_DOWN -> {
+ //F3
+ pageno++
+ if (kvMap.size <= pageno * PAGENUM) {
+ pageno--
+ } else {
+ showPara()
+ }
+ return true
+ }
+ KeyEvent.KEYCODE_DPAD_RIGHT -> {
+ //F4
+ if (pageno > 0) {
+ pageno--
+ showPara()
+ }
+ return true
+ }
+ //case KeyEvent.KEYCODE_DPAD_UP:
+ //F2
+ KeyEvent.KEYCODE_DEL -> {
+ //cancel
+ jumpActivity(MenuActivity::class.java)
+ return true
+ }
+ }
+ }
+ return super.dispatchKeyEvent(event)
+ }
+
+ override fun onResume() {
+ super.onResume()
+ keyActive = true
+ pageno = 0
+ showPara()
+ }
+
+ private fun showPara() {
+ val paraList = ArrayList<ControlParaRecord>()
+ val auxList = ArrayList<String>()
+ for (i in 0 until PAGENUM) {
+ val index = pageno * PAGENUM + i
+ if (index < kvMap.size) {
+ auxList.add(kvMap[index]!!.paraname!!)
+ auxList.add(kvMap[index]!!.paraval!!)
+ } else {
+ auxList.add(" ")
+ auxList.add(" ")
+ }
+ }
+ for (i in 0 until kvMap.size) {
+ paraList.add(kvMap[i]!!)
+ }
+ adapter!!.setList(paraList)
+ adapter!!.notifyDataSetChanged()
+
+ AuxScreenController.getInstance().refreshTitle("设备参数查询")
+ AuxScreenController.getInstance().refreshBottom("F3/F4 切换翻页")
+ AuxScreenController.getInstance().refreshContent(auxList)
+ }
+
+ private var counter: ContinuePressTimer? = null
+
+ private fun resetCounter(timems: Long) {
+ counter?.cancel()
+ if (counter == null) {
+ counter = ContinuePressTimer(timems, 100)
+ }
+ keyActive = false
+ counter!!.start()
+ }
+
+ private inner class ContinuePressTimer internal constructor(millisInFuture: Long, countDownInterval: Long) :
+ CountDownTimer(millisInFuture, countDownInterval) {
+
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ keyActive = true
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/syspara/adapter/SysparaAdapter.kt b/app/src/main/java/com/supwisdom/activities/syspara/adapter/SysparaAdapter.kt
new file mode 100644
index 0000000..53d7b5d
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/syspara/adapter/SysparaAdapter.kt
@@ -0,0 +1,60 @@
+package com.supwisdom.activities.syspara.adapter
+
+import android.content.Context
+import android.view.View
+import android.view.ViewGroup
+import android.widget.BaseAdapter
+import android.widget.TextView
+import com.supwisdom.R
+import com.supwisdom.entity.ControlParaRecord
+
+/**
+ ** create by zzq on 2019/7/26
+ ** @desc
+ **/
+class SysparaAdapter constructor(context: Context) : BaseAdapter() {
+ private val context = context
+ private val list = ArrayList<ControlParaRecord>()
+
+ fun setList(data: List<ControlParaRecord>?) {
+ list.clear()
+ if (data != null && data.isNotEmpty()) {
+ list.addAll(data)
+ }
+ }
+
+ override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
+ val holder: Holder
+ var view = convertView
+ if (view == null) {
+ holder = Holder()
+ view = View.inflate(context, R.layout.item_syspara, null)
+ holder.paraname = view.findViewById(R.id.tv_name) as TextView
+ holder.paraval = view.findViewById(R.id.tv_value) as TextView
+
+ view.tag = holder
+ } else {
+ holder = view.tag as Holder
+ }
+ holder.paraname.text = list[position].paraname
+ holder.paraval.text = list[position].paraval
+ return view!!
+ }
+
+ override fun getItem(position: Int): ControlParaRecord {
+ return list[position]
+ }
+
+ override fun getItemId(position: Int): Long {
+ return position.toLong()
+ }
+
+ override fun getCount(): Int {
+ return list.size
+ }
+
+ private inner class Holder {
+ lateinit var paraname: TextView
+ lateinit var paraval: TextView
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/transdtl/TransdtlActivity.kt b/app/src/main/java/com/supwisdom/activities/transdtl/TransdtlActivity.kt
new file mode 100644
index 0000000..c20049a
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/transdtl/TransdtlActivity.kt
@@ -0,0 +1,223 @@
+package com.supwisdom.activities.transdtl
+
+import android.os.AsyncTask
+import android.os.Bundle
+import android.os.CountDownTimer
+import android.view.KeyEvent
+import android.widget.TextView
+import com.supwisdom.R
+import com.supwisdom.activities.BaseActivity
+import com.supwisdom.activities.SPApplication
+import com.supwisdom.activities.consume.ConsumeActivity
+import com.supwisdom.auxscreen.AuxScreenController
+import com.supwisdom.entity.PayStatus
+import com.supwisdom.entity.ReversalFlag
+import com.supwisdom.entity.TransdtlUnionRecord
+import com.supwisdom.utils.DateUtil
+import java.util.*
+
+/**
+ ** create by zzq on 2019/7/26
+ ** @desc
+ **/
+class TransdtlActivity : BaseActivity() {
+ private val pos = SPApplication.getInstance().getPos()
+ private lateinit var vSeqno: TextView
+ private lateinit var vContent: TextView
+ private var isSearching: Boolean = false
+ @Volatile
+ private var keyActive = true
+ private val MAX_SEARCH_NUM = 19
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ this.setContentView(R.layout.activity_transdtl)
+ initView()
+ }
+
+ private fun initView() {
+ vSeqno = findViewById<TextView>(R.id.transdtl_seqno)
+ vContent = findViewById<TextView>(R.id.transdtl_content)
+ }
+
+ private fun refresh() {
+ setShowSeqno(1)
+ doSearch(1)
+ }
+
+ private fun showCustomQuery(seqno: Int) {
+ AuxScreenController.getInstance().refreshTitle("流水记录查询")
+ AuxScreenController.getInstance().refreshBottom("F3/F4 切换记录")
+ AuxScreenController.getInstance()
+ .refreshContent(Arrays.asList<String>("流水索引号:$seqno", "正在查询", "请稍等...", " ", " ", " "))
+ }
+
+ override fun dispatchKeyEvent(event: KeyEvent): Boolean {
+ if (event.action == KeyEvent.ACTION_DOWN) {
+ if (isSearching || !keyActive) {
+ return super.dispatchKeyEvent(event)
+ }
+ resetCounter(200)
+
+ when (event.keyCode) {
+ KeyEvent.KEYCODE_DPAD_UP -> {
+ }
+ KeyEvent.KEYCODE_DPAD_DOWN ->
+ //F3
+ movePreSeqno()
+ KeyEvent.KEYCODE_DPAD_RIGHT ->
+ //F4
+ moveNextSeqno()
+ KeyEvent.KEYCODE_DEL ->
+ //cancel
+ jumpActivity(ConsumeActivity::class.java)
+ }//F2
+ }
+ return super.dispatchKeyEvent(event)
+ }
+
+ private fun moveNextSeqno() {
+ var seqno = getShowSeqno()
+ if (seqno > MAX_SEARCH_NUM) {
+ return
+ }
+ seqno += 1
+ setShowSeqno(seqno)
+ doSearch(seqno)
+ }
+
+ private fun movePreSeqno() {
+ var seqno = getShowSeqno()
+ if (seqno > 1) {
+ seqno -= 1
+ setShowSeqno(seqno)
+ doSearch(seqno)
+ }
+ }
+
+ private fun doSearch(seqno: Int) {
+ isSearching = true
+ showCustomQuery(seqno)
+ queryTransdtl(seqno - 1)
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ }
+
+ override fun onResume() {
+ super.onResume()
+ keyActive = true
+ refresh()
+ }
+
+ fun showTransdtlResult(record: TransdtlUnionRecord?) {
+ isSearching = false
+ if (record == null) {
+ vContent.text = "未找到消费记录"
+ AuxScreenController.getInstance().refreshContent(
+ Arrays.asList<String>(
+ "流水索引号:" + getShowSeqno(),
+ "查询失败:", "未找到消费记录", " ", " ", " "
+ )
+ )
+ } else {
+ val transdatetime = StringBuilder()
+ transdatetime.append(record.transdate!!.substring(0, 4)).append("-")
+ .append(record.transdate!!.substring(4, 6)).append("-")
+ .append(record.transdate!!.substring(6)).append(" ")
+ .append(record.transtime!!.substring(0, 2)).append(":")
+ .append(record.transtime!!.substring(2, 4)).append(":")
+ .append(record.transtime!!.substring(4))
+ val result = if (record.status == PayStatus.SUC) {
+ if (record.reversalflag == ReversalFlag.AUTO ||
+ record.reversalflag == ReversalFlag.MANUAL
+ ) {
+ "已退款"
+ } else {
+ "消费成功"
+ }
+ } else {
+ if (record.reversalflag == ReversalFlag.AUTO ||
+ record.reversalflag == ReversalFlag.MANUAL
+ ) {
+ "冲正失败"
+ } else {
+ "消费失败"
+ }
+ }
+ val payWay = if (record.payway == "code") {
+ "二维码"
+ } else {
+ "市民卡"
+ }
+ val sb = StringBuilder("查询成功 \n")
+ sb.append("姓名: ").append(record.username).append("\n")
+ .append("支付方式: ").append(payWay).append("\n")
+ .append(String.format("支付金额: %.02f元", record.payamt / 100.0f)).append("\n")
+ .append("支付时间: ").append(transdatetime.toString()).append("\n")
+ .append("支付结果: ").append(result)
+ vContent.text = sb.toString()
+
+ AuxScreenController.getInstance().refreshContent(
+ Arrays.asList(
+ "时间:$transdatetime",
+ "姓名:" + record.username,
+ String.format("金额:%.02f元", record.payamt / 100.0f),
+ "方式:$payWay", "结果:$result"
+ )
+ )
+ }
+ }
+
+ private fun getShowSeqno(): Int {
+ return Integer.parseInt(vSeqno.text.toString())
+ }
+
+ private fun setShowSeqno(seqno: Int) {
+ vSeqno.text = seqno.toString()
+ }
+
+ private fun queryTransdtl(seqno: Int) {
+ AsyncTransdtl().execute(seqno)
+ }
+
+ private inner class AsyncTransdtl : AsyncTask<Int, Void, TransdtlUnionRecord?>() {
+ override fun onPostExecute(record: TransdtlUnionRecord?) {
+ showTransdtlResult(record)
+ }
+
+ override fun doInBackground(vararg integers: Int?): TransdtlUnionRecord? {
+ val searchSeqno = integers[0]!!
+ val list = pos.getTransdtlUnion(DateUtil.getNowDateNoFormat(), searchSeqno, 1, 1)
+ return if (list.isNotEmpty()) {
+ list[0]
+ } else {
+ null
+ }
+ }
+ }
+
+ private var counter: ContinuePressTimer? = null
+
+ private fun resetCounter(timems: Long) {
+ counter?.cancel()
+ if (counter == null) {
+ counter = ContinuePressTimer(timems, 100)
+ }
+ keyActive = false
+ counter!!.start()
+ }
+
+ private inner class ContinuePressTimer internal constructor(millisInFuture: Long, countDownInterval: Long) :
+ CountDownTimer(millisInFuture, countDownInterval) {
+
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ keyActive = true
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/unregister/UnregisterActivity.kt b/app/src/main/java/com/supwisdom/activities/unregister/UnregisterActivity.kt
new file mode 100644
index 0000000..14e8c6f
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/unregister/UnregisterActivity.kt
@@ -0,0 +1,60 @@
+package com.supwisdom.activities.unregister
+
+import android.content.Intent
+import android.os.Bundle
+import android.view.KeyEvent
+import android.widget.TextView
+import com.supwisdom.R
+import com.supwisdom.activities.BaseActivity
+import com.supwisdom.activities.init.InitActivity
+import com.supwisdom.auxscreen.AuxScreenController
+import com.supwisdom.utils.DateUtil
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+class UnregisterActivity:BaseActivity() {
+ private lateinit var vErrmsg: TextView
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ this.setContentView(R.layout.activity_unregister)
+
+ initView()
+ }
+
+ private fun initView() {
+ val backBtn = this.findViewById(R.id.tv_back) as TextView
+ backBtn.setOnClickListener {
+ jumpActivity(InitActivity::class.java)
+ }
+ vErrmsg = this.findViewById(R.id.tv_errmsg) as TextView
+ }
+
+ override fun dispatchKeyEvent(event: KeyEvent?): Boolean {
+ return super.dispatchKeyEvent(event)
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ }
+
+ override fun onResume() {
+ super.onResume()
+ val errmsg = intent.getStringExtra("errmsg")
+ refresh(errmsg)
+ vErrmsg.text = errmsg
+ }
+
+ private fun refresh(errmsg: String) {
+ AuxScreenController.getInstance().refreshTitle("设备注册状态")
+ AuxScreenController.getInstance().refreshBottom(DateUtil.getNowDateTime())
+ AuxScreenController.getInstance().refreshContent(listOf("设备未注册", errmsg))
+ }
+
+ override fun onNewIntent(intent: Intent) {
+ super.onNewIntent(intent)
+ this.intent.putExtra("errmsg", intent.getStringExtra("errmsg"))
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/upgrade/UpgradeActivity.kt b/app/src/main/java/com/supwisdom/activities/upgrade/UpgradeActivity.kt
new file mode 100644
index 0000000..0640dc4
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/upgrade/UpgradeActivity.kt
@@ -0,0 +1,179 @@
+package com.supwisdom.activities.upgrade
+
+import android.content.Intent
+import android.net.Uri
+import android.os.Build
+import android.os.Bundle
+import android.os.CountDownTimer
+import android.support.v4.content.FileProvider
+import android.view.KeyEvent
+import android.widget.Button
+import android.widget.TextView
+import com.supwisdom.R
+import com.supwisdom.activities.BaseActivity
+import com.supwisdom.auxscreen.AuxScreenController
+import com.supwisdom.activities.upgrade.mode.EpayUpgradeApi
+import com.supwisdom.utils.CommonUtil
+import com.supwisdom.utils.DateUtil
+import com.supwisdom.utils.ThreadPool
+import java.io.File
+import java.util.*
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+@Suppress("DEPRECATION")
+class UpgradeActivity : BaseActivity() {
+ private lateinit var vResult: TextView
+ private lateinit var vUpgradeMsg: TextView
+ private lateinit var vServerUrl: TextView
+ private lateinit var vPosOldVersion: TextView
+ private lateinit var vPosVersion: TextView
+ private var isUpgrading = false
+ @Volatile
+ private var keyActive = true
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_upgrade)
+ initView()
+ initData()
+ }
+
+ private fun initData() {
+ vPosOldVersion.text = CommonUtil.getVersionName(this)
+ }
+
+ private fun initView() {
+ vResult = this.findViewById(R.id.tv_result) as TextView
+ vUpgradeMsg = this.findViewById(R.id.tv_upgrade_msg) as TextView
+
+ vServerUrl = this.findViewById(R.id.tv_server_url) as TextView
+ vPosOldVersion = this.findViewById(R.id.tv_old_version) as TextView
+ vPosVersion = this.findViewById(R.id.tv_pos_version) as TextView
+ this.findViewById<Button>(R.id.tv_upgrade).setOnClickListener {
+ asyncUpgrade()
+ }
+ }
+
+ override fun dispatchKeyEvent(event: KeyEvent): Boolean {
+ if (event.action == KeyEvent.ACTION_DOWN) {
+ if (isUpgrading || !keyActive) {
+ return super.dispatchKeyEvent(event)
+ }
+ resetCounter(200)
+
+ when (event.keyCode) {
+ KeyEvent.KEYCODE_DEL ->
+ //cancel
+ finish()
+ KeyEvent.KEYCODE_ENTER -> {
+ //ok
+ isUpgrading = true
+ AuxScreenController.getInstance().refreshContent(Arrays.asList<String>("正在升级", "请稍等..."))
+ asyncUpgrade()
+ }
+ }
+ }
+ return super.dispatchKeyEvent(event)
+ }
+
+ override fun onResume() {
+ super.onResume()
+ keyActive = true
+ refresh()
+ }
+
+ private fun refresh() {
+ isUpgrading = false
+ AuxScreenController.getInstance().refreshTitle("应用在线升级")
+ AuxScreenController.getInstance().refreshBottom(DateUtil.getNowDateTime())
+ AuxScreenController.getInstance().refreshContent(
+ Arrays.asList(
+ "当前版本>>", CommonUtil.getVersionName(applicationContext),
+ "确认 --应用升级", "取消 --退出"
+ )
+ )
+ }
+
+ private val upgradeApiCallback = object : EpayUpgradeApi.CallbackInterface {
+ override fun progresss(pro: Int) {
+ runOnUiThread {
+ vUpgradeMsg.text = "$pro%"
+ vUpgradeMsg.setTextColor(resources.getColor(R.color.black))
+ AuxScreenController.getInstance().refreshContent(Arrays.asList<String>("正在下载", "$pro%"))
+ }
+ }
+
+ override fun success(filepath: String) {
+ runOnUiThread {
+ isUpgrading = false
+ vUpgradeMsg.text = "下载成功"
+ vUpgradeMsg.setTextColor(resources.getColor(R.color.black))
+ AuxScreenController.getInstance().refreshContent(Arrays.asList<String>("下载应用成功", "请在大屏确认升级"))
+ val apkFile = File(filepath)
+ installAPK(apkFile)
+ }
+ }
+
+ override fun failed(errmsg: String) {
+ runOnUiThread {
+ isUpgrading = false
+ vUpgradeMsg.text = errmsg
+ vUpgradeMsg.setTextColor(resources.getColor(R.color.cl_red))
+ AuxScreenController.getInstance().refreshContent(Arrays.asList<String>("升级失败", "原因:", errmsg))
+ }
+ }
+ }
+
+ /**
+ * 开始下载apk
+ */
+ fun asyncUpgrade() {
+ ThreadPool.getDownloadPool().execute(Runnable {
+ EpayUpgradeApi(upgradeApiCallback).upgrade(CommonUtil.getVersionName(this))
+ })
+ }
+
+ /**
+ * 安装apk
+ */
+ private fun installAPK(apkFile: File) {
+ val intent = Intent(Intent.ACTION_VIEW)
+ intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ intent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
+ val contentUri = FileProvider.getUriForFile(
+ this, "com.supwisdom.charge.fileprovider", apkFile
+ )
+ intent.setDataAndType(contentUri, "application/vnd.android.package-archive")
+ } else {
+ intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive")
+ }
+ startActivity(intent)
+ }
+
+ private var counter: ContinuePressTimer? = null
+
+ private fun resetCounter(timems: Long) {
+ if (counter == null) {
+ counter = ContinuePressTimer(timems, 100)
+ }
+ counter!!.cancel()
+ keyActive = false
+ counter!!.start()
+ }
+
+ private inner class ContinuePressTimer internal constructor(millisInFuture: Long, countDownInterval: Long) :
+ CountDownTimer(millisInFuture, countDownInterval) {
+
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ keyActive = true
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/activities/upgrade/mode/EpayUpgradeApi.kt b/app/src/main/java/com/supwisdom/activities/upgrade/mode/EpayUpgradeApi.kt
new file mode 100644
index 0000000..1545002
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/activities/upgrade/mode/EpayUpgradeApi.kt
@@ -0,0 +1,177 @@
+package com.supwisdom.activities.upgrade.mode
+
+import android.text.TextUtils
+import com.supwisdom.activities.YktSession
+import com.supwisdom.bean.UpgradeInfoRetBean
+import com.supwisdom.okhttp.WebParams
+import com.supwisdom.utils.*
+import org.apache.http.HttpStatus
+import java.io.File
+import java.io.FileInputStream
+import java.io.FileOutputStream
+import java.net.HttpURLConnection
+import java.net.URL
+import java.util.*
+
+/**
+ * @author zzq
+ * @date 2019/4/9
+ * @desc 在线升级
+ */
+class EpayUpgradeApi constructor(callbackInterface: CallbackInterface) {
+ private val TIMEOUT = 5 * 1000// 超时
+ private val callbackInterface = callbackInterface
+ private val POSID = "chargepos"
+
+ fun upgrade(versionName: String) {
+ val resp = getAppVersion()
+ if (resp.retcode != PublicDef.SUCCESS) {
+ callbackInterface.failed(resp.retmsg!!)
+ return
+ }
+ val updateFile = FileUtil.getUpdateFile("$POSID.zip")
+ if (updateFile == null) {
+ callbackInterface.failed("创建本地文件失败")
+ return
+ }
+ if (!downloadUpdateFile(resp.packageurl!!, updateFile, resp.packageversion!!)) {
+ return
+ }
+ parseDownloadFile(updateFile.absolutePath, resp.packageversion!!)
+ }
+
+ private fun downloadUpdateFile(downUrl: String, file: File, versionName: String): Boolean {
+// val downStep = 1// 提示step
+ var downStep = 0// 提示step
+ val totalSize: Int// 文件总大小
+ var downloadCount = 0// 已经下载好的大小
+ var updateCount = 0// 已经上传的文件大小
+ try {
+ val url = URL(downUrl)
+ val urlConnection = url.openConnection() as HttpURLConnection
+ urlConnection.connectTimeout = TIMEOUT
+ urlConnection.readTimeout = TIMEOUT
+ urlConnection.doOutput = true
+ urlConnection.doInput = true
+ urlConnection.useCaches = false
+ // setting serialized
+ urlConnection.setRequestProperty("Content-type", "application/x-java-serialized-object")
+ //default is GET
+ urlConnection.requestMethod = "POST"
+ urlConnection.setRequestProperty("Charsert", "UTF-8")
+ urlConnection.setRequestProperty("connection", "Keep-Alive")
+ urlConnection.addRequestProperty("version", versionName)
+
+ urlConnection.addRequestProperty("username", "supwisdom")
+ urlConnection.addRequestProperty("password", "supwisdom")
+ urlConnection.addRequestProperty("filename", "$POSID.apk")
+
+ //connect to server (tcp)
+ urlConnection.connect()
+ // 获取下载文件的size
+ totalSize = urlConnection.contentLength
+ if (urlConnection.responseCode != HttpStatus.SC_OK) {
+ urlConnection.disconnect()
+ callbackInterface.failed("下载文件失败:错误码=${urlConnection.responseCode}")
+ return false
+ }
+ val inputStream = urlConnection.inputStream
+ val outputStream = FileOutputStream(file, false)// 文件存在则覆盖掉
+ val buffer = ByteArray(1024)
+ while (true) {
+ val readSize = inputStream.read(buffer)
+ if (readSize < 0) {
+ break
+ }
+ outputStream.write(buffer, 0, readSize)
+ downloadCount += readSize// 实时获取下载到的大小
+
+ val progress = downloadCount * 1.0 / totalSize
+ val pro = Math.round(progress * 100).toInt()
+ if (pro - downStep >= 1) {
+ downStep++
+ CommonUtil.doSleep(100)
+ callbackInterface.progresss(pro)
+ }
+ }
+ urlConnection.disconnect()
+ inputStream.close()
+ outputStream.close()
+ return true
+ } catch (e: Exception) {
+ e.printStackTrace()
+ callbackInterface.failed("下载文件异常:${e.message}")
+ return false
+ }
+ }
+
+ private fun parseDownloadFile(zipFilePath: String, versionName: String): Boolean {
+ try {
+ val index = zipFilePath.lastIndexOf("/")
+ val unZipFilePath = zipFilePath.substring(0, index)
+ ZipUtil.unzip(zipFilePath, unZipFilePath, false)
+ val apkFile = File("$unZipFilePath/$POSID.apk")
+ if (!apkFile.exists()) {
+ callbackInterface.failed("未找到文件$POSID.apk")
+ return false
+ }
+
+ val fileHash256 = CryptUtil.HASH256(FileInputStream(apkFile), "nzoqPYMIu91VViA/mEIG5FtJXi8=")
+ if (fileHash256 == null) {
+ callbackInterface.failed("计算文件校验数据错误")
+ return false
+ }
+ val signFile = FileInputStream("$unZipFilePath/hash256.sign")
+ val buffer = ByteArray(1024)
+ val length = signFile.read(buffer, 0, buffer.size)
+ if (length < 0) {
+ callbackInterface.failed("读取校验文件失败")
+ return false
+ }
+ signFile.close()
+ val signHash256 = String(Arrays.copyOfRange(buffer, 0, length))
+ if (!fileHash256.equals(signHash256, ignoreCase = true)) {
+ callbackInterface.failed("文件校验错误")
+ return false
+ }
+ callbackInterface.success("$unZipFilePath/$POSID.apk")
+ return true
+ } catch (e: Exception) {
+ e.printStackTrace()
+ callbackInterface.failed("文件校验异常:${e.message}")
+ return false
+ }
+ }
+
+ private fun getAppVersion(): UpgradeInfoRetBean {
+ val params = WebParams()
+ params.setParameter("version_package_id", "com.supwisdom.$POSID")
+ .setParameter("sourcetype", "pos")
+
+ val signdata = params.getParameterString("version_package_id")
+ val resp = YktSession.getInstance().sendYktRequestPost("/common/apk/version", signdata, params)
+ ?: return UpgradeInfoRetBean(PublicDef.ERROR, "获取版本号网络超时")
+ if (resp.retcode != HttpStatus.SC_OK) {
+ return UpgradeInfoRetBean(resp.retcode, resp.retmsg!!)
+ }
+ return try {
+ val bean = GsonUtil.GsonToBean(resp.retjson!!, UpgradeInfoRetBean::class.java)
+ when {
+ TextUtils.isEmpty(bean.packageversion) -> UpgradeInfoRetBean(PublicDef.ERROR, "获取版本号为空")
+ TextUtils.isEmpty(bean.packageurl) -> UpgradeInfoRetBean(PublicDef.ERROR, "获取升级链接为空")
+ else -> bean
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ UpgradeInfoRetBean(PublicDef.ERROR, "获取版本号JSON错误:${e.message}")
+ }
+ }
+
+ interface CallbackInterface {
+ fun progresss(pro: Int)
+
+ fun success(filepath: String)
+
+ fun failed(errmsg: String)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/bean/AuthJwtRetBean.kt b/app/src/main/java/com/supwisdom/bean/AuthJwtRetBean.kt
new file mode 100644
index 0000000..0514140
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/bean/AuthJwtRetBean.kt
@@ -0,0 +1,10 @@
+package com.supwisdom.bean
+
+/**
+ ** create by zzq on 2019/7/29
+ ** @desc
+ **/
+class AuthJwtRetBean : BaseResp() {
+ var jwt: String? = null
+ var expiredAt: String? = null //过期时间 UTC格式
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/bean/AuthRetBean.kt b/app/src/main/java/com/supwisdom/bean/AuthRetBean.kt
new file mode 100644
index 0000000..b488ac6
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/bean/AuthRetBean.kt
@@ -0,0 +1,16 @@
+package com.supwisdom.bean
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+class AuthRetBean constructor(retcode: Int, retmsg: String) : BaseResp(retcode, retmsg) {
+ var deviceid: Int = 0
+ var merchaccno: Int = 0
+ var shopname: String? = null
+ var onlineseqno: Int = 0
+ var offlineseqno: Int = 0
+ var paraverno: Int = 0
+ var paragroupid: Int = 0
+ var cardverno: String? = null
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/bean/AuthTokenRetBean.kt b/app/src/main/java/com/supwisdom/bean/AuthTokenRetBean.kt
new file mode 100644
index 0000000..440ad89
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/bean/AuthTokenRetBean.kt
@@ -0,0 +1,10 @@
+package com.supwisdom.bean
+
+/**
+ ** create by zzq on 2019/7/29
+ ** @desc
+ **/
+class AuthTokenRetBean : BaseResp() {
+ var token: String? = null
+ var timestamp: String? = null
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/bean/BaseResp.kt b/app/src/main/java/com/supwisdom/bean/BaseResp.kt
new file mode 100644
index 0000000..ac5fb29
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/bean/BaseResp.kt
@@ -0,0 +1,17 @@
+package com.supwisdom.bean
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+open class BaseResp {
+ constructor(retcode: Int, retmsg: String?) {
+ this.retcode = retcode
+ this.retmsg = retmsg
+ }
+
+ constructor()
+
+ var retcode: Int = 0
+ var retmsg: String? = null
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/bean/HeartBeatRetBean.kt b/app/src/main/java/com/supwisdom/bean/HeartBeatRetBean.kt
new file mode 100644
index 0000000..2c68992
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/bean/HeartBeatRetBean.kt
@@ -0,0 +1,12 @@
+package com.supwisdom.bean
+
+/**
+ ** create by zzq on 2019/7/26
+ ** @desc
+ **/
+class HeartBeatRetBean : BaseResp() {
+ var systime: String? = null
+ var paragroupid: Int = 0
+ var paraverno: Int = 0
+ var cardverno: String? = null
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/bean/SystemParaItemBean.kt b/app/src/main/java/com/supwisdom/bean/SystemParaItemBean.kt
new file mode 100644
index 0000000..09beb47
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/bean/SystemParaItemBean.kt
@@ -0,0 +1,10 @@
+package com.supwisdom.bean
+
+/**
+ ** create by zzq on 2019/7/26
+ ** @desc
+ **/
+class SystemParaItemBean {
+ var paraname: String? = null
+ var paraval: String? = null
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/bean/SystemParaRetBean.kt b/app/src/main/java/com/supwisdom/bean/SystemParaRetBean.kt
new file mode 100644
index 0000000..16ed4e0
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/bean/SystemParaRetBean.kt
@@ -0,0 +1,11 @@
+package com.supwisdom.bean
+
+/**
+ ** create by zzq on 2019/7/26
+ ** @desc
+ **/
+class SystemParaRetBean : BaseResp() {
+ var paragroupid: Int = 0
+ var paraverno: Int = 0
+ var syspara: List<SystemParaItemBean>? = null
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/bean/TransdtlRetBean.kt b/app/src/main/java/com/supwisdom/bean/TransdtlRetBean.kt
new file mode 100644
index 0000000..2aded07
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/bean/TransdtlRetBean.kt
@@ -0,0 +1,9 @@
+package com.supwisdom.bean
+
+/**
+ ** create by zzq on 2019/7/26
+ ** @desc
+ **/
+class TransdtlRetBean : BaseResp() {
+ var termseqno: Int = 0
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/bean/UpgradeInfoRetBean.kt b/app/src/main/java/com/supwisdom/bean/UpgradeInfoRetBean.kt
new file mode 100644
index 0000000..d32ccff
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/bean/UpgradeInfoRetBean.kt
@@ -0,0 +1,10 @@
+package com.supwisdom.bean
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+class UpgradeInfoRetBean constructor(retcode: Int, retmsg: String) : BaseResp(retcode, retmsg) {
+ var packageversion: String? = null
+ var packageurl: String? = null
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/bean/WhiteListItemBean.kt b/app/src/main/java/com/supwisdom/bean/WhiteListItemBean.kt
new file mode 100644
index 0000000..398667c
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/bean/WhiteListItemBean.kt
@@ -0,0 +1,12 @@
+package com.supwisdom.bean
+
+/**
+ ** create by zzq on 2019/7/26
+ ** @desc
+ **/
+class WhiteListItemBean {
+ var cardphyid: String? = null
+ var cardno: String? = null
+ var flag: Int = 0
+ var balance: Int = 0
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/bean/WhiteListRetBean.kt b/app/src/main/java/com/supwisdom/bean/WhiteListRetBean.kt
new file mode 100644
index 0000000..d0a4d63
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/bean/WhiteListRetBean.kt
@@ -0,0 +1,11 @@
+package com.supwisdom.bean
+
+/**
+ ** create by zzq on 2019/7/26
+ ** @desc
+ **/
+class WhiteListRetBean : BaseResp() {
+ var cardverno: String? = null
+ var count: Int = 0
+ var whitelist: List<WhiteListItemBean>? = null
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/db/BeanPropEnum.kt b/app/src/main/java/com/supwisdom/db/BeanPropEnum.kt
new file mode 100644
index 0000000..8eb7e66
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/db/BeanPropEnum.kt
@@ -0,0 +1,110 @@
+package com.supwisdom.db
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+object BeanPropEnum {
+ enum class Syspara {
+ id,
+ returnFlag,
+ heatBeat,
+ offlineEnable,
+ maxOfflineDays,
+ mngpasswd,
+ fixpayGap,
+ consumeShowtime,
+ consumeFailShowtime,
+ commTime
+ }
+
+ enum class ConfigPara {
+ id,
+ mode,
+ devphyid,
+ psamno,
+ epayIP,
+ epayPort,
+ epayUri,
+ managePwd,
+ initOK
+ }
+
+ enum class DynamicPara {
+ id,
+ appid,
+ appsecret,
+ deviceid,
+ merchaccno,
+ shopname,
+ onlineseqno,
+ offlineseqno,
+ paraverno,
+ paragroupid,
+ cardverno,
+ jwt,
+ token
+ }
+
+ enum class ControlPara {
+ paraname,
+ paraval
+ }
+
+ enum class TransdtlOnline {
+ devphyid,
+ transdate,
+ transtime,
+ devseqno,
+ cardno,
+ cardphyid,
+ qrcode,
+ transtype,
+ payamt,
+ extraamt,
+ managefeetype,
+ username,
+ balance,
+ billno,
+ reversalflag,
+ reversalbillno,
+ status,
+ upflag
+ }
+
+ enum class TransdtlOffline {
+ devphyid,
+ transdate,
+ transtime,
+ devseqno,
+ cardno,
+ cardphyid,
+ payamt,
+ extraamt,
+ reversalflag,
+ reversalseqno,
+ reversaltransdate,
+ reversaltranstime,
+ status,
+ upflag
+ }
+
+ enum class WhiteList {
+ cardphyid,
+ cardno,
+ flag,
+ balance
+ }
+
+ enum class TransdtlUnion {
+ username,
+ transdate,
+ transtime,
+ devseqno,
+ payway,
+ reversalflag,
+ payamt,
+ status,
+ upflag
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/db/ConfigParaDao.kt b/app/src/main/java/com/supwisdom/db/ConfigParaDao.kt
new file mode 100644
index 0000000..cce42b8
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/db/ConfigParaDao.kt
@@ -0,0 +1,118 @@
+package com.supwisdom.db
+
+import android.content.ContentValues
+import android.content.Context
+import android.database.Cursor
+import com.supwisdom.entity.ConfigParaRecord
+import java.util.concurrent.locks.Lock
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+class ConfigParaDao constructor(context: Context) {
+ private val INDEX = "1"
+ private val TABLE = DBLocalHelper.TABLE_NAME_CONFIGPARA
+ private val dbHelper = DBLocalHelper.getInstance(context)
+
+ fun getLock(): Lock {
+ return dbHelper.getLock()
+ }
+
+ fun replace(record: ConfigParaRecord): Boolean {
+ val db = dbHelper.readableDatabase
+ val values = getContentValues(record)
+ try {
+ db.beginTransaction()
+ if (db.replace(TABLE, null, values) > 0) {
+ db.setTransactionSuccessful()
+ return true
+ }
+ } finally {
+ db.endTransaction()
+ }
+ return false
+ }
+
+ fun update(record: ConfigParaRecord): Boolean {
+ val db = dbHelper.writableDatabase
+ val values = getContentValues(record)
+ try {
+ db.beginTransaction()
+ if (db.update(
+ TABLE,
+ values,
+ BeanPropEnum.ConfigPara.id.toString() + "=?",
+ arrayOf(INDEX)
+ ) > 0
+ ) {
+ db.setTransactionSuccessful()
+ return true
+ }
+ } finally {
+ db.endTransaction()
+ }
+ return false
+ }
+
+ fun get(): ConfigParaRecord? {
+ val db = dbHelper.readableDatabase
+ var cursor: Cursor? = null
+ try {
+ cursor = db.query(
+ TABLE, null, BeanPropEnum.ConfigPara.id.toString() + "=?",
+ arrayOf(INDEX), null, null, null
+ )
+ if (cursor != null && cursor.moveToNext()) {
+ return getRecord(cursor)
+ }
+ } finally {
+ cursor?.close()
+ }
+ return null
+ }
+
+ private fun getRecord(cursor: Cursor): ConfigParaRecord {
+ val record = ConfigParaRecord()
+ record.mode = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.ConfigPara.mode.toString()))
+ record.devphyid = cursor.getString(cursor.getColumnIndex(BeanPropEnum.ConfigPara.devphyid.toString()))
+ record.epayIP = cursor.getString(cursor.getColumnIndex(BeanPropEnum.ConfigPara.epayIP.toString()))
+ record.epayPort = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.ConfigPara.epayPort.toString()))
+ record.epayUri = cursor.getString(cursor.getColumnIndex(BeanPropEnum.ConfigPara.epayUri.toString()))
+ record.shopPwd = cursor.getString(cursor.getColumnIndex(BeanPropEnum.ConfigPara.managePwd.toString()))
+ val value = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.ConfigPara.initOK.toString()))
+ record.initOK = value == 1
+ return record
+ }
+
+ fun clear(): Boolean {
+ val db = dbHelper.writableDatabase
+ try {
+ db.beginTransaction()
+ if (db.delete(TABLE, null, null) < 0) {
+ return false
+ }
+ db.setTransactionSuccessful()
+ return true
+ } finally {
+ db.endTransaction()
+ }
+ }
+
+ private fun getContentValues(record: ConfigParaRecord): ContentValues {
+ val values = ContentValues()
+ values.put(BeanPropEnum.ConfigPara.id.toString(), INDEX)
+ values.put(BeanPropEnum.ConfigPara.mode.toString(), record.mode)
+ values.put(BeanPropEnum.ConfigPara.devphyid.toString(), record.devphyid)
+ values.put(BeanPropEnum.ConfigPara.epayIP.toString(), record.epayIP)
+ values.put(BeanPropEnum.ConfigPara.epayPort.toString(), record.epayPort)
+ values.put(BeanPropEnum.ConfigPara.epayUri.toString(), record.epayUri)
+ values.put(BeanPropEnum.ConfigPara.managePwd.toString(), record.shopPwd)
+ if (record.initOK) {
+ values.put(BeanPropEnum.ConfigPara.initOK.toString(), 1)
+ } else {
+ values.put(BeanPropEnum.ConfigPara.initOK.toString(), 0)
+ }
+ return values
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/db/ControlParaDao.kt b/app/src/main/java/com/supwisdom/db/ControlParaDao.kt
new file mode 100644
index 0000000..d683d9c
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/db/ControlParaDao.kt
@@ -0,0 +1,118 @@
+package com.supwisdom.db
+
+import android.content.ContentValues
+import android.content.Context
+import android.database.Cursor
+import com.supwisdom.entity.ControlParaRecord
+import java.util.concurrent.locks.Lock
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+class ControlParaDao constructor(context: Context) {
+ private val dbHelper = DBParaHelper.getInstance(context)
+ private val TABLE = DBParaHelper.TABLE_NAME_CONTROLPARA
+
+ fun getLock(): Lock {
+ return dbHelper.getLock()
+ }
+
+ fun replace(record: ControlParaRecord): Boolean {
+ val db = dbHelper.readableDatabase
+ val values = getContentValues(record)
+ try {
+ db.beginTransaction()
+ if (db.replace(TABLE, null, values) > 0) {
+ return false
+ }
+ db.setTransactionSuccessful()
+ return true
+ } finally {
+ db.endTransaction()
+ }
+ }
+
+ fun replace(paraname: String, paraval: String): Boolean {
+ val db = dbHelper.readableDatabase
+ val values = ContentValues()
+ values.put(BeanPropEnum.ControlPara.paraname.toString(), paraname)
+ values.put(BeanPropEnum.ControlPara.paraval.toString(), paraval)
+ try {
+ db.beginTransaction()
+ if (db.replace(TABLE, null, values) < 0) {
+ return false
+ }
+ db.setTransactionSuccessful()
+ return true
+ } finally {
+ db.endTransaction()
+ }
+ }
+
+ fun update(record: ControlParaRecord): Boolean {
+ val db = dbHelper.writableDatabase
+ val values = getContentValues(record)
+ try {
+ db.beginTransaction()
+ if (db.update(
+ TABLE,
+ values,
+ BeanPropEnum.ControlPara.paraname.toString() + "=?",
+ arrayOf(record.paraname)
+ ) > 0
+ ) {
+ db.setTransactionSuccessful()
+ return true
+ }
+ } finally {
+ db.endTransaction()
+ }
+ return false
+ }
+
+ fun get(paraname: String): ControlParaRecord? {
+ val db = dbHelper.readableDatabase
+ var cursor: Cursor? = null
+ try {
+ cursor = db.query(
+ TABLE, null, BeanPropEnum.ControlPara.paraname.toString() + "=?",
+ arrayOf(paraname), null, null, null
+ )
+ if (cursor != null && cursor.moveToNext()) {
+ return getRecord(cursor)
+ }
+ } finally {
+ cursor?.close()
+ }
+ return null
+ }
+
+ fun clear(): Boolean {
+ val db = dbHelper.writableDatabase
+ try {
+ db.beginTransaction()
+ if (db.delete(TABLE, null, null) < 0) {
+ return false
+ }
+ db.setTransactionSuccessful()
+ return true
+ } finally {
+ db.endTransaction()
+ }
+ }
+
+ private fun getRecord(cursor: Cursor): ControlParaRecord {
+ val record = ControlParaRecord()
+ record.paraname = cursor.getString(cursor.getColumnIndex(BeanPropEnum.ControlPara.paraname.toString()))
+ record.paraval = cursor.getString(cursor.getColumnIndex(BeanPropEnum.ControlPara.paraval.toString()))
+ return record
+ }
+
+ private fun getContentValues(record: ControlParaRecord): ContentValues {
+ val values = ContentValues()
+ values.put(BeanPropEnum.ControlPara.paraname.toString(), record.paraname)
+ values.put(BeanPropEnum.ControlPara.paraval.toString(), record.paraval)
+ return values
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/db/DBLocalHelper.kt b/app/src/main/java/com/supwisdom/db/DBLocalHelper.kt
new file mode 100644
index 0000000..a57dc71
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/db/DBLocalHelper.kt
@@ -0,0 +1,62 @@
+package com.supwisdom.db
+
+import android.content.Context
+import android.database.sqlite.SQLiteDatabase
+import android.database.sqlite.SQLiteOpenHelper
+import java.util.concurrent.locks.Lock
+import java.util.concurrent.locks.ReentrantLock
+
+/**
+ ** create by zzq on 2019/7/31
+ ** @desc 本地配置文件
+ **/
+class DBLocalHelper private constructor(context: Context) : SQLiteOpenHelper(context, DB_NAME, null, VERSION) {
+ companion object {
+ private val DB_NAME = "db_local_config"
+ private val VERSION = 1
+ private var instance: DBLocalHelper? = null
+
+ const val TABLE_NAME_CONFIGPARA = "tb_configpara"
+
+ fun getInstance(context: Context): DBLocalHelper {
+ if (null == instance) {
+ synchronized(DBLocalHelper::class.java) {
+ if (null == instance) {
+ instance = DBLocalHelper(context)
+ }
+ }
+ }
+ return instance!!
+ }
+ }
+
+ /**
+ * SQL for create table
+ */
+ private val CREATE_TABLE_NAME_CONFIGPARA = ("create table IF NOT EXISTS "
+ + TABLE_NAME_CONFIGPARA + " ( "
+ + BeanPropEnum.ConfigPara.id + " long primary key, "
+ + BeanPropEnum.ConfigPara.mode + " integer, "
+ + BeanPropEnum.ConfigPara.devphyid + " char(8), "
+ + BeanPropEnum.ConfigPara.psamno + " char(12), "
+ + BeanPropEnum.ConfigPara.epayIP + " varchar(128), "
+ + BeanPropEnum.ConfigPara.epayPort + " integer, "
+ + BeanPropEnum.ConfigPara.epayUri + " varchar(128), "
+ + BeanPropEnum.ConfigPara.managePwd + " char(6),"
+ + BeanPropEnum.ConfigPara.initOK + " integer ) ")
+ private val DROP_TABLE_NAME_CONFIGPARA = "DROP TABLE IF EXISTS $TABLE_NAME_CONFIGPARA"
+
+ private val lock = ReentrantLock()
+ fun getLock(): Lock {
+ return lock
+ }
+
+ override fun onCreate(db: SQLiteDatabase) {
+ db.execSQL(CREATE_TABLE_NAME_CONFIGPARA)
+ }
+
+ override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
+ if (oldVersion < newVersion) {
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/db/DBParaHelper.kt b/app/src/main/java/com/supwisdom/db/DBParaHelper.kt
new file mode 100644
index 0000000..17c542a
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/db/DBParaHelper.kt
@@ -0,0 +1,100 @@
+package com.supwisdom.db
+
+import android.content.Context
+import android.database.sqlite.SQLiteDatabase
+import android.database.sqlite.SQLiteOpenHelper
+import java.util.concurrent.locks.Lock
+import java.util.concurrent.locks.ReentrantLock
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+class DBParaHelper private constructor(context: Context) : SQLiteOpenHelper(context, DB_NAME, null, VERSION) {
+ companion object {
+ private val DB_NAME = "db_para"
+ private val VERSION = 1
+
+ val TABLE_NAME_SYSPARA = "tb_syspara"
+ val TABLE_NAME_DYNAMICPARA = "tb_dynamicpara"
+ val TABLE_NAME_CONTROLPARA = "tb_controlpara"
+ val TABLE_NAME_WHITELIST = "tb_whitelist"
+
+ private var instance: DBParaHelper? = null
+ fun getInstance(context: Context): DBParaHelper {
+ if (null == instance) {
+ synchronized(DBParaHelper::class.java) {
+ if (null == instance) {
+ instance = DBParaHelper(context)
+ }
+ }
+ }
+ return instance!!
+ }
+ }
+
+
+ /**
+ * SQL for create table
+ */
+ private val CREATE_TABLE_NAME_WHITELIST = ("create table IF NOT EXISTS "
+ + TABLE_NAME_WHITELIST + " ( "
+ + BeanPropEnum.WhiteList.cardphyid + " varchar(32),"
+ + BeanPropEnum.WhiteList.cardno + " varchar(32),"
+ + BeanPropEnum.WhiteList.flag + " integer,"
+ + BeanPropEnum.WhiteList.balance + " integer,"
+ + "primary key ("
+ + BeanPropEnum.WhiteList.cardphyid + ","
+ + BeanPropEnum.WhiteList.cardno + ") )")
+
+ private val CREATE_TABLE_NAME_CONTROLPARA = ("create table IF NOT EXISTS "
+ + TABLE_NAME_CONTROLPARA + " ( "
+ + BeanPropEnum.ControlPara.paraname + " varchar(64) primary key,"
+ + BeanPropEnum.ControlPara.paraval + " varchar(64) )")
+ private val CREATE_TABLE_NAME_DYNAMICPARA = ("create table IF NOT EXISTS "
+ + TABLE_NAME_DYNAMICPARA + " ( "
+ + BeanPropEnum.DynamicPara.id + " long primary key, "
+ + BeanPropEnum.DynamicPara.appid + " varchar(16), "
+ + BeanPropEnum.DynamicPara.appsecret + " varchar(128), "
+ + BeanPropEnum.DynamicPara.deviceid + " integer, "
+ + BeanPropEnum.DynamicPara.merchaccno + " integer, "
+ + BeanPropEnum.DynamicPara.shopname + " varchar(32), "
+ + BeanPropEnum.DynamicPara.onlineseqno + " integer, "
+ + BeanPropEnum.DynamicPara.offlineseqno + " integer, "
+ + BeanPropEnum.DynamicPara.paraverno + " integer, "
+ + BeanPropEnum.DynamicPara.paragroupid + " integer, "
+ + BeanPropEnum.DynamicPara.cardverno + " char(14),"
+ + BeanPropEnum.DynamicPara.jwt + " varchar(254),"
+ + BeanPropEnum.DynamicPara.token + " varchar(32) )")
+ private val DROP_TABLE_NAME_DYNAMICPARA = "DROP TABLE IF EXISTS $TABLE_NAME_DYNAMICPARA"
+ private val CREATE_TABLE_NAME_SYSPARA = ("create table IF NOT EXISTS "
+ + TABLE_NAME_SYSPARA + " ( "
+ + BeanPropEnum.Syspara.id + " long primary key, "
+ + BeanPropEnum.Syspara.returnFlag + " integer, "
+ + BeanPropEnum.Syspara.heatBeat + " integer, "
+ + BeanPropEnum.Syspara.offlineEnable + " integer, "
+ + BeanPropEnum.Syspara.maxOfflineDays + " integer, "
+ + BeanPropEnum.Syspara.mngpasswd + " char(6), "
+ + BeanPropEnum.Syspara.fixpayGap + " integer, "
+ + BeanPropEnum.Syspara.consumeShowtime + " integer, "
+ + BeanPropEnum.Syspara.consumeFailShowtime + " integer, "
+ + BeanPropEnum.Syspara.commTime + " integer )")
+ private val DROP_TABLE_NAME_SYSPARA = "DROP TABLE IF EXISTS $TABLE_NAME_SYSPARA"
+
+ private val lock = ReentrantLock()
+ fun getLock(): Lock {
+ return lock
+ }
+
+ override fun onCreate(db: SQLiteDatabase) {
+ db.execSQL(CREATE_TABLE_NAME_SYSPARA)
+ db.execSQL(CREATE_TABLE_NAME_DYNAMICPARA)
+ db.execSQL(CREATE_TABLE_NAME_CONTROLPARA)
+ db.execSQL(CREATE_TABLE_NAME_WHITELIST)
+ }
+
+ override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
+ if (oldVersion < newVersion) {
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/db/DBTransdtlHelper.kt b/app/src/main/java/com/supwisdom/db/DBTransdtlHelper.kt
new file mode 100644
index 0000000..aadfb8d
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/db/DBTransdtlHelper.kt
@@ -0,0 +1,88 @@
+package com.supwisdom.db
+
+import android.content.Context
+import android.database.sqlite.SQLiteDatabase
+import android.database.sqlite.SQLiteOpenHelper
+import java.util.concurrent.locks.Lock
+import java.util.concurrent.locks.ReentrantLock
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+class DBTransdtlHelper private constructor(context: Context) : SQLiteOpenHelper(context, DB_NAME, null, VERSION) {
+ companion object {
+ private val DB_NAME = "db_transdtl"
+ private val VERSION = 1
+ private var instance: DBTransdtlHelper? = null
+
+ const val TABLE_NAME_DTL_ONLINE = "tb_dtl_online"
+ const val TABLE_NAME_DTL_OFFLINE = "tb_dtl_offline"
+
+ fun getInstance(context: Context): DBTransdtlHelper {
+ if (null == instance) {
+ synchronized(DBTransdtlHelper::class.java) {
+ if (null == instance) {
+ instance = DBTransdtlHelper(context)
+ }
+ }
+ }
+ return instance!!
+ }
+ }
+
+ /**
+ * SQL for create table
+ */
+ private val CRAETE_TABLE_NAME_DTL_ONLINE = ("create table IF NOT EXISTS "
+ + TABLE_NAME_DTL_ONLINE + " ( "
+ + BeanPropEnum.TransdtlOnline.devphyid + " char(8),"
+ + BeanPropEnum.TransdtlOnline.transdate + " char(8),"
+ + BeanPropEnum.TransdtlOnline.transtime + " char(6),"
+ + BeanPropEnum.TransdtlOnline.devseqno + " long primary key,"
+ + BeanPropEnum.TransdtlOnline.cardno + " varchar(32),"
+ + BeanPropEnum.TransdtlOnline.cardphyid + " varchar(32),"
+ + BeanPropEnum.TransdtlOnline.qrcode + " varchar(254),"
+ + BeanPropEnum.TransdtlOnline.transtype + " varchar(8),"
+ + BeanPropEnum.TransdtlOnline.payamt + " integer,"
+ + BeanPropEnum.TransdtlOnline.extraamt + " integer,"
+ + BeanPropEnum.TransdtlOnline.balance + " integer,"
+ + BeanPropEnum.TransdtlOnline.managefeetype + " varchar(10),"
+ + BeanPropEnum.TransdtlOnline.username + " varchar(32),"
+ + BeanPropEnum.TransdtlOnline.billno + " varchar(32),"
+ + BeanPropEnum.TransdtlOnline.reversalflag + " varchar(8),"
+ + BeanPropEnum.TransdtlOnline.reversalbillno + " varchar(32),"
+ + BeanPropEnum.TransdtlOnline.status + " varchar(8),"
+ + BeanPropEnum.TransdtlOnline.upflag + " integer )")
+ private val CRAETE_TABLE_NAME_DTL_OFFLINE = ("create table IF NOT EXISTS "
+ + TABLE_NAME_DTL_OFFLINE + " ( "
+ + BeanPropEnum.TransdtlOffline.devphyid + " char(8),"
+ + BeanPropEnum.TransdtlOffline.transdate + " char(8),"
+ + BeanPropEnum.TransdtlOffline.transtime + " char(6),"
+ + BeanPropEnum.TransdtlOffline.devseqno + " long primary key,"
+ + BeanPropEnum.TransdtlOffline.cardno + " varchar(32),"
+ + BeanPropEnum.TransdtlOffline.cardphyid + " varchar(32),"
+ + BeanPropEnum.TransdtlOffline.payamt + " integer,"
+ + BeanPropEnum.TransdtlOffline.extraamt + " integer,"
+ + BeanPropEnum.TransdtlOffline.reversalflag + " varchar(8),"
+ + BeanPropEnum.TransdtlOffline.reversalseqno + " integer,"
+ + BeanPropEnum.TransdtlOffline.reversaltransdate + " char(8),"
+ + BeanPropEnum.TransdtlOffline.reversaltranstime + " char(6),"
+ + BeanPropEnum.TransdtlOffline.status + " varchar(8),"
+ + BeanPropEnum.TransdtlOffline.upflag + " integer )")
+
+ private val lock = ReentrantLock()
+ fun getLock(): Lock {
+ return lock
+ }
+
+ override fun onCreate(db: SQLiteDatabase) {
+ db.execSQL(CRAETE_TABLE_NAME_DTL_ONLINE)
+ db.execSQL(CRAETE_TABLE_NAME_DTL_OFFLINE)
+ }
+
+ override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
+ if (oldVersion < newVersion) {
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/db/DynamicParaDao.kt b/app/src/main/java/com/supwisdom/db/DynamicParaDao.kt
new file mode 100644
index 0000000..20ab20d
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/db/DynamicParaDao.kt
@@ -0,0 +1,117 @@
+package com.supwisdom.db
+
+import android.content.ContentValues
+import android.content.Context
+import android.database.Cursor
+import com.supwisdom.entity.DynamicParaRecord
+import java.util.concurrent.locks.Lock
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+class DynamicParaDao constructor(context: Context) {
+ private val INDEX = "1" // 主键
+ private val dbHelper = DBParaHelper.getInstance(context)
+ private val TABLE = DBParaHelper.TABLE_NAME_DYNAMICPARA
+
+ fun getLock(): Lock {
+ return dbHelper.getLock()
+ }
+
+ fun replace(record: DynamicParaRecord): Boolean {
+ val db = dbHelper.readableDatabase
+ val values = getContentValues(record)
+ try {
+ db.beginTransaction()
+ if (db.replace(TABLE, null, values) > 0) {
+ db.setTransactionSuccessful()
+ return true
+ }
+ } finally {
+ db.endTransaction()
+ }
+ return false
+ }
+
+ fun update(record: DynamicParaRecord): Boolean {
+ val db = dbHelper.writableDatabase
+ val values = getContentValues(record)
+ try {
+ db.beginTransaction()
+ if (db.update(TABLE, values, BeanPropEnum.DynamicPara.id.toString() + "=?", arrayOf(INDEX)) > 0) {
+ db.setTransactionSuccessful()
+ return true
+ }
+ } finally {
+ db.endTransaction()
+ }
+ return false
+ }
+
+ fun get(): DynamicParaRecord? {
+ val db = dbHelper.readableDatabase
+ var cursor: Cursor? = null
+ try {
+ cursor = db.query(
+ TABLE, null, BeanPropEnum.DynamicPara.id.toString() + "=?",
+ arrayOf(INDEX), null, null, null
+ )
+ if (cursor != null && cursor.moveToNext()) {
+ return getRecord(cursor)
+ }
+ } finally {
+ cursor?.close()
+ }
+ return null
+ }
+
+ fun clear(): Boolean {
+ val db = dbHelper.writableDatabase
+ try {
+ db.beginTransaction()
+ if (db.delete(TABLE, null, null) < 0) {
+ return false
+ }
+ db.setTransactionSuccessful()
+ return true
+ } finally {
+ db.endTransaction()
+ }
+ }
+
+ private fun getRecord(cursor: Cursor): DynamicParaRecord {
+ val record = DynamicParaRecord()
+ record.appid = cursor.getString(cursor.getColumnIndex(BeanPropEnum.DynamicPara.appid.toString()))
+ record.appsecret = cursor.getString(cursor.getColumnIndex(BeanPropEnum.DynamicPara.appsecret.toString()))
+ record.deviceid = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.DynamicPara.deviceid.toString()))
+ record.merchaccno = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.DynamicPara.merchaccno.toString()))
+ record.shopname = cursor.getString(cursor.getColumnIndex(BeanPropEnum.DynamicPara.shopname.toString()))
+ record.onlineseqno = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.DynamicPara.onlineseqno.toString()))
+ record.offlineseqno = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.DynamicPara.offlineseqno.toString()))
+ record.paraverno = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.DynamicPara.paraverno.toString()))
+ record.paragroupid = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.DynamicPara.paragroupid.toString()))
+ record.cardverno = cursor.getString(cursor.getColumnIndex(BeanPropEnum.DynamicPara.cardverno.toString()))
+ record.jwt = cursor.getString(cursor.getColumnIndex(BeanPropEnum.DynamicPara.jwt.toString()))
+ record.token = cursor.getString(cursor.getColumnIndex(BeanPropEnum.DynamicPara.token.toString()))
+ return record
+ }
+
+ private fun getContentValues(record: DynamicParaRecord): ContentValues {
+ val values = ContentValues()
+ values.put(BeanPropEnum.DynamicPara.id.toString(), INDEX)
+ values.put(BeanPropEnum.DynamicPara.appid.toString(), record.appid)
+ values.put(BeanPropEnum.DynamicPara.appsecret.toString(), record.appsecret)
+ values.put(BeanPropEnum.DynamicPara.deviceid.toString(), record.deviceid)
+ values.put(BeanPropEnum.DynamicPara.merchaccno.toString(), record.merchaccno)
+ values.put(BeanPropEnum.DynamicPara.shopname.toString(), record.shopname)
+ values.put(BeanPropEnum.DynamicPara.onlineseqno.toString(), record.onlineseqno)
+ values.put(BeanPropEnum.DynamicPara.offlineseqno.toString(), record.offlineseqno)
+ values.put(BeanPropEnum.DynamicPara.paraverno.toString(), record.paraverno)
+ values.put(BeanPropEnum.DynamicPara.paragroupid.toString(), record.paragroupid)
+ values.put(BeanPropEnum.DynamicPara.cardverno.toString(), record.cardverno)
+ values.put(BeanPropEnum.DynamicPara.jwt.toString(), record.jwt)
+ values.put(BeanPropEnum.DynamicPara.token.toString(), record.token)
+ return values
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/db/Pos.kt b/app/src/main/java/com/supwisdom/db/Pos.kt
new file mode 100644
index 0000000..d03277b
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/db/Pos.kt
@@ -0,0 +1,262 @@
+package com.supwisdom.db
+
+import android.content.Context
+import com.supwisdom.entity.*
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+class Pos constructor(context: Context) {
+ private val sdContext = SDContext(context)
+ private val configParaDao = ConfigParaDao(sdContext)
+ private var cfgRecord: ConfigParaRecord? = null
+ private val dynamicParaDao = DynamicParaDao(context)
+ private var dyRecord: DynamicParaRecord? = null
+ private val sysParaDao = SysParaDao(context)
+ private var sysRecord: SysParaRecord? = null
+ private val controlParaDao = ControlParaDao(context)
+ private val whiteListDao = WhiteListDao(context)
+ private val transdtlOnlineDao = TransdtlOnlineDao(sdContext)
+ private val transdtlOfflineDao = TransdtlOfflineDao(sdContext)
+ private val transdtlUnionDao = TransdtlUnionDao(sdContext)
+ private var onlMaxSeqno = 0
+ private var offMaxSeqno = 0
+
+ init {
+ }
+
+ /**
+ * 设备参数
+ */
+ fun replaceConfigPara(record: ConfigParaRecord): Boolean {
+ try {
+ configParaDao.getLock().lock()
+ if (configParaDao.replace(record)) {
+ cfgRecord = record
+ return true
+ }
+ } finally {
+ configParaDao.getLock().unlock()
+ }
+ return false
+ }
+
+ fun getConfigPara(): ConfigParaRecord? {
+ if (cfgRecord == null) {
+ try {
+ configParaDao.getLock().lock()
+ cfgRecord = configParaDao.get()
+ } finally {
+ configParaDao.getLock().unlock()
+ }
+ }
+ return cfgRecord
+ }
+
+ fun replaceControlPara(record: ControlParaRecord): Boolean {
+ try {
+ controlParaDao.getLock().lock()
+ return controlParaDao.replace(record)
+ } finally {
+ controlParaDao.getLock().unlock()
+ }
+ }
+
+ fun replaceControlPara(paraname: String, paraval: String): Boolean {
+ try {
+ controlParaDao.getLock().lock()
+ return controlParaDao.replace(paraname, paraval)
+ } finally {
+ controlParaDao.getLock().unlock()
+ }
+ }
+
+ fun getControlPara(paraname: String): ControlParaRecord? {
+ try {
+ controlParaDao.getLock().lock()
+ return controlParaDao.get(paraname)
+ } finally {
+ controlParaDao.getLock().unlock()
+ }
+ }
+
+ fun replaceDynamicPara(record: DynamicParaRecord): Boolean {
+ try {
+ dynamicParaDao.getLock().lock()
+ if (dynamicParaDao.replace(record)) {
+ dyRecord = record
+ return true
+ }
+ } finally {
+ dynamicParaDao.getLock().unlock()
+ }
+ return false
+ }
+
+ fun getDynamicPara(): DynamicParaRecord? {
+ if (dyRecord == null) {
+ try {
+ dynamicParaDao.getLock().lock()
+ dyRecord = dynamicParaDao.get()
+ } finally {
+ dynamicParaDao.getLock().unlock()
+ }
+ }
+ return dyRecord
+ }
+
+ fun replaceSysPara(record: SysParaRecord): Boolean {
+ try {
+ sysParaDao.getLock().lock()
+ if (sysParaDao.replace(record)) {
+ sysRecord = record
+ return true
+ }
+ } finally {
+ sysParaDao.getLock().unlock()
+ }
+ return false
+ }
+
+ fun getSysPara(): SysParaRecord? {
+ if (sysRecord == null) {
+ try {
+ sysParaDao.getLock().lock()
+ sysRecord = sysParaDao.get()
+ } finally {
+ sysParaDao.getLock().unlock()
+ }
+ }
+ return sysRecord
+ }
+
+ fun saveWhiteList(list: List<WhiteListRecord>): Boolean {
+ try {
+ whiteListDao.getLock().lock()
+ return whiteListDao.replace(list)
+ } finally {
+ whiteListDao.getLock().unlock()
+ }
+ }
+
+ fun getWhiteList(cardphyid: String, cardno: String): WhiteListRecord? {
+ try {
+ whiteListDao.getLock().lock()
+ return whiteListDao.get(cardphyid, cardno)
+ } finally {
+ whiteListDao.getLock().unlock()
+ }
+ }
+
+ fun getTransdtlOnlineMaxSeqno(): Int {
+ if (onlMaxSeqno == 0) {
+ try {
+ transdtlOnlineDao.getLock().lock()
+ onlMaxSeqno = transdtlOnlineDao.getMaxSeqno()
+ } finally {
+ transdtlOnlineDao.getLock().unlock()
+ }
+ }
+ return onlMaxSeqno
+ }
+
+ fun getTransdtlOnlineUnconfirm(): List<TransdtlOnlineRecord> {
+ try {
+ transdtlOnlineDao.getLock().lock()
+ return transdtlOnlineDao.getUnconfirm()
+ } finally {
+ transdtlOnlineDao.getLock().unlock()
+ }
+ }
+
+ fun saveTransdtlOnline(record: TransdtlOnlineRecord): Boolean {
+ try {
+ transdtlOnlineDao.getLock().lock()
+ return transdtlOnlineDao.save(record)
+ } finally {
+ transdtlOnlineDao.getLock().unlock()
+ }
+ }
+
+ fun updateTransdtlOnline(record: TransdtlOnlineRecord): Boolean {
+ try {
+ transdtlOnlineDao.getLock().lock()
+ return transdtlOnlineDao.update(record)
+ } finally {
+ transdtlOnlineDao.getLock().unlock()
+ }
+ }
+
+ fun clearTransdtlOnline(date: String): Boolean {
+ try {
+ transdtlOnlineDao.getLock().lock()
+ return transdtlOnlineDao.clear(date)
+ } finally {
+ transdtlOnlineDao.getLock().unlock()
+ }
+ }
+
+ fun getTransdtlOfflineMaxSeqno(): Int {
+ if (offMaxSeqno == 0) {
+ try {
+ transdtlOfflineDao.getLock().lock()
+ offMaxSeqno = transdtlOfflineDao.getMaxSeqno()
+ } finally {
+ transdtlOfflineDao.getLock().unlock()
+ }
+ }
+ return offMaxSeqno
+ }
+
+ fun getTransdtlOfflineUnconfirm(): List<TransdtlOfflineRecord> {
+ try {
+ transdtlOfflineDao.getLock().lock()
+ return transdtlOfflineDao.getUnconfirm()
+ } finally {
+ transdtlOfflineDao.getLock().unlock()
+ }
+ }
+
+ fun saveTransdtlOffline(record: TransdtlOfflineRecord): Boolean {
+ try {
+ transdtlOfflineDao.getLock().lock()
+ return transdtlOfflineDao.save(record)
+ } finally {
+ transdtlOfflineDao.getLock().unlock()
+ }
+ }
+
+ fun updateTransdtlOffline(record: TransdtlOfflineRecord): Boolean {
+ try {
+ transdtlOfflineDao.getLock().lock()
+ return transdtlOfflineDao.update(record)
+ } finally {
+ transdtlOfflineDao.getLock().unlock()
+ }
+ }
+
+ fun clearTransdtlOffline(date: String): Boolean {
+ try {
+ transdtlOfflineDao.getLock().lock()
+ return transdtlOfflineDao.clear(date)
+ } finally {
+ transdtlOfflineDao.getLock().unlock()
+ }
+ }
+
+ /**
+ * @param date yyyyMMdd
+ * @param offset 流水偏移量
+ * @param flag 0--全部流水 1--成功流水 2--失败流水
+ * @param num 查询数量
+ */
+ fun getTransdtlUnion(date: String, offset: Int, flag: Int, num: Int): List<TransdtlUnionRecord> {
+ try {
+ transdtlUnionDao.getLock().lock()
+ return transdtlUnionDao.get(date, offset, flag, num)
+ } finally {
+ transdtlUnionDao.getLock().unlock()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/db/SDContext.kt b/app/src/main/java/com/supwisdom/db/SDContext.kt
new file mode 100644
index 0000000..1b870a6
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/db/SDContext.kt
@@ -0,0 +1,58 @@
+package com.supwisdom.db
+
+import android.content.Context
+import android.content.ContextWrapper
+import android.database.DatabaseErrorHandler
+import android.database.sqlite.SQLiteDatabase
+import java.io.File
+import java.io.IOException
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+class SDContext constructor(context: Context) : ContextWrapper(context) {
+ override fun getDatabasePath(name: String): File? {
+ if (android.os.Environment.MEDIA_MOUNTED == android.os.Environment.getExternalStorageState()) {
+ //获取sd卡路径
+ var dbDir = android.os.Environment.getExternalStorageDirectory().absolutePath
+ dbDir += "/supwisdom"//数据库所在目录
+ val dbPath = "$dbDir/$name"//数据库路径
+ //判断目录是否存在,不存在则创建该目录
+ val dirFile = File(dbDir)
+ if (!dirFile.exists()) {
+ dirFile.mkdirs()
+ }
+ val dbFile = File(dbPath)
+ if (!dbFile.exists()) {
+ try {
+ if (dbFile.createNewFile()) {
+ return dbFile
+ }
+ } catch (e: IOException) {
+ // TODO Auto-generated catch block
+ e.printStackTrace()
+ }
+ } else {
+ return dbFile
+ }
+ }
+ return null
+ }
+
+ override fun openOrCreateDatabase(
+ name: String, mode: Int,
+ factory: SQLiteDatabase.CursorFactory?
+ ): SQLiteDatabase {
+ val file = getDatabasePath(name) ?: return super.openOrCreateDatabase(name, mode, factory)
+ return SQLiteDatabase.openOrCreateDatabase(file, factory)
+ }
+
+ override fun openOrCreateDatabase(
+ name: String, mode: Int,
+ factory: SQLiteDatabase.CursorFactory?, errorHandler: DatabaseErrorHandler?
+ ): SQLiteDatabase {
+ val file = getDatabasePath(name) ?: return super.openOrCreateDatabase(name, mode, factory, errorHandler)
+ return SQLiteDatabase.openOrCreateDatabase(file, factory)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/db/SysParaDao.kt b/app/src/main/java/com/supwisdom/db/SysParaDao.kt
new file mode 100644
index 0000000..14872aa
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/db/SysParaDao.kt
@@ -0,0 +1,118 @@
+package com.supwisdom.db
+
+import android.content.ContentValues
+import android.content.Context
+import android.database.Cursor
+import com.supwisdom.entity.SysParaRecord
+import java.util.concurrent.locks.Lock
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+class SysParaDao constructor(context: Context) {
+ private val INDEX = "1" // 主键
+ private val dbHelper = DBParaHelper.getInstance(context)
+ private val TABLE = DBParaHelper.TABLE_NAME_SYSPARA
+
+ fun getLock(): Lock {
+ return dbHelper.getLock()
+ }
+
+ fun replace(record: SysParaRecord): Boolean {
+ val db = dbHelper.readableDatabase
+ val values = getContentValues(record)
+ try {
+ db.beginTransaction()
+ if (db.replace(TABLE, null, values) > 0) {
+ db.setTransactionSuccessful()
+ return true
+ }
+ } finally {
+ db.endTransaction()
+ }
+ return false
+ }
+
+ fun update(record: SysParaRecord): Boolean {
+ val db = dbHelper.writableDatabase
+ val values = getContentValues(record)
+ try {
+ db.beginTransaction()
+ if (db.update(TABLE, values, BeanPropEnum.Syspara.id.toString() + "=?", arrayOf(INDEX)) < 0) {
+ return false
+ }
+ db.setTransactionSuccessful()
+ return true
+ } finally {
+ db.endTransaction()
+ }
+ return false
+ }
+
+ fun get(): SysParaRecord? {
+ val db = dbHelper.readableDatabase
+ var cursor: Cursor? = null
+ try {
+ cursor = db.query(
+ TABLE, null, BeanPropEnum.Syspara.id.toString() + "=?",
+ arrayOf(INDEX), null, null, null
+ )
+ if (cursor != null && cursor.moveToNext()) {
+ return getRecord(cursor)
+ }
+ } finally {
+ cursor?.close()
+ }
+ return null
+ }
+
+ fun clear(): Boolean {
+ val db = dbHelper.writableDatabase
+ try {
+ db.beginTransaction()
+ if (db.delete(TABLE, null, null) < 0) {
+ return false
+ }
+ db.setTransactionSuccessful()
+ return true
+ } finally {
+ db.endTransaction()
+ }
+ }
+
+ private fun getRecord(cursor: Cursor): SysParaRecord {
+ val record = SysParaRecord()
+ record.returnFlag = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.Syspara.returnFlag.toString()))
+ record.heatBeat = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.Syspara.heatBeat.toString()))
+ val enable = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.Syspara.offlineEnable.toString()))
+ record.offlineEnable = enable == 1
+ record.maxOfflineDays = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.Syspara.maxOfflineDays.toString()))
+ record.mngPasswd = cursor.getString(cursor.getColumnIndex(BeanPropEnum.Syspara.mngpasswd.toString()))
+ record.fixpayGap = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.Syspara.fixpayGap.toString()))
+ record.sucShowtime = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.Syspara.consumeShowtime.toString()))
+ record.failShowtime =
+ cursor.getInt(cursor.getColumnIndex(BeanPropEnum.Syspara.consumeFailShowtime.toString()))
+ record.commTime = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.Syspara.commTime.toString()))
+ return record
+ }
+
+ private fun getContentValues(record: SysParaRecord): ContentValues {
+ val values = ContentValues()
+ values.put(BeanPropEnum.Syspara.id.toString(), INDEX)
+ values.put(BeanPropEnum.Syspara.returnFlag.toString(), record.returnFlag)
+ values.put(BeanPropEnum.Syspara.heatBeat.toString(), record.heatBeat)
+ if (record.offlineEnable) {
+ values.put(BeanPropEnum.Syspara.offlineEnable.toString(), 1)
+ } else {
+ values.put(BeanPropEnum.Syspara.offlineEnable.toString(), 0)
+ }
+ values.put(BeanPropEnum.Syspara.maxOfflineDays.toString(), record.maxOfflineDays)
+ values.put(BeanPropEnum.Syspara.mngpasswd.toString(), record.mngPasswd)
+ values.put(BeanPropEnum.Syspara.fixpayGap.toString(), record.fixpayGap)
+ values.put(BeanPropEnum.Syspara.consumeShowtime.toString(), record.sucShowtime)
+ values.put(BeanPropEnum.Syspara.consumeFailShowtime.toString(), record.failShowtime)
+ values.put(BeanPropEnum.Syspara.commTime.toString(), record.commTime)
+ return values
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/db/TransdtlOfflineDao.kt b/app/src/main/java/com/supwisdom/db/TransdtlOfflineDao.kt
new file mode 100644
index 0000000..20bcec1
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/db/TransdtlOfflineDao.kt
@@ -0,0 +1,172 @@
+package com.supwisdom.db
+
+import android.content.ContentValues
+import android.content.Context
+import android.database.Cursor
+import com.supwisdom.entity.PayStatus
+import com.supwisdom.entity.ReversalFlag
+import com.supwisdom.entity.TransdtlOfflineRecord
+import java.util.concurrent.locks.Lock
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+class TransdtlOfflineDao constructor(context: Context) {
+ private val dbHelper = DBTransdtlHelper.getInstance(context)
+ private val TABLE = DBTransdtlHelper.TABLE_NAME_DTL_OFFLINE
+
+ fun getLock(): Lock {
+ return dbHelper.getLock()
+ }
+
+ fun save(record: TransdtlOfflineRecord): Boolean {
+ val db = dbHelper.readableDatabase
+ val values = getContentValues(record)
+ try {
+ db.beginTransaction()
+ if (db.replace(TABLE, null, values) > 0) {
+ db.setTransactionSuccessful()
+ return true
+ }
+ } finally {
+ db.endTransaction()
+ }
+ return false
+ }
+
+ fun update(record: TransdtlOfflineRecord): Boolean {
+ val db = dbHelper.writableDatabase
+ val values = getContentValues(record)
+ try {
+ db.beginTransaction()
+ if (db.update(
+ TABLE,
+ values,
+ BeanPropEnum.TransdtlOffline.devseqno.toString() + "=?",
+ arrayOf(record.devseqno.toString())
+ ) > 0
+ ) {
+ db.setTransactionSuccessful()
+ return true
+ }
+ } finally {
+ db.endTransaction()
+ }
+ return false
+ }
+
+ fun getUnconfirm(): List<TransdtlOfflineRecord> {
+ val db = dbHelper.readableDatabase
+ var cursor: Cursor? = null
+ val selection = BeanPropEnum.TransdtlOffline.upflag.toString() + "=?"
+ try {
+ cursor = db.query(TABLE, null, selection, arrayOf("0"), null, null, null)
+ val list = ArrayList<TransdtlOfflineRecord>()
+ while (cursor != null && cursor.moveToNext()) {
+ list.add(getRecord(cursor))
+ }
+ return list
+ } finally {
+ cursor?.close()
+ }
+ }
+
+ fun getMaxSeqno(): Int {
+ val db = dbHelper.readableDatabase
+ val sql = ("select max(${BeanPropEnum.TransdtlOffline.devseqno}) as seqno from $TABLE")
+ var cursor: Cursor? = null
+ try {
+ cursor = db.rawQuery(sql, null, null)
+ if (cursor != null && cursor.moveToNext()) {
+ return cursor.getInt(cursor.getColumnIndex("seqno"))
+ }
+ } finally {
+ cursor?.close()
+ }
+ return 0
+ }
+
+ fun clear(): Boolean {
+ val db = dbHelper.writableDatabase
+ try {
+ db.beginTransaction()
+ if (db.delete(TABLE, null, null) < 0) {
+ return false
+ }
+ db.setTransactionSuccessful()
+ return true
+ } finally {
+ db.endTransaction()
+ }
+ }
+
+ fun clear(date: String): Boolean {
+ val db = dbHelper.writableDatabase
+ val selection =
+ BeanPropEnum.TransdtlOffline.upflag.toString() + "=?" + BeanPropEnum.TransdtlOffline.transdate + "<?"
+ try {
+ db.beginTransaction()
+ if (db.delete(TABLE, selection, arrayOf("1", date)) < 0) {
+ return false
+ }
+ db.setTransactionSuccessful()
+ return true
+ } finally {
+ db.endTransaction()
+ }
+ }
+
+ private fun getRecord(cursor: Cursor): TransdtlOfflineRecord {
+ val record = TransdtlOfflineRecord()
+ record.devphyid = cursor.getString(cursor.getColumnIndex(BeanPropEnum.TransdtlOffline.devphyid.toString()))
+ record.transdate = cursor.getString(cursor.getColumnIndex(BeanPropEnum.TransdtlOffline.transdate.toString()))
+ record.transtime = cursor.getString(cursor.getColumnIndex(BeanPropEnum.TransdtlOffline.transtime.toString()))
+ record.devseqno = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.TransdtlOffline.devseqno.toString()))
+ record.cardno = cursor.getString(cursor.getColumnIndex(BeanPropEnum.TransdtlOffline.cardno.toString()))
+ record.cardphyid = cursor.getString(cursor.getColumnIndex(BeanPropEnum.TransdtlOffline.cardphyid.toString()))
+ record.payamt = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.TransdtlOffline.payamt.toString()))
+ record.extraamt = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.TransdtlOffline.extraamt.toString()))
+ var flag = cursor.getString(cursor.getColumnIndex(BeanPropEnum.TransdtlOffline.reversalflag.toString()))
+ when (flag) {
+ ReversalFlag.NONE.toString() -> record.reversalflag = ReversalFlag.NONE
+ ReversalFlag.AUTO.toString() -> record.reversalflag = ReversalFlag.AUTO
+ ReversalFlag.MANUAL.toString() -> record.reversalflag = ReversalFlag.MANUAL
+ else -> record.reversalflag = ReversalFlag.NONE
+ }
+ record.reversalseqno =
+ cursor.getInt(cursor.getColumnIndex(BeanPropEnum.TransdtlOffline.reversalseqno.toString()))
+ record.reversaltransdate =
+ cursor.getString(cursor.getColumnIndex(BeanPropEnum.TransdtlOffline.reversaltransdate.toString()))
+ record.reversaltranstime =
+ cursor.getString(cursor.getColumnIndex(BeanPropEnum.TransdtlOffline.reversaltranstime.toString()))
+ flag = cursor.getString(cursor.getColumnIndex(BeanPropEnum.TransdtlOffline.status.toString()))
+ when (flag) {
+ PayStatus.INIT.toString() -> record.status = PayStatus.INIT
+ PayStatus.FAIL.toString() -> record.status = PayStatus.FAIL
+ PayStatus.SUC.toString() -> record.status = PayStatus.SUC
+ else -> record.status = PayStatus.INIT
+ }
+ record.upflag = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.TransdtlOffline.upflag.toString()))
+ return record
+ }
+
+ private fun getContentValues(record: TransdtlOfflineRecord): ContentValues {
+ val values = ContentValues()
+ values.put(BeanPropEnum.TransdtlOffline.devphyid.toString(), record.devphyid)
+ values.put(BeanPropEnum.TransdtlOffline.transdate.toString(), record.transdate)
+ values.put(BeanPropEnum.TransdtlOffline.transtime.toString(), record.transtime)
+ values.put(BeanPropEnum.TransdtlOffline.devseqno.toString(), record.devseqno)
+ values.put(BeanPropEnum.TransdtlOffline.cardno.toString(), record.cardno)
+ values.put(BeanPropEnum.TransdtlOffline.cardphyid.toString(), record.cardphyid)
+ values.put(BeanPropEnum.TransdtlOffline.payamt.toString(), record.payamt)
+ values.put(BeanPropEnum.TransdtlOffline.extraamt.toString(), record.extraamt)
+ values.put(BeanPropEnum.TransdtlOffline.reversalflag.toString(), record.reversalflag.toString())
+ values.put(BeanPropEnum.TransdtlOffline.reversalseqno.toString(), record.reversalseqno)
+ values.put(BeanPropEnum.TransdtlOffline.reversaltransdate.toString(), record.reversaltransdate)
+ values.put(BeanPropEnum.TransdtlOffline.reversaltranstime.toString(), record.reversaltranstime)
+ values.put(BeanPropEnum.TransdtlOffline.status.toString(), record.status.toString())
+ values.put(BeanPropEnum.TransdtlOffline.upflag.toString(), record.upflag)
+ return values
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/db/TransdtlOnlineDao.kt b/app/src/main/java/com/supwisdom/db/TransdtlOnlineDao.kt
new file mode 100644
index 0000000..063c6e7
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/db/TransdtlOnlineDao.kt
@@ -0,0 +1,179 @@
+package com.supwisdom.db
+
+import android.content.ContentValues
+import android.content.Context
+import android.database.Cursor
+import com.supwisdom.entity.PayStatus
+import com.supwisdom.entity.ReversalFlag
+import com.supwisdom.entity.TransdtlOnlineRecord
+import java.util.concurrent.locks.Lock
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+class TransdtlOnlineDao constructor(context: Context) {
+ private val dbHelper = DBTransdtlHelper.getInstance(context)
+ private val TABLE = DBTransdtlHelper.TABLE_NAME_DTL_ONLINE
+
+ fun getLock(): Lock {
+ return dbHelper.getLock()
+ }
+
+ fun save(record: TransdtlOnlineRecord): Boolean {
+ val db = dbHelper.readableDatabase
+ val values = getContentValues(record)
+ try {
+ db.beginTransaction()
+ if (db.replace(TABLE, null, values) > 0) {
+ db.setTransactionSuccessful()
+ return true
+ }
+ } finally {
+ db.endTransaction()
+ }
+ return false
+ }
+
+ fun update(record: TransdtlOnlineRecord): Boolean {
+ val db = dbHelper.writableDatabase
+ val values = getContentValues(record)
+ try {
+ db.beginTransaction()
+ if (db.update(
+ TABLE,
+ values,
+ BeanPropEnum.TransdtlOnline.devseqno.toString() + "=?",
+ arrayOf(record.devseqno.toString())
+ ) > 0
+ ) {
+ db.setTransactionSuccessful()
+ return true
+ }
+ } finally {
+ db.endTransaction()
+ }
+ return false
+ }
+
+ fun getUnconfirm(): List<TransdtlOnlineRecord> {
+ val db = dbHelper.readableDatabase
+ var cursor: Cursor? = null
+ val selection = BeanPropEnum.TransdtlOnline.upflag.toString() + "=?"
+ try {
+ cursor = db.query(TABLE, null, selection, arrayOf("0"), null, null, null)
+ val list = ArrayList<TransdtlOnlineRecord>()
+ while (cursor != null && cursor.moveToNext()) {
+ list.add(getRecord(cursor))
+ }
+ return list
+ } finally {
+ cursor?.close()
+ }
+ }
+
+ fun getMaxSeqno(): Int {
+ val db = dbHelper.readableDatabase
+ val sql = ("select max(${BeanPropEnum.TransdtlOnline.devseqno}) as seqno from $TABLE")
+ var cursor: Cursor? = null
+ try {
+ cursor = db.rawQuery(sql, null, null)
+ if (cursor != null && cursor.moveToNext()) {
+ return cursor.getInt(cursor.getColumnIndex("seqno"))
+ }
+ } finally {
+ cursor?.close()
+ }
+ return 0
+ }
+
+ fun clear(): Boolean {
+ val db = dbHelper.writableDatabase
+ try {
+ db.beginTransaction()
+ if (db.delete(TABLE, null, null) < 0) {
+ return false
+ }
+ db.setTransactionSuccessful()
+ return true
+ } finally {
+ db.endTransaction()
+ }
+ }
+
+ fun clear(date: String): Boolean {
+ val db = dbHelper.writableDatabase
+ val selection =
+ BeanPropEnum.TransdtlOnline.upflag.toString() + "=?" + BeanPropEnum.TransdtlOnline.transdate + "<?"
+ try {
+ db.beginTransaction()
+ if (db.delete(TABLE, selection, arrayOf("1", date)) < 0) {
+ return false
+ }
+ db.setTransactionSuccessful()
+ return true
+ } finally {
+ db.endTransaction()
+ }
+ }
+
+ private fun getRecord(cursor: Cursor): TransdtlOnlineRecord {
+ val record = TransdtlOnlineRecord()
+ record.devphyid = cursor.getString(cursor.getColumnIndex(BeanPropEnum.TransdtlOnline.devphyid.toString()))
+ record.transdate = cursor.getString(cursor.getColumnIndex(BeanPropEnum.TransdtlOnline.transdate.toString()))
+ record.transtime = cursor.getString(cursor.getColumnIndex(BeanPropEnum.TransdtlOnline.transtime.toString()))
+ record.devseqno = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.TransdtlOnline.devseqno.toString()))
+ record.cardno = cursor.getString(cursor.getColumnIndex(BeanPropEnum.TransdtlOnline.cardno.toString()))
+ record.cardphyid = cursor.getString(cursor.getColumnIndex(BeanPropEnum.TransdtlOnline.cardphyid.toString()))
+ record.qrcode = cursor.getString(cursor.getColumnIndex(BeanPropEnum.TransdtlOnline.qrcode.toString()))
+ record.transtype = cursor.getString(cursor.getColumnIndex(BeanPropEnum.TransdtlOnline.transtype.toString()))
+ record.billno = cursor.getString(cursor.getColumnIndex(BeanPropEnum.TransdtlOnline.billno.toString()))
+ record.managefeetype =
+ cursor.getString(cursor.getColumnIndex(BeanPropEnum.TransdtlOnline.managefeetype.toString()))
+ record.username = cursor.getString(cursor.getColumnIndex(BeanPropEnum.TransdtlOnline.username.toString()))
+ record.payamt = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.TransdtlOnline.payamt.toString()))
+ record.extraamt = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.TransdtlOnline.extraamt.toString()))
+ record.balance = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.TransdtlOnline.balance.toString()))
+ var flag = cursor.getString(cursor.getColumnIndex(BeanPropEnum.TransdtlOnline.reversalflag.toString()))
+ when (flag) {
+ ReversalFlag.NONE.toString() -> record.reversalflag = ReversalFlag.NONE
+ ReversalFlag.AUTO.toString() -> record.reversalflag = ReversalFlag.AUTO
+ ReversalFlag.MANUAL.toString() -> record.reversalflag = ReversalFlag.MANUAL
+ else -> record.reversalflag = ReversalFlag.NONE
+ }
+ record.reversalbillno =
+ cursor.getString(cursor.getColumnIndex(BeanPropEnum.TransdtlOnline.reversalbillno.toString()))
+ flag = cursor.getString(cursor.getColumnIndex(BeanPropEnum.TransdtlOnline.status.toString()))
+ when (flag) {
+ PayStatus.INIT.toString() -> record.status = PayStatus.INIT
+ PayStatus.FAIL.toString() -> record.status = PayStatus.FAIL
+ PayStatus.SUC.toString() -> record.status = PayStatus.SUC
+ else -> record.status = PayStatus.INIT
+ }
+ record.upflag = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.TransdtlOnline.upflag.toString()))
+ return record
+ }
+
+ private fun getContentValues(record: TransdtlOnlineRecord): ContentValues {
+ val values = ContentValues()
+ values.put(BeanPropEnum.TransdtlOnline.devphyid.toString(), record.devphyid)
+ values.put(BeanPropEnum.TransdtlOnline.transdate.toString(), record.transdate)
+ values.put(BeanPropEnum.TransdtlOnline.transtime.toString(), record.transtime)
+ values.put(BeanPropEnum.TransdtlOnline.devseqno.toString(), record.devseqno)
+ values.put(BeanPropEnum.TransdtlOnline.cardno.toString(), record.cardno)
+ values.put(BeanPropEnum.TransdtlOnline.cardphyid.toString(), record.cardphyid)
+ values.put(BeanPropEnum.TransdtlOnline.qrcode.toString(), record.qrcode)
+ values.put(BeanPropEnum.TransdtlOnline.transtype.toString(), record.transtype)
+ values.put(BeanPropEnum.TransdtlOnline.payamt.toString(), record.payamt)
+ values.put(BeanPropEnum.TransdtlOnline.extraamt.toString(), record.extraamt)
+ values.put(BeanPropEnum.TransdtlOnline.balance.toString(), record.balance)
+ values.put(BeanPropEnum.TransdtlOnline.billno.toString(), record.billno)
+ values.put(BeanPropEnum.TransdtlOnline.managefeetype.toString(), record.managefeetype)
+ values.put(BeanPropEnum.TransdtlOnline.username.toString(), record.username)
+ values.put(BeanPropEnum.TransdtlOnline.reversalflag.toString(), record.reversalflag.toString())
+ values.put(BeanPropEnum.TransdtlOnline.reversalbillno.toString(), record.reversalbillno)
+ values.put(BeanPropEnum.TransdtlOnline.status.toString(), record.status.toString())
+ values.put(BeanPropEnum.TransdtlOnline.upflag.toString(), record.upflag)
+ return values
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/db/TransdtlUnionDao.kt b/app/src/main/java/com/supwisdom/db/TransdtlUnionDao.kt
new file mode 100644
index 0000000..78bae0c
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/db/TransdtlUnionDao.kt
@@ -0,0 +1,118 @@
+package com.supwisdom.db
+
+import android.content.Context
+import android.database.Cursor
+import com.supwisdom.entity.PayStatus
+import com.supwisdom.entity.ReversalFlag
+import com.supwisdom.entity.TransdtlUnionRecord
+import java.util.concurrent.locks.Lock
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class TransdtlUnionDao constructor(context: Context) {
+ private val tablesql = StringBuilder()
+ private val dbHelper = DBTransdtlHelper.getInstance(context)
+
+ init {
+ tablesql.append("select ")
+ .append(BeanPropEnum.TransdtlOffline.transdate).append(",")
+ .append(BeanPropEnum.TransdtlOffline.transtime).append(",")
+ .append(BeanPropEnum.TransdtlOffline.devseqno).append(",")
+ .append(" 'offcard' as ").append(BeanPropEnum.TransdtlUnion.payway).append(",")
+ .append(BeanPropEnum.TransdtlOffline.reversalflag).append(",")
+ .append(BeanPropEnum.TransdtlOffline.payamt).append(",")
+ .append(BeanPropEnum.TransdtlOffline.status).append(",")
+ .append(BeanPropEnum.TransdtlOffline.cardno).append(" as ").append(BeanPropEnum.TransdtlUnion.username)
+ .append(",")
+ .append(BeanPropEnum.TransdtlOffline.upflag)
+ .append(" from ").append(DBTransdtlHelper.TABLE_NAME_DTL_OFFLINE)
+ .append(" UNION ALL select ")
+ .append(BeanPropEnum.TransdtlOnline.transdate).append(",")
+ .append(BeanPropEnum.TransdtlOnline.transtime).append(",")
+ .append(BeanPropEnum.TransdtlOnline.devseqno).append(",")
+ .append(BeanPropEnum.TransdtlOnline.transtype).append(" as ").append(BeanPropEnum.TransdtlUnion.payway)
+ .append(",")
+ .append(BeanPropEnum.TransdtlOnline.reversalflag).append(",")
+ .append(BeanPropEnum.TransdtlOnline.payamt).append(",")
+ .append(BeanPropEnum.TransdtlOnline.status).append(",")
+ .append(BeanPropEnum.TransdtlOnline.username).append(",")
+ .append(BeanPropEnum.TransdtlOnline.upflag)
+ .append(" from ").append(DBTransdtlHelper.TABLE_NAME_DTL_ONLINE)
+ }
+
+ fun getLock(): Lock {
+ return dbHelper.getLock()
+ }
+
+ fun get(date: String, offset: Int, flag: Int, num: Int): List<TransdtlUnionRecord> {
+ val db = dbHelper.readableDatabase
+ var cursor: Cursor? = null
+ var sql = when (flag) {
+ 0 -> {
+ (tablesql.toString()
+ + " where " + BeanPropEnum.TransdtlUnion.transdate + "='" + date
+ + "' order by " + BeanPropEnum.TransdtlUnion.transtime
+ + " desc ")
+ }
+ 1 -> {
+ (tablesql.toString()
+ + " where " + BeanPropEnum.TransdtlUnion.transdate + "='" + date
+ + "' and " + BeanPropEnum.TransdtlUnion.status + "='"
+ + PayStatus.SUC.toString()
+ + "' order by " + BeanPropEnum.TransdtlUnion.transtime
+ + " desc ")
+ }
+ else -> {
+ (tablesql.toString()
+ + " where " + BeanPropEnum.TransdtlUnion.transdate + "='" + date
+ + "' and " + BeanPropEnum.TransdtlUnion.status + "='"
+ + PayStatus.FAIL.toString()
+ + "' order by " + BeanPropEnum.TransdtlUnion.transtime
+ + " desc ")
+ }
+ }
+ sql += if (offset > 0) {
+ " limit $num offset $offset"
+ } else {
+ " limit $num"
+ }
+ try {
+ cursor = db.rawQuery(sql, null)
+ val list = ArrayList<TransdtlUnionRecord>()
+ while (cursor != null && cursor.moveToNext()) {
+ list.add(getRecord(cursor))
+ }
+ return list
+ } finally {
+ cursor?.close()
+ }
+ }
+
+ private fun getRecord(cursor: Cursor): TransdtlUnionRecord {
+ val record = TransdtlUnionRecord()
+ record.transdate = cursor.getString(cursor.getColumnIndex(BeanPropEnum.TransdtlUnion.transdate.toString()))
+ record.transtime = cursor.getString(cursor.getColumnIndex(BeanPropEnum.TransdtlUnion.transtime.toString()))
+ record.devseqno = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.TransdtlUnion.devseqno.toString()))
+ record.payway = cursor.getString(cursor.getColumnIndex(BeanPropEnum.TransdtlUnion.payway.toString()))
+ record.username = cursor.getString(cursor.getColumnIndex(BeanPropEnum.TransdtlUnion.username.toString()))
+ var flag = cursor.getString(cursor.getColumnIndex(BeanPropEnum.TransdtlUnion.reversalflag.toString()))
+ when (flag) {
+ ReversalFlag.NONE.toString() -> record.reversalflag = ReversalFlag.NONE
+ ReversalFlag.AUTO.toString() -> record.reversalflag = ReversalFlag.AUTO
+ ReversalFlag.MANUAL.toString() -> record.reversalflag = ReversalFlag.MANUAL
+ else -> record.reversalflag = ReversalFlag.NONE
+ }
+ record.payamt = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.TransdtlUnion.payamt.toString()))
+ flag = cursor.getString(cursor.getColumnIndex(BeanPropEnum.TransdtlUnion.status.toString()))
+ when (flag) {
+ PayStatus.INIT.toString() -> record.status = PayStatus.INIT
+ PayStatus.FAIL.toString() -> record.status = PayStatus.FAIL
+ PayStatus.SUC.toString() -> record.status = PayStatus.SUC
+ else -> record.status = PayStatus.INIT
+ }
+ record.upflag = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.TransdtlUnion.upflag.toString()))
+ return record
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/db/WhiteListDao.kt b/app/src/main/java/com/supwisdom/db/WhiteListDao.kt
new file mode 100644
index 0000000..a5dfcdd
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/db/WhiteListDao.kt
@@ -0,0 +1,84 @@
+package com.supwisdom.db
+
+import android.content.ContentValues
+import android.content.Context
+import android.database.Cursor
+import com.supwisdom.entity.WhiteListRecord
+import java.util.concurrent.locks.Lock
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class WhiteListDao constructor(context: Context) {
+ private val dbHelper = DBParaHelper.getInstance(context)
+ private val TABLE = DBParaHelper.TABLE_NAME_WHITELIST
+
+ fun getLock(): Lock {
+ return dbHelper.getLock()
+ }
+
+ fun replace(list: List<WhiteListRecord>): Boolean {
+ val db = dbHelper.readableDatabase
+ try {
+ db.beginTransaction()
+ list.forEach {
+ val values = getContentValues(it)
+ if (db.replace(TABLE, null, values) < 0) {
+ return false
+ }
+ }
+ db.setTransactionSuccessful()
+ return true
+ } finally {
+ db.endTransaction()
+ }
+ }
+
+ fun get(cardphyid: String, cardno: String): WhiteListRecord? {
+ val db = dbHelper.readableDatabase
+ var cursor: Cursor? = null
+ val selection = BeanPropEnum.WhiteList.cardphyid.toString() + "=? and " + BeanPropEnum.WhiteList.cardno + "=?"
+ try {
+ cursor = db.query(TABLE, null, selection, arrayOf(cardphyid, cardno), null, null, null)
+ if (cursor != null && cursor.moveToNext()) {
+ return getRecord(cursor)
+ }
+ } finally {
+ cursor?.close()
+ }
+ return null
+ }
+
+ fun clear(): Boolean {
+ val db = dbHelper.writableDatabase
+ try {
+ db.beginTransaction()
+ if (db.delete(TABLE, null, null) < 0) {
+ return false
+ }
+ db.setTransactionSuccessful()
+ return true
+ } finally {
+ db.endTransaction()
+ }
+ }
+
+ private fun getRecord(cursor: Cursor): WhiteListRecord {
+ val record = WhiteListRecord()
+ record.cardphyid = cursor.getString(cursor.getColumnIndex(BeanPropEnum.WhiteList.cardphyid.toString()))
+ record.cardno = cursor.getString(cursor.getColumnIndex(BeanPropEnum.WhiteList.cardno.toString()))
+ record.flag = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.WhiteList.flag.toString()))
+ record.balance = cursor.getInt(cursor.getColumnIndex(BeanPropEnum.WhiteList.balance.toString()))
+ return record
+ }
+
+ private fun getContentValues(record: WhiteListRecord): ContentValues {
+ val values = ContentValues()
+ values.put(BeanPropEnum.WhiteList.cardphyid.toString(), record.cardphyid)
+ values.put(BeanPropEnum.WhiteList.cardno.toString(), record.cardno)
+ values.put(BeanPropEnum.WhiteList.flag.toString(), record.flag)
+ values.put(BeanPropEnum.WhiteList.balance.toString(), record.balance)
+ return values
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/entity/ConfigParaRecord.kt b/app/src/main/java/com/supwisdom/entity/ConfigParaRecord.kt
new file mode 100644
index 0000000..4b536ac
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/entity/ConfigParaRecord.kt
@@ -0,0 +1,16 @@
+package com.supwisdom.entity
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc 本地配置参数
+ **/
+class ConfigParaRecord {
+ var mode: Int = 0//
+ var devphyid: String? = null
+ var epayIP: String? = null
+ var epayPort: Int = 0
+ var epayUri: String? = null
+ var shopPwd: String? = null //商户密码
+
+ var initOK: Boolean = false //是否初始化 true--未初始化,false--已初始化
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/entity/ControlParaRecord.kt b/app/src/main/java/com/supwisdom/entity/ControlParaRecord.kt
new file mode 100644
index 0000000..7e1ff12
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/entity/ControlParaRecord.kt
@@ -0,0 +1,19 @@
+package com.supwisdom.entity
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc 本地控制参数
+ **/
+class ControlParaRecord {
+ constructor() {
+
+ }
+
+ constructor(paraname: String, paraval: String) {
+ this.paraname = paraname
+ this.paraval = paraval
+ }
+
+ var paraname: String? = null
+ var paraval: String? = null
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/entity/DynamicParaRecord.kt b/app/src/main/java/com/supwisdom/entity/DynamicParaRecord.kt
new file mode 100644
index 0000000..bee1dbe
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/entity/DynamicParaRecord.kt
@@ -0,0 +1,21 @@
+package com.supwisdom.entity
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc 后台动态参数
+ **/
+class DynamicParaRecord {
+ var appid: String? = null
+ var appsecret: String? = null
+ var deviceid: Int = 0 // 设备ID
+ var merchaccno: Int = 0 //商户号
+ var shopname: String? = null //商户名
+ var paraverno: Int = 0//参数版本
+ var paragroupid: Int = 0//参数组id
+ var onlineseqno: Int = 0 //后台最大联机流水号
+ var offlineseqno: Int = 0 //后台最大离线流水号
+ var cardverno: String? = null // 黑名单版本号 12byte
+ var jwt: String? = null
+ var token: String? = null
+ var jwtExpire: String? = null //jwt有效期 yyyyMMddhhmmss
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/entity/SysParaRecord.kt b/app/src/main/java/com/supwisdom/entity/SysParaRecord.kt
new file mode 100644
index 0000000..65e1640
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/entity/SysParaRecord.kt
@@ -0,0 +1,20 @@
+package com.supwisdom.entity
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc 后台系统参数
+ **/
+class SysParaRecord {
+ var returnFlag: Int = 0// 消费撤销开关 0bit -0x1表示冲正使能
+ var heatBeat: Int = 0// 心跳间隔
+ var offlineEnable: Boolean = false // 脱机消费时限开关 false-关闭, true-开启
+ var maxOfflineDays: Int = 0// 最大脱机天数
+ var mngPasswd: String? = null// 维护密码
+ var sucShowtime: Int = 0// 消费成功显示时间
+ var failShowtime: Int = 0 //消费失败显示时间
+ var commTime: Int = 0 //通讯超时时间 默认2s
+ /**
+ * 定额消费同卡消费间隔(s)
+ */
+ var fixpayGap: Int = 0
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/entity/TransdtlOfflineRecord.kt b/app/src/main/java/com/supwisdom/entity/TransdtlOfflineRecord.kt
new file mode 100644
index 0000000..ea0e3b4
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/entity/TransdtlOfflineRecord.kt
@@ -0,0 +1,23 @@
+package com.supwisdom.entity
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc 离线流水
+ **/
+class TransdtlOfflineRecord {
+ var devphyid: String? = null
+ var transdate: String? = null
+ var transtime: String? = null
+ var devseqno: Int = 0
+ var cardno: String? = null
+ var cardphyid: String? = null
+ var payamt: Int = 0
+ var extraamt: Int = 0
+ var managefeetype: String? = null // none,discount,mealer
+ var reversalflag: ReversalFlag? = null //消费none 手动撤销 manual
+ var reversalseqno: Int = 0 //被冲正流水号
+ var reversaltransdate: String? = null //被冲正流水日期
+ var reversaltranstime: String? = null //被冲正流水时间
+ var status: PayStatus? = null // init,fail,suc
+ var upflag: Int = 0 // 1已上传
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/entity/TransdtlOnlineRecord.kt b/app/src/main/java/com/supwisdom/entity/TransdtlOnlineRecord.kt
new file mode 100644
index 0000000..97cfa84
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/entity/TransdtlOnlineRecord.kt
@@ -0,0 +1,27 @@
+package com.supwisdom.entity
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc 联机流水
+ **/
+class TransdtlOnlineRecord {
+ var devphyid: String? = null
+ var transdate: String? = null
+ var transtime: String? = null
+ var devseqno: Int = 0
+ var cardno: String? = null
+ var cardphyid: String? = null
+ var qrcode: String? = null
+ var transtype: String? = null //card,code
+ var payamt: Int = 0
+ var extraamt: Int = 0
+ var managefeetype: String? = null // none,discount,mealer
+ var balance: Int? = null
+ var username: String? = null
+ // var userid: Int = 0
+ var billno: String? = null
+ var reversalflag: ReversalFlag? = null //消费none 自动冲正auto 手动撤销 manual
+ var reversalbillno: String? = null //被冲正交易参考号
+ var status: PayStatus? = null // init,fail,suc
+ var upflag: Int = 0 // 1已上传
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/entity/TransdtlUnionRecord.kt b/app/src/main/java/com/supwisdom/entity/TransdtlUnionRecord.kt
new file mode 100644
index 0000000..bc78c6f
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/entity/TransdtlUnionRecord.kt
@@ -0,0 +1,39 @@
+package com.supwisdom.entity
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class TransdtlUnionRecord {
+ var username: String? = null
+ var transdate: String? = null
+ var transtime: String? = null
+ var devseqno: Int = 0
+ var payway: String? = null //card,code,offcard
+ var reversalflag: ReversalFlag? = null //消费none 自动冲正auto 手动撤销 manual
+ var payamt: Int = 0
+ var status: PayStatus? = null // init,fail,suc
+ var upflag: Int = 0
+}
+
+/**
+ * NONE -- 正常消费
+ * AUTO -- 自动冲正
+ * MANUAL -- 手动撤销
+ */
+enum class ReversalFlag {
+ NONE,
+ AUTO,
+ MANUAL
+}
+
+/**
+ * INIT -- 初始化
+ * FAIL -- 支付失败
+ * SUC --支付成功
+ */
+enum class PayStatus {
+ INIT,
+ FAIL,
+ SUC
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/entity/WhiteListRecord.kt b/app/src/main/java/com/supwisdom/entity/WhiteListRecord.kt
new file mode 100644
index 0000000..bbda15c
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/entity/WhiteListRecord.kt
@@ -0,0 +1,12 @@
+package com.supwisdom.entity
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc 白名单
+ **/
+class WhiteListRecord {
+ var cardphyid: String? = null
+ var cardno: String? = null
+ var flag: Int = 0 // 0--白卡 1--黑卡
+ var balance: Int = 0
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/epaycard/ApduResponse.kt b/app/src/main/java/com/supwisdom/epaycard/ApduResponse.kt
new file mode 100644
index 0000000..ec0b7c7
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/epaycard/ApduResponse.kt
@@ -0,0 +1,40 @@
+package com.supwisdom.epaycard
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class ApduResponse constructor(val buffer: ByteArray) {
+ val sW1: Int
+ get() {
+ return buffer[buffer.size - 2].toInt() and 0xFF
+ }
+
+ val sW2: Int
+ get() {
+ return buffer[buffer.size - 1].toInt() and 0xFF
+ }
+
+ val sw: Int
+ get() {
+ return (sW1 shl 8) or sW2
+ }
+
+ val data: ByteArray
+ get() {
+ return buffer.copyOfRange(0, buffer.size - 2)
+ }
+
+ val bytes: ByteArray
+ get() {
+ return buffer
+ }
+
+ fun isOK(): Boolean {
+ return sW1 == 0x90 && sW2 == 0x00
+ }
+
+ fun swToString(): String {
+ return "%02X%02X".format(sW1, sW2)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/epaycard/CardBaseInfoBean.kt b/app/src/main/java/com/supwisdom/epaycard/CardBaseInfoBean.kt
new file mode 100644
index 0000000..c43d6d8
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/epaycard/CardBaseInfoBean.kt
@@ -0,0 +1,22 @@
+package com.supwisdom.epaycard
+
+import com.supwisdom.utils.decodeBCD
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class CardBaseInfoBean constructor(val data: ByteArray) {
+ val cardNo: String
+ get() {
+ return data.copyOfRange(39, 42).decodeBCD()
+ }
+ val idCard: String
+ get() {
+ return data.copyOfRange(43, 60).decodeBCD()
+ }
+ val expireDate: String
+ get() {
+ return data.copyOfRange(61, 64).decodeBCD()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/epaycard/Cardlib.kt b/app/src/main/java/com/supwisdom/epaycard/Cardlib.kt
new file mode 100644
index 0000000..4ee2bc0
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/epaycard/Cardlib.kt
@@ -0,0 +1,12 @@
+package com.supwisdom.epaycard
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class Cardlib {
+ companion object {
+ @JvmStatic
+ val instance: EpayCardlib = EpayCardlib()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/epaycard/DaliReader.kt b/app/src/main/java/com/supwisdom/epaycard/DaliReader.kt
new file mode 100644
index 0000000..4992921
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/epaycard/DaliReader.kt
@@ -0,0 +1,154 @@
+package com.supwisdom.epaycard
+
+import android.os.Build
+import com.newcapec.jni.ApduResp
+import com.newcapec.jni.ApduSend
+import com.newcapec.jni.Picc
+import com.supwisdom.exception.CardNotFoundError
+import com.supwisdom.exception.CardlibInitError
+import com.supwisdom.exception.CardlibValueError
+import com.supwisdom.utils.CommonUtil
+import com.supwisdom.utils.LogUtil
+import com.supwisdom.utils.encodeHex
+import com.supwisdom.utils.unsignedToInt
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class DaliReader {
+ private val TAG = "DaliReader"
+ private var cardTag = Picc.DetectInfo()
+ private var picc: Picc? = null
+
+ fun close() {
+ picc?.close()
+ picc = null
+ }
+
+ @Throws(CardlibInitError::class)
+ fun init() {
+ // CAP08S-V1.1.0.20181107 test-keys
+ //****设备固件版本>1.0.8c 使用新读卡驱动
+ /** 固件版本<=1.08 使用v108so ***/
+ /** 固件版本<=1.10 使用v110so ***/
+ /** 固件版本>=1.15 使用v115so ***/
+ /** 固件版本>=1.16 使用v116so ***/
+ val temp = Build.DISPLAY
+ val version = if (temp.contains("CAP08S-V1")) {
+ when {
+ temp < "CAP08S-V1.0.9" -> 108
+ temp < "CAP08S-V1.1.1" -> 110
+ else -> 115
+ }
+ } else {
+ /**
+ * v1.1.6
+ */
+ CommonUtil.getSerialNumber()?.replace("v", "")
+ ?.replace("V", "")
+ ?.replace(".", "")
+ ?.toInt() ?: 116
+ }
+ picc = Picc(version)
+ val ret = picc!!.open()
+ if (ret != 0) {
+ LogUtil.d(TAG, "A711Reader init error,ret=$ret")
+ throw CardlibInitError("加载卡库错误=$ret")
+ }
+ }
+
+ @Throws(CardNotFoundError::class)
+ fun requestCard(): String {
+ picc!!.remove('R'.toByte(), 0)
+ val ret = picc!!.detect('X'.toByte(), cardTag)
+ if (ret != 0) {
+ throw CardNotFoundError("寻卡错误=$ret")
+ }
+ val uidLen = cardTag.SerialInfo_Array[0].unsignedToInt()
+ val cardSN = cardTag.SerialInfo_Array.copyOfRange(1, 1 + uidLen)
+ return cardSN.encodeHex()
+ }
+
+ @Throws(CardlibValueError::class)
+ fun cpuApdu(cmd: ByteArray): ApduResponse {
+ val send = ApduSend()
+ val resp = ApduResp()
+ when {
+ cmd.size == 4 -> System.arraycopy(cmd, 0, send.Command, 0, 4)
+ cmd.size == 5 -> {
+ System.arraycopy(cmd, 0, send.Command, 0, 4)
+ send.Le = cmd[4].unsignedToInt().toShort()
+ if (0xB2 == cmd[1].unsignedToInt() &&
+ 0x84 == cmd[3].unsignedToInt()
+ ) {
+ //file 0x10
+ send.Le = 24
+ } else if (0xB2 == cmd[1].unsignedToInt() &&
+ 0x4C == cmd[3].unsignedToInt()
+ ) {
+ //file 0x09
+ send.Le = 37
+ }
+ }
+ else -> {
+ System.arraycopy(cmd, 0, send.Command, 0, 4)
+ send.Lc = cmd[4].unsignedToInt().toShort()
+ System.arraycopy(cmd, 5, send.DataIn, 0, send.Lc.toInt())
+ if (cmd.size > 5 + send.Lc) {
+ send.Le = cmd[5 + send.Lc].unsignedToInt().toShort()
+ }
+ }
+ }
+ var ret = picc!!.sendIsoCommand(0.toByte(), send, resp)
+ if (ret == 0) {
+ if (resp.SWA.unsignedToInt() == 0x61 &&
+ resp.SWB.unsignedToInt() > 0
+ ) {
+ var recv = ByteArray(resp.LenOut.toInt())
+ System.arraycopy(resp.DataOut, 0, recv, 0, resp.LenOut.toInt())
+ while (true) {
+ val innercmd = ByteArray(5)
+ innercmd[0] = 0x0
+ innercmd[1] = 0xC0.toByte()
+ innercmd[2] = 0x0
+ innercmd[3] = 0x0
+ innercmd[4] = resp.SWB
+ System.arraycopy(innercmd, 0, send.Command, 0, 4)
+ send.Le = innercmd[4].unsignedToInt().toShort()
+ send.Lc = 0
+ ret = picc!!.sendIsoCommand(0.toByte(), send, resp)
+ if (ret == 0) {
+ if (resp.SWA.unsignedToInt() == 0x61 &&
+ resp.SWB.unsignedToInt() > 0
+ ) {
+ val tmp = ByteArray(resp.LenOut.toInt() + recv.size)
+ System.arraycopy(recv, 0, tmp, 0, recv.size)
+ System.arraycopy(resp.DataOut, 0, tmp, recv.size, resp.LenOut.toInt())
+ recv = tmp
+ continue
+ } else {
+ val tmp = ByteArray(resp.LenOut.toInt() + recv.size + 2)
+ System.arraycopy(recv, 0, tmp, 0, recv.size)
+ System.arraycopy(resp.DataOut, 0, tmp, recv.size, resp.LenOut.toInt())
+ tmp[tmp.size - 2] = resp.SWA
+ tmp[tmp.size - 1] = resp.SWB
+ recv = tmp
+ return ApduResponse(recv)
+ }
+ } else {
+ throw CardlibValueError("交互失败,错误码=$ret")
+ }
+ }
+ } else {
+ val recv = ByteArray(resp.LenOut + 2)
+ System.arraycopy(resp.DataOut, 0, recv, 0, resp.LenOut.toInt())
+ recv[resp.LenOut.toInt()] = resp.SWA
+ recv[resp.LenOut + 1] = resp.SWB
+ return ApduResponse(recv)
+ }
+ }
+ LogUtil.d(TAG, "A711Reader cpuApdu error,ret=$ret")
+ throw CardlibValueError("交互失败,错误码=$ret")
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/epaycard/EpayCardlib.kt b/app/src/main/java/com/supwisdom/epaycard/EpayCardlib.kt
new file mode 100644
index 0000000..86f0b47
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/epaycard/EpayCardlib.kt
@@ -0,0 +1,49 @@
+package com.supwisdom.epaycard
+
+import com.supwisdom.exception.CardNotFoundError
+import com.supwisdom.exception.CardlibInitError
+import com.supwisdom.exception.CardlibValueError
+import com.supwisdom.utils.decodeHex
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class EpayCardlib {
+ private var reader = DaliReader()
+ private var hasInit = false
+
+ @Throws(CardlibInitError::class)
+ fun init() {
+ if (!hasInit) {
+ reader.init()
+ hasInit = true
+ }
+ }
+
+ @Throws(CardNotFoundError::class)
+ fun requestCard(): String {
+ return reader.requestCard()
+ }
+
+ @Throws(CardlibValueError::class)
+ fun readCard(): CardBaseInfoBean {
+ selectADF()
+ return readBaseInfo()
+ }
+
+ private fun selectADF() {
+ val res = reader.cpuApdu("00A40000023F00".decodeHex())
+ if (!res.isOK()) {
+ throw CardlibValueError("选应用错误:${res.swToString()}")
+ }
+ }
+
+ private fun readBaseInfo(): CardBaseInfoBean {
+ val res = reader.cpuApdu("00B0950047".decodeHex())
+ if (!res.isOK()) {
+ throw CardlibValueError("读基本信息错误:${res.swToString()}")
+ }
+ return CardBaseInfoBean(res.data)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/exception/AuthEpayError.kt b/app/src/main/java/com/supwisdom/exception/AuthEpayError.kt
new file mode 100644
index 0000000..70cab0a
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/exception/AuthEpayError.kt
@@ -0,0 +1,13 @@
+package com.supwisdom.exception
+
+/**
+ ** create by zzq on 2019/7/29
+ ** @desc
+ **/
+class AuthEpayError : Exception {
+ constructor(message: String, ex: Exception) : super(message + ex.message)
+
+ constructor(message: String) : super(message)
+
+ constructor(ex: Exception) : super(ex.message)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/exception/CardNotFoundError.kt b/app/src/main/java/com/supwisdom/exception/CardNotFoundError.kt
new file mode 100644
index 0000000..151ec03
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/exception/CardNotFoundError.kt
@@ -0,0 +1,13 @@
+package com.supwisdom.exception
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class CardNotFoundError : Exception {
+ constructor(message: String, ex: Exception) : super(message + ex.message)
+
+ constructor(message: String) : super(message)
+
+ constructor(ex: Exception) : super(ex.message)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/exception/CardPayCancelFailError.kt b/app/src/main/java/com/supwisdom/exception/CardPayCancelFailError.kt
new file mode 100644
index 0000000..5c34275
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/exception/CardPayCancelFailError.kt
@@ -0,0 +1,13 @@
+package com.supwisdom.exception
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class CardPayCancelFailError : Exception {
+ constructor(message: String, ex: Exception) : super(message + ex.message)
+
+ constructor(message: String) : super(message)
+
+ constructor(ex: Exception) : super(ex.message)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/exception/CardPayFailError.kt b/app/src/main/java/com/supwisdom/exception/CardPayFailError.kt
new file mode 100644
index 0000000..82e3c07
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/exception/CardPayFailError.kt
@@ -0,0 +1,13 @@
+package com.supwisdom.exception
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class CardPayFailError : Exception {
+ constructor(message: String, ex: Exception) : super(message + ex.message)
+
+ constructor(message: String) : super(message)
+
+ constructor(ex: Exception) : super(ex.message)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/exception/CardlibInitError.kt b/app/src/main/java/com/supwisdom/exception/CardlibInitError.kt
new file mode 100644
index 0000000..188df3b
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/exception/CardlibInitError.kt
@@ -0,0 +1,13 @@
+package com.supwisdom.exception
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class CardlibInitError : Exception {
+ constructor(message: String, ex: Exception) : super(message + ex.message)
+
+ constructor(message: String) : super(message)
+
+ constructor(ex: Exception) : super(ex.message)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/exception/CardlibValueError.kt b/app/src/main/java/com/supwisdom/exception/CardlibValueError.kt
new file mode 100644
index 0000000..09e239e
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/exception/CardlibValueError.kt
@@ -0,0 +1,13 @@
+package com.supwisdom.exception
+
+/**
+ ** create by zzq on 2019/7/25
+ ** @desc
+ **/
+class CardlibValueError : Exception {
+ constructor(message: String, ex: Exception) : super(message + ex.message)
+
+ constructor(message: String) : super(message)
+
+ constructor(ex: Exception) : super(ex.message)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/exception/HeartBeatError.kt b/app/src/main/java/com/supwisdom/exception/HeartBeatError.kt
new file mode 100644
index 0000000..dcaa874
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/exception/HeartBeatError.kt
@@ -0,0 +1,13 @@
+package com.supwisdom.exception
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+class HeartBeatError : Exception {
+ constructor(message: String, ex: Exception) : super(message + ex.message)
+
+ constructor(message: String) : super(message)
+
+ constructor(ex: Exception) : super(ex.message)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/exception/SysParaError.kt b/app/src/main/java/com/supwisdom/exception/SysParaError.kt
new file mode 100644
index 0000000..1cdceb3
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/exception/SysParaError.kt
@@ -0,0 +1,13 @@
+package com.supwisdom.exception
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+class SysParaError : Exception {
+ constructor(message: String, ex: Exception) : super(message + ex.message)
+
+ constructor(message: String) : super(message)
+
+ constructor(ex: Exception) : super(ex.message)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/exception/TransdtlUploadError.kt b/app/src/main/java/com/supwisdom/exception/TransdtlUploadError.kt
new file mode 100644
index 0000000..ce3e7ef
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/exception/TransdtlUploadError.kt
@@ -0,0 +1,13 @@
+package com.supwisdom.exception
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+class TransdtlUploadError : Exception {
+ constructor(message: String, ex: Exception) : super(message + ex.message)
+
+ constructor(message: String) : super(message)
+
+ constructor(ex: Exception) : super(ex.message)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/exception/WhiteListError.kt b/app/src/main/java/com/supwisdom/exception/WhiteListError.kt
new file mode 100644
index 0000000..9c9033a
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/exception/WhiteListError.kt
@@ -0,0 +1,13 @@
+package com.supwisdom.exception
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+class WhiteListError : Exception {
+ constructor(message: String, ex: Exception) : super(message + ex.message)
+
+ constructor(message: String) : super(message)
+
+ constructor(ex: Exception) : super(ex.message)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/okhttp/ICallBackok.kt b/app/src/main/java/com/supwisdom/okhttp/ICallBackok.kt
new file mode 100644
index 0000000..0620933
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/okhttp/ICallBackok.kt
@@ -0,0 +1,9 @@
+package com.supwisdom.okhttp
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+interface ICallBackok<T> {
+ fun callback(t: T)
+}
diff --git a/app/src/main/java/com/supwisdom/okhttp/NetworkHandler.kt b/app/src/main/java/com/supwisdom/okhttp/NetworkHandler.kt
new file mode 100644
index 0000000..bf93d9b
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/okhttp/NetworkHandler.kt
@@ -0,0 +1,278 @@
+package com.supwisdom.okhttp
+
+import android.text.TextUtils
+import okhttp3.*
+import java.io.IOException
+import java.io.UnsupportedEncodingException
+import java.security.SecureRandom
+import java.security.cert.CertificateException
+import java.security.cert.X509Certificate
+import java.util.concurrent.TimeUnit
+import javax.net.ssl.*
+import com.supwisdom.okhttp.ICallBackok as ICallBack1
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+@Suppress("DEPRECATION")
+class NetworkHandler private constructor() {
+ companion object {
+ private var instance: NetworkHandler? = null
+ fun getInstance(): NetworkHandler {
+ if (instance == null) {
+ synchronized(NetworkHandler::class.java) {
+ if (instance == null) {
+ instance = NetworkHandler()
+ }
+ }
+ }
+ return instance!!
+ }
+ }
+
+ private var client: OkHttpClient? = null
+ private var clientLong: OkHttpClient
+ private val JSON = MediaType.parse("application/json; charset=utf-8")
+ private val FORM_ENCODE = MediaType.parse("application/x-www-form-urlencoded;charset=utf-8")
+ private var commTime = 2
+ private var clientId: String? = null
+ private var jwt: String? = null
+
+ init {
+ client = OkHttpClient()
+ .newBuilder()
+ .retryOnConnectionFailure(false)
+ .readTimeout(commTime.toLong(), TimeUnit.SECONDS)
+ .writeTimeout(1, TimeUnit.SECONDS)
+ .connectTimeout(commTime.toLong(), TimeUnit.SECONDS)
+ .hostnameVerifier(TrustAllHostnameVerifier())
+ .sslSocketFactory(createSSLSocketFactory()!!)
+ .build()
+ clientLong = OkHttpClient()
+ .newBuilder()
+ .retryOnConnectionFailure(false)
+ .readTimeout(35, TimeUnit.SECONDS)
+ .writeTimeout(1, TimeUnit.SECONDS)
+ .connectTimeout(3, TimeUnit.SECONDS)
+ .hostnameVerifier(TrustAllHostnameVerifier())
+ .sslSocketFactory(createSSLSocketFactory())
+ .build()
+
+ }
+
+ fun setCommTime(communicateTime: Int) {
+ if (communicateTime != 0 && commTime != communicateTime) {
+ this.commTime = communicateTime
+ client = OkHttpClient()
+ .newBuilder()
+ .retryOnConnectionFailure(false)
+ .readTimeout(commTime.toLong(), TimeUnit.SECONDS)
+ .writeTimeout(1, TimeUnit.SECONDS)
+ .connectTimeout(commTime.toLong(), TimeUnit.SECONDS)
+ .hostnameVerifier(TrustAllHostnameVerifier())
+ .sslSocketFactory(createSSLSocketFactory())
+ .build()
+ }
+ }
+
+ fun setClientId(clientId: String?) {
+ this.clientId = clientId
+ }
+
+ fun setJwt(jwt: String?) {
+ if (TextUtils.isEmpty(jwt)) {
+ this.jwt = jwt
+ } else {
+ this.jwt = "Bearer $jwt"
+ }
+ }
+
+ private class TrustAllCerts : X509TrustManager {
+ @Throws(CertificateException::class)
+ override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {
+ }
+
+ @Throws(CertificateException::class)
+ override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) {
+ }
+
+ override fun getAcceptedIssuers(): Array<X509Certificate> {
+ return arrayOf<X509Certificate>()
+ }
+ }
+
+ private class TrustAllHostnameVerifier : HostnameVerifier {
+ override fun verify(hostname: String, session: SSLSession): Boolean {
+ return true
+ }
+ }
+
+ private fun createSSLSocketFactory(): SSLSocketFactory? {
+ var ssfFactory: SSLSocketFactory? = null
+ try {
+ val sc = SSLContext.getInstance("TLS")
+ sc.init(null, arrayOf<TrustManager>(TrustAllCerts()), SecureRandom())
+ ssfFactory = sc.socketFactory
+ } catch (e: Exception) {
+ }
+
+ return ssfFactory
+ }
+
+ private fun addExtentHeader(request: Request.Builder): Request.Builder {
+ if (!TextUtils.isEmpty(clientId)) {
+ request.addHeader("X-TENANT-ID", clientId)
+ }
+ if (!TextUtils.isEmpty(jwt)) {
+ request.addHeader("Authorization", jwt)
+ }
+ return request
+ }
+
+ fun get(url: String, params: WebParams?): TransResp? {
+ val request = Request.Builder()
+ .url(geturl(url, params))
+ .addHeader("Accept", "application/json; q=0.5")
+ .addHeader("Connection", "close")
+ return getTransResp(addExtentHeader(request).build())
+ }
+
+ fun get(url: String, params: WebParams, callback: com.supwisdom.okhttp.ICallBackok<Any?>) {
+ val request = Request.Builder()
+ .url(geturl(url, params))
+ .addHeader("Accept", "application/json; q=0.5")
+ .addHeader("Connection", "close")
+ client!!.newCall(addExtentHeader(request).build()).enqueue(object : Callback {
+ override fun onFailure(call: Call, e: IOException) {
+ callback.callback(null)
+ }
+
+ override fun onResponse(call: Call, response: Response) {
+ try {
+ val content = response.body()!!.string()
+ val resp = TransResp(response.code(), response.message())
+ if (response.isSuccessful) {
+ resp.retjson = content
+ }
+ callback.callback(resp)
+ } catch (e: Exception) {
+ e.printStackTrace()
+ callback.callback(null)
+ }
+
+ }
+ })
+ }
+
+ fun post(url: String, params: WebParams): TransResp? {
+ val builder = FormBody.Builder()
+ for (name in params.allParameterNames()) {
+ builder.add(name, params.getParameterString(name))
+ }
+ val request = Request.Builder()
+ .url(url)
+ .addHeader("Accept", "application/json; q=0.5")
+ .addHeader("Connection", "close")
+ .post(builder.build())
+ return getTransResp(addExtentHeader(request).build())
+ }
+
+ fun longPost(url: String, params: WebParams): TransResp? {
+ val builder = FormBody.Builder()
+ for (name in params.allParameterNames()) {
+ builder.add(name, params.getParameterString(name))
+ }
+ val request = Request.Builder()
+ .url(url)
+ .addHeader("Accept", "application/json; q=0.5")
+ .addHeader("Connection", "close")
+ .post(builder.build())
+ return getLongTransResp(addExtentHeader(request).build())
+ }
+
+ fun post(url: String, json: String): TransResp? {
+ val body = RequestBody.create(JSON, json)
+ val request = Request.Builder()
+ .url(url)
+ .addHeader("Accept", "application/json; q=0.5")
+ .addHeader("Connection", "close")
+ .post(body)
+ return getTransResp(addExtentHeader(request).build())
+ }
+
+ fun post(url: String, json: String, callback: com.supwisdom.okhttp.ICallBackok<Any?>) {
+ val body = RequestBody.create(JSON, json)
+ val request = Request.Builder()
+ .url(url)
+ .addHeader("Accept", "application/json; q=0.5")
+ .addHeader("Connection", "close")
+ .post(body)
+ client!!.newCall(addExtentHeader(request).build()).enqueue(object : Callback {
+ override fun onFailure(call: Call, e: IOException) {
+ callback.callback(null)
+ }
+
+ override fun onResponse(call: Call, response: Response) {
+ try {
+ val content = response.body()!!.string()
+ val resp = TransResp(response.code(), response.message())
+ if (response.isSuccessful) {
+ resp.retjson = content
+ }
+ callback.callback(resp)
+ } catch (e: Exception) {
+ callback.callback(null)
+ }
+
+ }
+ })
+ }
+
+ private fun getLongTransResp(request: Request): TransResp? {
+ return try {
+ val response = clientLong.newCall(request).execute()
+ /*响应主体只能被消耗一次*/
+ val content = response.body()!!.string()
+ val resp = TransResp(response.code(), response.message())
+ if (response.isSuccessful) {
+ resp.retjson = content
+ }
+ resp
+ } catch (e: Exception) {
+ e.printStackTrace()
+ null
+ }
+
+ }
+
+ private fun getTransResp(request: Request): TransResp? {
+ return try {
+ val response = client!!.newCall(request).execute()
+ /*响应主体只能被消耗一次*/
+ val content = response.body()!!.string()
+ val resp = TransResp(response.code(), response.message())
+ if (response.isSuccessful) {
+ resp.retjson = content
+ }
+ resp
+ } catch (e: Exception) {
+ e.printStackTrace()
+ //通讯超时
+ null
+ }
+ }
+
+ private fun geturl(url: String, params: WebParams?): String {
+ val sb = StringBuilder()
+ sb.append(url)
+ if (params != null) {
+ try {
+ sb.append(params.encodeURL())
+ } catch (e: UnsupportedEncodingException) {
+ e.printStackTrace()
+ }
+ }
+ return sb.toString()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/okhttp/TransResp.kt b/app/src/main/java/com/supwisdom/okhttp/TransResp.kt
new file mode 100644
index 0000000..3215172
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/okhttp/TransResp.kt
@@ -0,0 +1,20 @@
+package com.supwisdom.okhttp
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+class TransResp constructor(retcode: Int, retmsg: String?) {
+ /**
+ * HTTP返回码 retcode 200 success
+ */
+ var retcode: Int = retcode
+ /**
+ * retmsg 返回消息,如果是200 则为空,非200则为返回错误信息
+ */
+ var retmsg: String? = retmsg
+ /**
+ * 返回json信息
+ */
+ var retjson: String? = null
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/okhttp/WebAPISession.kt b/app/src/main/java/com/supwisdom/okhttp/WebAPISession.kt
new file mode 100644
index 0000000..b695ed2
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/okhttp/WebAPISession.kt
@@ -0,0 +1,40 @@
+package com.supwisdom.okhttp
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+class WebAPISession : Cloneable {
+ /**
+ * appid,appsecret暂时写死在代码
+ */
+// private val appId = PublicDef.APP_ID
+// private val appSecret = PublicDef.APP_SECRET
+ private var termId = ""
+ private var epayurl = ""
+ private var sessionKey: String? = null
+
+ fun getEpayurl(): String {
+ return epayurl
+ }
+
+ fun setEpayurl(epayurl: String) {
+ this.epayurl = epayurl
+ }
+
+ @Throws(CloneNotSupportedException::class)
+ override fun clone(): Any {
+ val another = WebAPISession()
+ another.termId = this.termId
+ another.sessionKey = this.sessionKey
+ return another
+ }
+
+ fun getSessionKey(): String? {
+ return sessionKey
+ }
+
+ fun setSessionKey(sessionKey: String) {
+ this.sessionKey = sessionKey
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/okhttp/WebParams.kt b/app/src/main/java/com/supwisdom/okhttp/WebParams.kt
new file mode 100644
index 0000000..559123b
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/okhttp/WebParams.kt
@@ -0,0 +1,90 @@
+package com.supwisdom.okhttp
+
+import java.io.*
+import java.net.URLEncoder
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+class WebParams {
+ private val mParameters = hashMapOf<String, Any?>()
+
+ fun setParameter(name: String, value: String?): WebParams {
+ mParameters[name] = value
+ return this
+ }
+
+ fun setParameter(name: String, value: Int?): WebParams {
+ mParameters[name] = value?.toString()
+ return this
+ }
+
+ fun setParameter(name: String, value: Float?): WebParams {
+ mParameters[name] = value?.toString()
+ return this
+ }
+
+ fun getParameterString(name: String): String {
+ val ret = mParameters[name]
+ if (String::class.java.isInstance(ret)) {
+ return ret as String
+ } else if (Int::class.java.isInstance(ret)) {
+ return ret.toString()
+ } else if (Double::class.java.isInstance(ret)) {
+ return ret.toString()
+ }
+ return ""
+ }
+
+ fun getParameterInt(name: String): Int {
+ val ret = mParameters[name]
+ return if (Int::class.java.isInstance(ret)) {
+ ret as Int
+ } else 0
+ }
+
+ fun getParameterFloat(name: String): Float {
+ val ret = mParameters[name]
+ return if (Float::class.java.isInstance(ret)) {
+ ret as Float
+ } else 0f
+ }
+
+ fun removeParameter(name: String) {
+ if (mParameters.containsKey(name)) {
+ mParameters.remove(name)
+ }
+ }
+
+ @Throws(UnsupportedEncodingException::class)
+ fun encodeURL(): String {
+ val result = StringBuilder()
+ for (name in mParameters.keys) {
+ val value = mParameters[name]
+ result.append(URLEncoder.encode(name, "utf-8"))
+ .append("=")
+ .append(URLEncoder.encode(value.toString(), "utf-8"))
+ .append("&")
+ }
+ return result.toString()
+ }
+
+ @Throws(IOException::class)
+ fun encodeURL(output: OutputStream): Int {
+ val byteStream = DataOutputStream(output)
+ val writer = OutputStreamWriter(byteStream, "utf-8")
+ for (name in mParameters.keys) {
+ val value = mParameters[name]
+ writer.write(URLEncoder.encode(name, "utf-8"))
+ writer.write("=")
+ writer.write(URLEncoder.encode(value.toString(), "utf-8"))
+ writer.write("&")
+ }
+ return byteStream.size()
+ }
+
+ fun allParameterNames(): Set<String> {
+ return mParameters.keys
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/service/APIInterface.kt b/app/src/main/java/com/supwisdom/service/APIInterface.kt
new file mode 100644
index 0000000..b24df22
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/service/APIInterface.kt
@@ -0,0 +1,22 @@
+package com.supwisdom.service
+
+import com.supwisdom.entity.TransdtlOfflineRecord
+import com.supwisdom.entity.TransdtlOnlineRecord
+
+/**
+ ** create by zzq on 2019/7/23
+ ** @desc
+ **/
+interface APIInterface {
+ fun heartBeat()
+
+ fun linkCheck()
+
+ fun downloadSyspara(paragroupid: Int, paraverno: Int)
+
+ fun downloadWhitelist(maxCardverno: String)
+
+ fun uploadTransdtl(record: TransdtlOnlineRecord)
+
+ fun uploadTransdtl(record: TransdtlOfflineRecord)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/service/AuthEpay.kt b/app/src/main/java/com/supwisdom/service/AuthEpay.kt
new file mode 100644
index 0000000..fc252ae
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/service/AuthEpay.kt
@@ -0,0 +1,150 @@
+package com.supwisdom.service
+
+import android.text.TextUtils
+import com.supwisdom.activities.SPApplication
+import com.supwisdom.activities.YktSession
+import com.supwisdom.bean.AuthJwtRetBean
+import com.supwisdom.bean.AuthRetBean
+import com.supwisdom.bean.AuthTokenRetBean
+import com.supwisdom.exception.AuthEpayError
+import com.supwisdom.okhttp.NetworkHandler
+import com.supwisdom.okhttp.WebParams
+import com.supwisdom.utils.CryptUtil
+import com.supwisdom.utils.DateUtil
+import com.supwisdom.utils.GsonUtil
+import com.supwisdom.utils.PublicDef
+import org.apache.http.HttpStatus
+
+/**
+ ** create by zzq on 2019/7/23
+ ** @desc
+ **/
+class AuthEpay {
+ private val pos = SPApplication.getInstance().getPos()
+
+ @Throws(AuthEpayError::class)
+ fun login(): AuthRetBean {
+ val token = getAccessToken()
+ getAccessJwt(token)
+ return secureAuth()
+ }
+
+ @Throws(AuthEpayError::class)
+ fun refresh() {
+ val record = pos.getConfigPara()
+ val url = StringBuilder()
+ url.append(record!!.epayIP).append(":").append(record.epayPort)
+ .append("/").append(record.epayUri)
+ .append("/api/auth/refresh/").append(record.devphyid).append("?")
+ val resp = NetworkHandler.getInstance().get(url.toString(), null)
+ ?: throw AuthEpayError("jwt刷新请求超时")
+ if (resp.retcode != HttpStatus.SC_OK) {
+ throw AuthEpayError("jwt刷新错误码=${resp.retcode}")
+ }
+ val retBean = try {
+ GsonUtil.GsonToBean(resp.retjson!!, AuthJwtRetBean::class.java)
+ } catch (ex: Exception) {
+ throw AuthEpayError("jwt json异常:${ex.message}")
+ }
+ dealSession(retBean)
+ }
+
+ private fun getAccessToken(): String {
+ val record = pos.getConfigPara()
+ val url = StringBuilder()
+ url.append(record!!.epayIP).append(":").append(record.epayPort)
+ .append("/").append(record.epayUri)
+ .append("/api/auth/gettoken/").append(record.devphyid).append("?")
+ val params = WebParams()
+ params.setParameter("appid", pos.getDynamicPara()!!.appid)
+
+ NetworkHandler.getInstance().setClientId(record.devphyid!!)
+ NetworkHandler.getInstance().setJwt(null)
+
+ val resp = NetworkHandler.getInstance().get(url.toString(), params)
+ ?: throw AuthEpayError("token请求超时")
+ if (resp.retcode != HttpStatus.SC_OK) {
+ throw AuthEpayError("token错误码=${resp.retcode}")
+ }
+ val retBean = try {
+ GsonUtil.GsonToBean(resp.retjson!!, AuthTokenRetBean::class.java)
+ } catch (ex: Exception) {
+ throw AuthEpayError("token json异常:${ex.message}")
+ }
+ if (retBean.retcode != PublicDef.SUCCESS) {
+ throw AuthEpayError(retBean.retmsg!!)
+ }
+ if (TextUtils.isEmpty(retBean.token)) {
+ throw AuthEpayError("token不能为空")
+ }
+ return retBean.token!!
+ }
+
+ private fun getAccessJwt(token: String) {
+ val record = pos.getConfigPara()
+ val url = StringBuilder()
+ url.append(record!!.epayIP).append(":").append(record.epayPort)
+ .append("/").append(record.epayUri)
+ .append("/api/auth/authentication/").append(record.devphyid).append("?")
+
+ val secret = CryptUtil.HMACSHA256(pos.getDynamicPara()!!.appsecret!!, token)
+ val params = WebParams()
+ params.setParameter("appid", pos.getDynamicPara()!!.appid)
+ .setParameter("secret", secret)
+
+ val resp = NetworkHandler.getInstance().get(url.toString(), params)
+ ?: throw AuthEpayError("jwt请求超时")
+ if (resp.retcode != HttpStatus.SC_OK) {
+ throw AuthEpayError("jwt错误码=${resp.retcode}")
+ }
+ val retBean = try {
+ GsonUtil.GsonToBean(resp.retjson!!, AuthJwtRetBean::class.java)
+ } catch (ex: Exception) {
+ throw AuthEpayError("jwt json异常:${ex.message}")
+ }
+ dealSession(retBean)
+ }
+
+ private fun secureAuth(): AuthRetBean {
+ val dyRecord = pos.getDynamicPara()
+ val cardverno = dyRecord!!.cardverno ?: "0"
+ val params = WebParams()
+ params.setParameter("devphyid", pos.getConfigPara()!!.devphyid)
+ .setParameter("termdate", DateUtil.getNowDateNoFormat())
+ .setParameter("termtime", DateUtil.getNowTimeNoFormat())
+ .setParameter("paragroupid", dyRecord.paragroupid)
+ .setParameter("cardverno", cardverno)
+
+ val resp = YktSession.getInstance().sendYktRequestPost("/api/pos/login", "", params)
+ ?: throw AuthEpayError("请求超时")
+ if (resp.retcode != HttpStatus.SC_OK) {
+ throw AuthEpayError("错误码=${resp.retcode}")
+ }
+ val retBean = try {
+ GsonUtil.GsonToBean(resp.retjson!!, AuthRetBean::class.java)
+ } catch (ex: Exception) {
+ throw AuthEpayError("json异常:${ex.message}")
+ }
+ if (retBean.retcode != PublicDef.SUCCESS) {
+ throw AuthEpayError(retBean.retmsg!!)
+ }
+ return retBean
+ }
+
+ private fun dealSession(bean: AuthJwtRetBean) {
+ if (bean.retcode != PublicDef.SUCCESS) {
+ throw AuthEpayError(bean.retmsg!!)
+ }
+ if (TextUtils.isEmpty(bean.jwt)) {
+ throw AuthEpayError("jwt不能为空")
+ }
+ NetworkHandler.getInstance().setJwt(bean.jwt!!)
+
+ val dyRecord = pos.getDynamicPara()
+ dyRecord!!.jwt = bean.jwt
+ dyRecord.jwtExpire = DateUtil.utcToLocal(bean.expiredAt!!)
+ if (!pos.replaceDynamicPara(dyRecord)) {
+ throw AuthEpayError("保存参数失败")
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/service/BackgroundTaskService.kt b/app/src/main/java/com/supwisdom/service/BackgroundTaskService.kt
new file mode 100644
index 0000000..8a7c9f7
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/service/BackgroundTaskService.kt
@@ -0,0 +1,137 @@
+package com.supwisdom.service
+
+import com.supwisdom.activities.SPApplication
+import com.supwisdom.entity.SysParaRecord
+import com.supwisdom.exception.AuthEpayError
+import com.supwisdom.exception.HeartBeatError
+import com.supwisdom.exception.TransdtlUploadError
+import com.supwisdom.utils.CommonUtil
+import com.supwisdom.utils.DateUtil
+import com.supwisdom.utils.FileUtil
+
+/**
+ ** create by zzq on 2019/7/23
+ ** @desc
+ **/
+class BackgroundTaskService : Thread() {
+ private val pos = SPApplication.getInstance().getPos()
+ private val websocketProcess = WebsocketProcess()
+ private var websocketHasRun = false
+ private var apiInterface: APIInterface? = null
+ private var sysRecord: SysParaRecord? = null
+ private var transdtlClearDate: String? = null
+
+ fun getWebsocketProcess(): WebsocketProcess {
+ return websocketProcess
+ }
+
+ override fun run() {
+ var heartgap = 0
+ CommonUtil.doSleep(60 * 1000)
+ while (true) {
+ val hasInit = pos.getConfigPara()?.initOK ?: false
+ if (hasInit) {
+ break
+ }
+ CommonUtil.doSleep(1000)
+ }
+ while (true) {
+ //做一卡通心跳和流水上传
+ heartAndTransdtl()
+ //清除流水
+ clearTransdtl()
+ sysRecord = pos.getSysPara()
+// if (sysRecord != null && sysRecord!!.getSocketSwitch() != 0) {
+// if (!websocketHasRun) {
+// websocketHasRun = true
+// websocketProcess.start()
+// }
+// } else {
+// if (websocketHasRun) {
+// websocketHasRun = false
+// websocketProcess.stop()
+// }
+// }
+ heartgap = if (sysRecord == null || sysRecord!!.heatBeat < 10 || sysRecord!!.heatBeat > 600) {
+ 60
+ } else {
+ sysRecord!!.heatBeat
+ }
+ CommonUtil.doSleep(heartgap * 1000)
+ }
+ }
+
+ private fun heartAndTransdtl() {
+ //做一卡通的心跳以及流水上传
+ try {
+ apiInterface!!.heartBeat()
+ SPApplication.getInstance().setEpayLinking(true)
+// /*更新通讯jwt*/
+ refreshJwt()
+ uploadTransdtl()
+ } catch (ex: HeartBeatError) {
+ SPApplication.getInstance().setEpayLinking(false)
+ }
+ }
+
+ private fun uploadTransdtl() {
+ try {
+ pos.getTransdtlOfflineUnconfirm().forEach {
+ apiInterface!!.uploadTransdtl(it)
+ it.upflag = 1
+ pos.updateTransdtlOffline(it)
+ }
+ pos.getTransdtlOnlineUnconfirm().forEach {
+ apiInterface!!.uploadTransdtl(it)
+ it.upflag = 1
+ pos.updateTransdtlOnline(it)
+ }
+ } catch (ex: TransdtlUploadError) {
+ ex.printStackTrace()
+ }
+ }
+
+ private fun refreshJwt() {
+ try {
+ val jwtExpire = pos.getDynamicPara()?.jwtExpire ?: "0"
+ if (jwtExpire < DateUtil.getNowDateTimeNoFormat()) {
+ autoAuth()
+ } else {
+ AuthEpay().refresh()
+ }
+ SPApplication.getInstance().setEpayLinking(true)
+ } catch (ex: AuthEpayError) {
+ ex.printStackTrace()
+ SPApplication.getInstance().setEpayLinking(false)
+ }
+ }
+
+ private fun autoAuth() {
+ val bean = AuthEpay().login()
+ val dyRecord = pos.getDynamicPara()
+ dyRecord!!.deviceid = bean.deviceid
+ dyRecord.merchaccno = bean.merchaccno
+ dyRecord.shopname = bean.shopname
+ dyRecord.onlineseqno = bean.onlineseqno
+ dyRecord.offlineseqno = bean.offlineseqno
+ dyRecord.paragroupid = bean.paragroupid
+ pos.replaceDynamicPara(dyRecord)
+ }
+
+ private fun clearTransdtl() {
+ val date = DateUtil.getDayDateNoFormatBefore(100)
+ if (date == transdtlClearDate) {
+ /*每天清除流水一次*/
+ return
+ }
+ pos.clearTransdtlOnline(date)
+ pos.clearTransdtlOffline(date)
+
+ transdtlClearDate = date
+
+ /*删除15天前的日志*/
+ FileUtil.removeLogFile(15)
+ FileUtil.removeCrashFile(15)
+ FileUtil.removeDtlFile(15)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/service/EpayApiImpl.kt b/app/src/main/java/com/supwisdom/service/EpayApiImpl.kt
new file mode 100644
index 0000000..517819d
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/service/EpayApiImpl.kt
@@ -0,0 +1,245 @@
+package com.supwisdom.service
+
+import com.supwisdom.activities.SPApplication
+import com.supwisdom.activities.YktSession
+import com.supwisdom.bean.HeartBeatRetBean
+import com.supwisdom.bean.SystemParaRetBean
+import com.supwisdom.bean.TransdtlRetBean
+import com.supwisdom.bean.WhiteListRetBean
+import com.supwisdom.entity.*
+import com.supwisdom.exception.HeartBeatError
+import com.supwisdom.exception.SysParaError
+import com.supwisdom.exception.TransdtlUploadError
+import com.supwisdom.exception.WhiteListError
+import com.supwisdom.okhttp.WebParams
+import com.supwisdom.utils.DateUtil
+import com.supwisdom.utils.GsonUtil
+import com.supwisdom.utils.PublicDef
+import org.apache.http.HttpStatus
+
+/**
+ ** create by zzq on 2019/7/23
+ ** @desc
+ **/
+class EpayApiImpl : APIInterface {
+ private val pos = SPApplication.getInstance().getPos()
+
+ @Throws(HeartBeatError::class)
+ override fun heartBeat() {
+ val dyRecord = pos.getDynamicPara()
+ val cardverno = dyRecord!!.cardverno ?: "0"
+ val params = WebParams()
+ params.setParameter("devphyid", pos.getConfigPara()!!.devphyid)
+ .setParameter("termdate", DateUtil.getNowDateNoFormat())
+ .setParameter("termtime", DateUtil.getNowTimeNoFormat())
+ .setParameter("paragroupid", dyRecord.paragroupid)
+ .setParameter("cardverno", cardverno)
+
+ val resp = YktSession.getInstance().sendYktRequestPost("/api/pos/heartbeat", "", params)
+ ?: throw HeartBeatError("请求超时")
+ if (resp.retcode != HttpStatus.SC_OK) {
+ throw HeartBeatError("错误码=${resp.retcode}")
+ }
+ val retBean = try {
+ GsonUtil.GsonToBean(resp.retjson!!, HeartBeatRetBean::class.java)
+ } catch (ex: Exception) {
+ throw HeartBeatError("json异常:${ex.message}")
+ }
+ if (retBean.retcode != PublicDef.SUCCESS) {
+ throw HeartBeatError(retBean.retmsg!!)
+ }
+ if (cardverno < retBean.cardverno!!) {
+ try {
+ downloadWhitelist(retBean.cardverno!!)
+ } catch (ex: WhiteListError) {
+ throw HeartBeatError(ex.message ?: "null")
+ }
+ }
+ if (dyRecord.paraverno != retBean.paraverno) {
+ try {
+ downloadSyspara(retBean.paragroupid, retBean.paraverno)
+ } catch (ex: SysParaError) {
+ throw SysParaError(ex.message ?: "null")
+ }
+ }
+ /**
+ * 时钟校准
+ */
+ NtpClient().startCalibrateTime(retBean.systime!!)
+ }
+
+ @Throws(HeartBeatError::class)
+ override fun linkCheck() {
+ heartBeat()
+ }
+
+ @Throws(SysParaError::class)
+ override fun downloadSyspara(paragroupid: Int, paraverno: Int) {
+ val params = WebParams()
+ params.setParameter("devphyid", pos.getConfigPara()!!.devphyid)
+ .setParameter("termdate", DateUtil.getNowDateNoFormat())
+ .setParameter("termtime", DateUtil.getNowTimeNoFormat())
+ .setParameter("paragroupid", paragroupid)
+
+ val resp = YktSession.getInstance().sendYktRequestPost("/api/pos/systempara", "", params)
+ ?: throw SysParaError("请求超时")
+ if (resp.retcode != HttpStatus.SC_OK) {
+ throw SysParaError("错误码=${resp.retcode}")
+ }
+ val retBean = try {
+ GsonUtil.GsonToBean(resp.retjson!!, SystemParaRetBean::class.java)
+ } catch (ex: Exception) {
+ throw SysParaError("json异常:${ex.message}")
+ }
+ if (retBean.retcode != PublicDef.SUCCESS) {
+ throw SysParaError(retBean.retmsg!!)
+ }
+ val record = pos.getSysPara() ?: SysParaRecord()
+ retBean.syspara?.forEach {
+ when {
+ it.paraname == "heat_beat" -> record.heatBeat = it.paraval!!.toInt()
+ it.paraname == "return_flag" -> record.returnFlag = it.paraval!!.toInt()
+ it.paraname == "consume_show_time" -> record.sucShowtime = it.paraval!!.toInt()
+ it.paraname == "consume_fail_show_time" -> record.failShowtime = it.paraval!!.toInt()
+ it.paraname == "fixpay_consume_gap" -> record.fixpayGap = it.paraval!!.toInt()
+ it.paraname == "manage_passwd" -> record.mngPasswd = it.paraval
+ it.paraname == "offline_flag" -> record.offlineEnable = it.paraval == "1"
+ it.paraname == "max_offline_days" -> record.maxOfflineDays = it.paraval!!.toInt()
+ it.paraname == "communicate_time" -> record.commTime = it.paraval!!.toInt()
+ }
+ }
+ if (!pos.replaceSysPara(record)) {
+ throw SysParaError("保存参数失败")
+ }
+ }
+
+ @Throws(WhiteListError::class)
+ override fun downloadWhitelist(maxCardverno: String) {
+ val maxcount = 20
+ do {
+ val params = WebParams()
+ params.setParameter("devphyid", pos.getConfigPara()!!.devphyid)
+ .setParameter("cardverno", pos.getDynamicPara()!!.cardverno)
+ .setParameter("maxcount", maxcount)
+
+ val resp = YktSession.getInstance().sendYktRequestPost("/api/pos/whitelist", "", params)
+ ?: throw WhiteListError("请求超时")
+ if (resp.retcode != HttpStatus.SC_OK) {
+ throw WhiteListError("错误码=${resp.retcode}")
+ }
+ val retBean = try {
+ GsonUtil.GsonToBean(resp.retjson!!, WhiteListRetBean::class.java)
+ } catch (ex: Exception) {
+ throw WhiteListError("json异常:${ex.message}")
+ }
+ if (retBean.retcode != PublicDef.SUCCESS) {
+ throw WhiteListError(retBean.retmsg!!)
+ }
+ if (retBean.count != retBean.whitelist?.size) {
+ throw WhiteListError("白名单数量不对[${retBean.count},${retBean.whitelist?.size}]")
+ }
+ val list = ArrayList<WhiteListRecord>()
+ retBean.whitelist?.forEach {
+ val record = WhiteListRecord()
+ record.cardphyid = it.cardphyid
+ record.cardno = it.cardno
+ record.flag = it.flag
+ record.balance = it.balance
+ list.add(record)
+ }
+ if (!pos.saveWhiteList(list)) {
+ throw WhiteListError("保存白名单失败")
+ }
+ val dyRecord = pos.getDynamicPara()
+ dyRecord!!.cardverno = retBean.cardverno
+ if (!pos.replaceDynamicPara(dyRecord)) {
+ throw WhiteListError("保存参数失败")
+ }
+ } while (retBean.count == maxcount)
+ }
+
+ @Throws(TransdtlUploadError::class)
+ override fun uploadTransdtl(record: TransdtlOnlineRecord) {
+ var reversalflag = "false"
+ if (record.reversalflag == ReversalFlag.AUTO ||
+ record.reversalflag == ReversalFlag.MANUAL
+ ) {
+ reversalflag = "true"
+ }
+
+ val params = WebParams()
+ params.setParameter("devphyid", record.devphyid)
+ .setParameter("transdate", record.transdate)
+ .setParameter("transtime", record.transtime)
+ .setParameter("termseqno", record.devseqno)
+ .setParameter("cardno", record.cardno)
+ .setParameter("cardphyid", record.cardphyid)
+ .setParameter("qrcode", record.qrcode)
+ .setParameter("transtype", record.transtype)
+ .setParameter("amount", record.payamt)
+ .setParameter("extraamt", record.extraamt)
+ .setParameter("managefeetype", record.managefeetype)
+ .setParameter("managefeetype", record.managefeetype)
+ .setParameter("billno", record.billno)
+ .setParameter("reversalflag", reversalflag)
+ .setParameter("status", record.status.toString())
+ val resp = YktSession.getInstance().sendYktRequestPost("/api/pos/paycancel", "", params)
+ ?: throw TransdtlUploadError("请求超时")
+ if (resp.retcode != HttpStatus.SC_OK) {
+ throw TransdtlUploadError("错误码=${resp.retcode}")
+ }
+ val retBean = try {
+ GsonUtil.GsonToBean(resp.retjson!!, TransdtlRetBean::class.java)
+ } catch (ex: Exception) {
+ throw TransdtlUploadError("json异常:${ex.message}")
+ }
+ if (retBean.retcode != PublicDef.SUCCESS) {
+ throw TransdtlUploadError(retBean.retmsg!!)
+ }
+ if (retBean.termseqno != record.devseqno) {
+ throw TransdtlUploadError("返回流水号不一致")
+ }
+ }
+
+ @Throws(TransdtlUploadError::class)
+ override fun uploadTransdtl(record: TransdtlOfflineRecord) {
+ val params = WebParams()
+ var reversalflag = "false"
+ if (record.reversalflag == ReversalFlag.AUTO ||
+ record.reversalflag == ReversalFlag.MANUAL
+ ) {
+ reversalflag = "true"
+ }
+ params.setParameter("devphyid", record.devphyid)
+ .setParameter("termseqno", record.devseqno)
+ .setParameter("transdate", record.transdate)
+ .setParameter("transtime", record.transtime)
+ .setParameter("cardno", record.cardno)
+ .setParameter("cardphyid", record.cardphyid)
+ .setParameter("amount", record.payamt)
+ .setParameter("extraamt", record.extraamt)
+ .setParameter("managefeetype", record.managefeetype)
+ .setParameter("reversalflag", reversalflag)
+ .setParameter("reversaltermseqno", record.reversalseqno)
+ .setParameter("reversaltransdate", record.reversaltransdate)
+ .setParameter("reversaltransdate", record.reversaltranstime)
+ .setParameter("status", record.status.toString())
+
+ val resp = YktSession.getInstance().sendYktRequestPost("/api/pos/offlinetransdtl", "", params)
+ ?: throw TransdtlUploadError("请求超时")
+ if (resp.retcode != HttpStatus.SC_OK) {
+ throw TransdtlUploadError("错误码=${resp.retcode}")
+ }
+ val retBean = try {
+ GsonUtil.GsonToBean(resp.retjson!!, TransdtlRetBean::class.java)
+ } catch (ex: Exception) {
+ throw TransdtlUploadError("json异常:${ex.message}")
+ }
+ if (retBean.retcode != PublicDef.SUCCESS) {
+ throw TransdtlUploadError(retBean.retmsg!!)
+ }
+ if (retBean.termseqno != record.devseqno) {
+ throw TransdtlUploadError("返回流水号不一致")
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/service/NtpClient.kt b/app/src/main/java/com/supwisdom/service/NtpClient.kt
new file mode 100644
index 0000000..2e4f3f0
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/service/NtpClient.kt
@@ -0,0 +1,120 @@
+package com.supwisdom.service
+
+import android.os.SystemClock
+import com.supwisdom.utils.DateUtil
+import com.supwisdom.utils.ThreadPool
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+class NtpClient {
+ private val NTP_TIME_OUT_MILLISECOND = 10000
+ /**
+ * 国内ntp服务器地址集
+ */
+ private val ntpServerHost = arrayOf("cn.pool.ntp.org", "tw.pool.ntp.org")
+ private var privatelServerHost: String? = null
+
+ fun setPrivatelServerHost(privatelServerHost: String) {
+ this.privatelServerHost = privatelServerHost
+ }
+
+ private fun getTimeFromNtpServer(ntpHost: String?): Long {
+ val client = SntpClient()
+ val isSuccessful = client.requestTime(ntpHost!!, NTP_TIME_OUT_MILLISECOND)
+ return if (isSuccessful) {
+ client.getNtpTime()
+ } else {
+ -1
+ }
+ }
+
+ /**
+ * @param synctime yyyyMMddHHmmss
+ */
+ fun startCalibrateTime(synctime: String) {
+ val time = DateUtil.dateFormatConvertToLong(synctime)
+ startCalibrateTime(time)
+ }
+
+ /**
+ * @param synctime ms
+ */
+ fun startCalibrateTime(synctime: Long) {
+ val localTime = System.currentTimeMillis()
+ if (synctime > 0) {
+ if (synctime > localTime && synctime - localTime > 60000) {
+ setCurrentTimeMillis(synctime)
+ } else if (localTime > synctime && localTime - synctime > 60000) {
+ setCurrentTimeMillis(synctime)
+ }
+ }
+ }
+
+ /**
+ * 开始校准时间
+ */
+ fun startCalibrateTime() {
+ ThreadPool.getShortPool().execute(Runnable {
+ /**
+ * 优先使用专网ntp服务器地址
+ */
+ /**
+ * 优先使用专网ntp服务器地址
+ */
+ if (privatelServerHost != null) {
+ val time = getTimeFromNtpServer(privatelServerHost)
+ if (time > 0) {
+ val isSetTimeSuccessful = setCurrentTimeMillis(time)
+ if (isSetTimeSuccessful) {
+ // LogUtil.d("set time successful");
+ return@Runnable
+ } else {
+ // LogUtil.d("set time failure");
+ }
+ }
+ }
+ for (itemHost in ntpServerHost) {
+ val time = getTimeFromNtpServer(itemHost)
+ if (time > 0) {
+ val isSetTimeSuccessful = setCurrentTimeMillis(time)
+ if (isSetTimeSuccessful) {
+ return@Runnable
+ } else {
+ // LogUtil.d("set time failure");
+ }
+ }
+ }
+ })
+ }
+
+ /**
+ * 设置当前的系统时间
+ *
+ * @param time
+ * @return true表示设置成功, false表示设置失败
+ */
+ // private Boolean setCurrentTimeMillis(long time) {
+ // try {
+ // TimeZone.setDefault(TimeZone.getTimeZone("GMT+8"));
+ // String datetime = CommonUtil.getDatetimeStringByLong(time);
+ // LogUtil.d("set time is: " + datetime);
+ // Process process = Runtime.getRuntime().exec("su");
+ // DataOutputStream os = new DataOutputStream(process.getOutputStream());
+ // //os.writeBytes("setprop persist.sys.timezone GMT\n");
+ // os.writeBytes("/system/bin/date -s " + datetime + "\n");
+ // os.writeBytes("clock -w\n");
+ // os.writeBytes("exit\n");
+ // os.flush();
+ // return true;
+ // } catch (Exception ex) {
+ // LogUtil.d("set time exception = " + CommonUtil.getExceptionStack(ex));
+ // ex.printStackTrace();
+ // return false;
+ // }
+ // }
+ private fun setCurrentTimeMillis(time: Long): Boolean {
+ return SystemClock.setCurrentTimeMillis(time)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/service/SntpClient.kt b/app/src/main/java/com/supwisdom/service/SntpClient.kt
new file mode 100644
index 0000000..d6e9ab9
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/service/SntpClient.kt
@@ -0,0 +1,202 @@
+package com.supwisdom.service
+
+import android.os.SystemClock
+import com.supwisdom.utils.unsignedToLong
+import java.net.DatagramPacket
+import java.net.DatagramSocket
+import java.net.InetAddress
+import kotlin.experimental.and
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc 时钟同步
+ **/
+class SntpClient {
+ /**
+ * 从ntp服务器中获取时间
+ * @param ntpHost ntp服务器域名地址
+ * @return 如果失败返回-1,否则返回当前的毫秒数
+ */
+ private val REFERENCE_TIME_OFFSET = 16
+ private val ORIGINATE_TIME_OFFSET = 24
+ private val RECEIVE_TIME_OFFSET = 32
+ private val TRANSMIT_TIME_OFFSET = 40
+ private val NTP_PACKET_SIZE = 48
+
+ private val NTP_PORT = 123
+ private val NTP_MODE_CLIENT = 3
+ private val NTP_VERSION = 3
+
+ // Number of seconds between Jan 1, 1900 and Jan 1, 1970
+ // 70 years plus 17 leap days
+ private val OFFSET_1900_TO_1970: Long = ((365L * 70L) + 17L) * 24L * 60L * 60L
+
+ // system time computed from NTP server response
+ private var mNtpTime: Long = 0
+
+ // value of SystemClock.elapsedRealtime() corresponding to mNtpTime
+ private var mNtpTimeReference: Long = 0
+
+ // round trip time in milliseconds
+ private var mRoundTripTime: Long = 0
+
+ /**
+ * Sends an SNTP request to the given host and processes the response.
+ *
+ * @param host host name of the server.
+ * @param timeout network timeout in milliseconds.
+ * @return true if the transaction was successful.
+ */
+ fun requestTime(host: String, timeout: Int): Boolean {
+ var socket: DatagramSocket? = null
+ try {
+ socket = DatagramSocket()
+ socket.soTimeout = timeout
+ val address: InetAddress = InetAddress.getByName(host)
+ val buffer = ByteArray(NTP_PACKET_SIZE)
+ val request = DatagramPacket(buffer, buffer.size, address, NTP_PORT)
+
+ // set mode = 3 (client) and version = 3
+ // mode is in low 3 bits of first byte
+ // version is in bits 3-5 of first byte
+// buffer[0] = NTP_MODE_CLIENT or (NTP_VERSION << 3)
+ buffer[0] = (NTP_MODE_CLIENT or (NTP_VERSION shl 3)).toByte()
+
+
+ // get current time and write it to the request packet
+ val requestTime = System.currentTimeMillis()
+ val requestTicks = SystemClock.elapsedRealtime()
+ writeTimeStamp(buffer, TRANSMIT_TIME_OFFSET, requestTime)
+
+ socket.send(request)
+
+ // read the response
+ val response = DatagramPacket(buffer, buffer.size)
+ socket.receive(response)
+ val responseTicks = SystemClock.elapsedRealtime()
+ val responseTime = requestTime + (responseTicks - requestTicks)
+
+ // extract the results
+ val originateTime = readTimeStamp(buffer, ORIGINATE_TIME_OFFSET)
+ val receiveTime = readTimeStamp(buffer, RECEIVE_TIME_OFFSET)
+ val transmitTime = readTimeStamp(buffer, TRANSMIT_TIME_OFFSET)
+ val roundTripTime = responseTicks - requestTicks - (transmitTime - receiveTime)
+ // receiveTime = originateTime + transit + skew
+ // responseTime = transmitTime + transit - skew
+ // clockOffset = ((receiveTime - originateTime) + (transmitTime - responseTime))/2
+ // = ((originateTime + transit + skew - originateTime) +
+ // (transmitTime - (transmitTime + transit - skew)))/2
+ // = ((transit + skew) + (transmitTime - transmitTime - transit + skew))/2
+ // = (transit + skew - transit + skew)/2
+ // = (2 * skew)/2 = skew
+ val clockOffset = ((receiveTime - originateTime) + (transmitTime - responseTime)) / 2
+ // save our results - use the times on this side of the network latency
+ // (response rather than request time)
+ mNtpTime = responseTime + clockOffset
+ mNtpTimeReference = responseTicks
+ mRoundTripTime = roundTripTime
+ } catch (ex: Exception) {
+ ex.printStackTrace()
+ return false
+ } finally {
+ socket?.close()
+ }
+ return true
+ }
+
+ /**
+ * Returns the time computed from the NTP transaction.
+ *
+ * @return time value computed from NTP server response.
+ */
+ fun getNtpTime(): Long {
+ return mNtpTime
+ }
+
+ /**
+ * Returns the reference clock value (value of SystemClock.elapsedRealtime())
+ * corresponding to the NTP time.
+ *
+ * @return reference clock corresponding to the NTP time.
+ */
+ fun getNtpTimeReference(): Long {
+ return mNtpTimeReference
+ }
+
+ /**
+ * Returns the round trip time of the NTP transaction
+ *
+ * @return round trip time in milliseconds.
+ */
+ fun getRoundTripTime(): Long {
+ return mRoundTripTime
+ }
+
+ /**
+ * Reads an unsigned 32 bit big endian number from the given offset in the buffer.
+ */
+ private fun read32(buffer: ByteArray, offset: Int): Long {
+ val b0 = buffer[offset]
+ val b1 = buffer[offset + 1]
+ val b2 = buffer[offset + 2]
+ val b3 = buffer[offset + 3]
+ // convert signed bytes to unsigned values
+ var i0 = b0.unsignedToLong()
+ if (b0 and 0x80.toByte() == 0x80.toByte()) {
+ i0 = ((b0 and 0x7F.toByte()) + 0x80.toByte()).toByte().unsignedToLong()
+ }
+ var i1 = b1.unsignedToLong()
+ if (b1 and 0x80.toByte() == 0x80.toByte()) {
+ i1 = ((b1 and 0x7F.toByte()) + 0x80.toByte()).toByte().unsignedToLong()
+ }
+ var i2 = b2.unsignedToLong()
+ if (b2 and 0x80.toByte() == 0x80.toByte()) {
+ i2 = ((b2 and 0x7F.toByte()) + 0x80.toByte()).toByte().unsignedToLong()
+ }
+ var i3 = b3.unsignedToLong()
+ if (b3 and 0x80.toByte() == 0x80.toByte()) {
+ i3 = ((b3 and 0x7F.toByte()) + 0x80.toByte()).toByte().unsignedToLong()
+ }
+// val i0 = (b0 and 0x80.toByte()) == 0x80 ? (b0 & 0x7F)+0x80 : b0)
+// val i1 = ((b1 & 0x80) == 0x80 ? (b1 & 0x7F)+0x80 : b1)
+// val i2 = ((b2 & 0x80) == 0x80 ? (b2 & 0x7F)+0x80 : b2)
+// val i3 = ((b3 & 0x80) == 0x80 ? (b3 & 0x7F)+0x80 : b3)
+
+ return (i0 shl 24) + (i1 shl 16) + (i2 shl 8) + i3
+ }
+
+ /**
+ * Reads the NTP time stamp at the given offset in the buffer and returns
+ * it as a system time (milliseconds since January 1, 1970).
+ */
+ private fun readTimeStamp(buffer: ByteArray, offset: Int): Long {
+ val seconds = read32(buffer, offset)
+ val fraction = read32(buffer, offset + 4)
+ return ((seconds - OFFSET_1900_TO_1970) * 1000) + ((fraction * 1000L) / 0x100000000L)
+ }
+
+ /**
+ * Writes system time (milliseconds since January 1, 1970) as an NTP time stamp
+ * at the given offset in the buffer.
+ */
+ private fun writeTimeStamp(buffer: ByteArray, offset: Int, time: Long) {
+ var tmpOffset = offset
+ var seconds = time / 1000L
+ val milliseconds = time - seconds * 1000L
+ seconds += OFFSET_1900_TO_1970
+
+ // write seconds in big endian format
+ buffer[tmpOffset++] = (seconds shr 24).toByte()
+ buffer[tmpOffset++] = (seconds shr 16).toByte()
+ buffer[tmpOffset++] = (seconds shr 8).toByte()
+ buffer[tmpOffset++] = (seconds shr 0).toByte()
+
+ val fraction = milliseconds * 0x100000000L / 1000L
+ // write fraction in big endian format
+ buffer[tmpOffset++] = (fraction shr 24).toByte()
+ buffer[tmpOffset++] = (fraction shr 16).toByte()
+ buffer[tmpOffset++] = (fraction shr 8).toByte()
+ // low order bits should be random data
+ buffer[tmpOffset] = (Math.random() * 255.0).toByte()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/service/WebsocketProcess.kt b/app/src/main/java/com/supwisdom/service/WebsocketProcess.kt
new file mode 100644
index 0000000..2a8ca33
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/service/WebsocketProcess.kt
@@ -0,0 +1,327 @@
+package com.supwisdom.service
+
+import android.os.Handler
+import android.os.Message
+import com.koushikdutta.async.callback.CompletedCallback
+import com.koushikdutta.async.future.Future
+import com.koushikdutta.async.http.AsyncHttpClient
+import com.koushikdutta.async.http.WebSocket
+import com.supwisdom.activities.SPApplication
+import com.supwisdom.db.Pos
+import com.supwisdom.utils.CommonUtil
+import com.supwisdom.utils.LogUtil
+
+/**
+ ** create by zzq on 2019/7/23
+ ** @desc
+ **/
+class WebsocketProcess {
+ private val TAG = "WebsocketProcess"
+ private var handler: Handler? = null
+ private var pos: Pos = SPApplication.getInstance().getPos()
+ private var websocketService: WebsocketService
+ private var isExit: Boolean = false
+ private var qrcodeThread: Thread? = null
+ @Volatile
+ private var isConnected: Boolean = false
+ @Volatile
+ private var connectDoing: Boolean = false
+ private var webSocket: Future<WebSocket>? = null
+ private var reLinkCnt: Int = 0
+ private var clientID = ""
+ @Volatile
+ private var hasRecv: Boolean = false
+ private var pingFailCnt: Int = 0
+
+ init {
+ websocketService = WebsocketService()
+ }
+
+ fun start() {
+ isExit = false
+ if (qrcodeThread == null) {
+ synchronized(WebsocketProcess::class.java) {
+ if (qrcodeThread == null) {
+ qrcodeThread = Thread(websocketService)
+ qrcodeThread!!.start()
+ }
+ }
+ }
+ clientID = SPApplication.getInstance().getPos().getConfigPara()!!.devphyid!!
+ }
+
+ fun setHandler(handler: Handler) {
+ this.handler = handler
+ }
+
+ fun stop() {
+ isExit = true
+ if (qrcodeThread != null) {
+ qrcodeThread!!.interrupt()
+ }
+ qrcodeThread = null
+ }
+
+ private inner class WebsocketService : Runnable {
+ override fun run() {
+ while (!isExit) {
+ CommonUtil.doSleep(1000)
+ if (!isConnected) {
+ if (!connectDoing) {
+ connectDoing = true
+ createNewWebsocket()
+ }
+ }
+ if (isConnected) {
+ try {
+ webSocket!!.get().ping(clientID)
+ } catch (e: Exception) {
+ e.printStackTrace()
+ pingFailCnt++
+ }
+
+ if (hasRecv) {
+ hasRecv = false
+ pingFailCnt = 0
+ } else {
+ pingFailCnt++
+ if (pingFailCnt > 10) {
+ isConnected = false
+ pingFailCnt = 0
+ }
+ }
+ }
+ }
+ if (webSocket != null) {
+ webSocket!!.cancel()
+ }
+ }
+ }
+
+// private fun getServerUrl(): String {
+// val sb = StringBuilder()
+// val url = YktSession.getInstance().getWebAPISession().getEpayurl()
+// val offset = url.lastIndexOf("/")
+// sb.append(url.substring(0, offset))
+// .append("/websocket/device_service")
+// return sb.toString()
+// }
+
+ private fun newWebsocket(url: String): Future<WebSocket> {
+ return AsyncHttpClient.getDefaultInstance().websocket(url, null,
+ AsyncHttpClient.WebSocketConnectCallback { ex, webSocket ->
+ if (ex != null) {
+ //网络断开
+ ex.printStackTrace()
+ connectDoing = false
+ isConnected = false
+ return@WebSocketConnectCallback
+ }
+ reLinkCnt = 0
+ isConnected = true
+ connectDoing = false
+// val loginStr = getLoginString()
+// webSocket.send(loginStr)
+ webSocket.stringCallback = WebSocket.StringCallback { s ->
+ // if (!CommonUtil.isEmpty(s)) {
+// try {
+// val retBean = GsonUtil.GsonToBean(s, WebsocketRetBean::class.java)
+// if (retBean.getRetcode() === PublicDef.SUCCESS) {
+// if ("login" == retBean.getAction()) {
+// val retData = WebsocketLoginRetData()
+// val data = retBean.getData() as JSONObject
+// retData.setHost_time(data["host_time"] as String?)
+// } else if ("qrpay_in_process" == retBean.getAction()) {
+// val retData = WebsockConsumeProcessRetBean()
+// val data = retBean.getData() as JSONObject
+// retData.setCustname(data["custname"] as String?)
+// retData.setStuempno(data["stuempno"] as String?)
+// retData.setClientid(data["clientid"] as String?)
+// retData.setDevphyid(data["devphyid"] as String?)
+// retData.setTransdatetime(data["transdatetime"] as String?)
+//
+// sendMsg(PublicDef.MSG_CONSUME_PAYING, "扫码付款中...")
+// webSocket.send(
+// getQRProcessResp(
+// retBean.getAction(),
+// retBean.getRequestid(),
+// retData
+// )
+// )
+// } else if ("qrpay_finish" == retBean.getAction()) {
+// val retData = WebsockConsumeFinishRetBean()
+// val data = retBean.getData() as JSONObject
+// retData.setCustname(data["custname"] as String?)
+// retData.setStuempno(data["stuempno"] as String?)
+// retData.setDevphyid(data["devphyid"] as String?)
+// retData.setRefno(data["refno"] as String?)
+// retData.setStatus(data["status"] as String?)
+// retData.setAmount(data["amount"] as Int?)
+// retData.setAvailbal(data["availbal"] as Int?)
+// retData.setTransdatetime(data["transdatetime"] as String?)
+//
+// if ("succ" == retData.getStatus()) {
+// val info = UserCardInfo(PublicDef.SUCCESS, "付款成功")
+// info.setDatetime(retData.getTransdatetime())
+// info.setUsername(retData.getCustname())
+// info.setStuempno(retData.getStuempno())
+// info.setPayamt(retData.getAmount())
+// info.setAmount(retData.getAmount())
+// info.setBalance(retData.getAvailbal())
+// info.setShowtime(pos.getSysPara().getSucShowtime())
+// info.setFlag(PublicDef.TRANSFLAG_NORMAL_CONSUME or PublicDef.TRANSFLAG_WRITE_CARD_SUCCESS)
+// info.setConsumeType(PublicDef.CONSUME_TYPE_BAR)
+// SPApplication.getInstance().setLastInfo(info)
+// sendMsg(PublicDef.MSG_CONSUME_QR_SUC, info)
+//
+// saveTransdtlOnline(info)
+// }
+// webSocket.send(
+// getQRSuccessResp(
+// retBean.getAction(),
+// retBean.getRequestid(),
+// retData
+// )
+// )
+// }
+// }
+// } catch (e: Exception) {
+// e.printStackTrace()
+// }
+//
+// }
+ }
+ webSocket.closedCallback = CompletedCallback {
+ //主动断网,关服务
+ // isConnected = false;
+ // connectDoing = false;
+ }
+ webSocket.endCallback = CompletedCallback {
+ //主动断网,关服务
+ // isConnected = false;
+ // connectDoing = false;
+ }
+ webSocket.pongCallback = WebSocket.PongCallback { hasRecv = true }
+ webSocket.setPingCallback { hasRecv = true }
+ })
+ }
+
+ private fun doSleep() {
+ reLinkCnt *= 2
+ if (reLinkCnt < 2 || reLinkCnt > 128) {
+ reLinkCnt = 2
+ }
+ CommonUtil.doSleep(reLinkCnt * 1000)
+ }
+
+// private fun buildServerUrl(clientId: String): String {
+// val nowtime = CommonUtil.getNowDateTimeNoFormat()
+// val signdata = StringBuilder()
+// signdata.append(PublicDef.APP_ID).append(clientId).append(nowtime)
+// val sign = Encrypt.HMACSHA1(signdata.toString(), PublicDef.APP_SECRET)
+//
+// val uri = StringBuilder()
+// uri.append("?local_time=").append(DateUtil.getNowDateTimeNoFormat()).append("&appid=")
+// .append(PublicDef.APP_ID)
+// .append("&clientid=").append(clientId).append("&sign=").append(sign)
+// return getServerUrl() + uri.toString()
+// }
+
+ private fun tryCloseWebsocket(sc: Future<WebSocket>?) {
+ if (sc != null) {
+ if (sc.cancel()) {
+ LogUtil.d(
+ TAG,
+ clientID + " websocket cancel fail,exception=" + CommonUtil.getExceptionStack(sc.tryGetException())
+ )
+ } else {
+ LogUtil.d(TAG, "$clientID websocket cancel success")
+ }
+ }
+ }
+
+ private fun createNewWebsocket() {
+ doSleep()
+ tryCloseWebsocket(webSocket)
+// webSocket = newWebsocket(buildServerUrl(clientID))
+ }
+
+// private fun getQRProcessResp(action: String, requestid: String, retData: WebsockConsumeProcessRetBean): String {
+// val data = WebsockConsumeProcessRespBean.Content()
+// data.setDevphyid(retData.getDevphyid())
+// val resp = WebsockConsumeProcessRespBean()
+// resp.setRetcode(PublicDef.SUCCESS)
+// resp.setRetmsg("推流成功")
+// resp.setAction(action)
+// resp.setRequestid(requestid)
+// resp.setData(data)
+// return GsonUtil.GsonString(resp)
+// }
+//
+// private fun getQRSuccessResp(action: String, requestid: String, retData: WebsockConsumeFinishRetBean): String {
+// val data = WebsockConsumeFinishRespBean.Content()
+// data.setDevphyid(retData.getDevphyid())
+// val resp = WebsockConsumeFinishRespBean()
+// resp.setRetcode(PublicDef.SUCCESS)
+// resp.setRetmsg("推流成功")
+// resp.setAction(action)
+// resp.setRequestid(requestid)
+// resp.setData(data)
+// return GsonUtil.GsonString(resp)
+// }
+//
+// fun getLoginString(): String {
+// val data = WebsocketLoginDataReqBean()
+// data.setClientid(clientID)
+// data.setLocal_time(CommonUtil.getNowDateTimeNoFormat())
+//
+// val req = WebsocketLoginReqBean()
+// req.setAction("login")
+// req.setNeedresp("true")
+// req.setRequestid(getRandom())
+// req.setData(data)
+// return GsonUtil.GsonString(req)
+// }
+//
+// private fun getRandom(): String {
+// val rand = Random()
+// rand.setSeed(System.currentTimeMillis())
+// return String.format("%010d", rand.nextInt(999999999))
+// }
+//
+// private fun saveTransdtlOnline(info: UserCardInfo): Boolean {
+// val record = TransdtlOnlineRecord()
+// var seqno = pos.getTransdtlOnlineSeqno()
+// if (seqno == 0) {
+// val ctlRecord = pos.getControlPara(PublicDef.CONTROL_TRANSDTLONL_SEQNO)
+// if (ctlRecord != null) {
+// seqno = Integer.valueOf(ctlRecord!!.getValue())
+// }
+// }
+// record.setDevseqno(seqno + 1)
+// record.setCustname(info.getUsername())
+// record.setStuempno(info.getStuempno())
+// record.setTransdate(info.getDatetime().substring(0, 8))
+// record.setTranstime(info.getDatetime().substring(8))
+// record.setDevphyid(pos.getConfigPara().getDevphyid())
+// record.setPayamt(info.getAmount())
+// record.setConsumetype(PublicDef.CONSUME_TYPE_BAR)
+// record.setFlag(PublicDef.TRANSFLAG_NORMAL_CONSUME or PublicDef.TRANSFLAG_WRITE_CARD_SUCCESS)
+// record.setUpflag(1)
+// return pos.saveTransdtlOnline(record)
+// }
+
+ private fun sendMsg(code: Int, o: Any) {
+ if (handler == null) {
+ return
+ }
+ try {
+ val msg = Message()
+ msg.what = code
+ msg.obj = o
+ handler!!.sendMessage(msg)
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/utils/AppExitUtil.kt b/app/src/main/java/com/supwisdom/utils/AppExitUtil.kt
new file mode 100644
index 0000000..d9f3f3a
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/utils/AppExitUtil.kt
@@ -0,0 +1,53 @@
+package com.supwisdom.utils
+
+import android.app.Activity
+import java.util.*
+
+/**
+ * @author zzq
+ * @date 2018/3/20.
+ * @version 1.0.1
+ * @desc : activity管理
+ */
+object AppExitUtil {
+ private val acys = HashSet<Activity>()
+
+ fun add(acy: Activity) {
+ acys.add(acy)
+ }
+
+ fun remove(acy: Activity) {
+ acys.remove(acy)
+ if (!acy.isFinishing) {
+ acy.finish()
+ }
+ if (acys.size == 0) {
+ killprocess()
+ }
+ }
+
+ fun exit() {
+ val iter = acys.iterator()
+ val arrs = arrayOfNulls<Activity>(acys.size)
+ var i = 0
+ while (iter.hasNext()) {
+ arrs[i] = iter.next()
+ i += 1
+ }
+ acys.clear()
+ for (j in arrs.indices) {
+ if (arrs[j] != null && !arrs[j]!!.isFinishing) {
+ arrs[j]!!.finish()
+ arrs[j] = null
+ }
+ }
+ killprocess()
+ }
+
+ private fun killprocess() {
+ ThreadPool.getShortPool().execute(Runnable {
+ CommonUtil.doSleep(2000)
+ android.os.Process.killProcess(android.os.Process.myPid())
+ })
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/utils/CommonUtil.kt b/app/src/main/java/com/supwisdom/utils/CommonUtil.kt
new file mode 100644
index 0000000..917f39c
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/utils/CommonUtil.kt
@@ -0,0 +1,194 @@
+@file:Suppress("DEPRECATION")
+
+package com.supwisdom.utils
+
+import android.annotation.SuppressLint
+import android.app.Activity
+import android.app.ActivityManager
+import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.net.Uri
+import android.os.Build
+import android.os.PowerManager
+import android.provider.Settings
+import android.widget.EditText
+import com.supwisdom.activities.SPApplication
+import java.io.File
+import java.io.FileOutputStream
+import java.io.PrintWriter
+import java.io.StringWriter
+import java.util.regex.Pattern
+
+/**
+ * @author zzq
+ * @date 2018/5/9.
+ * @version 1.0.1
+ * @desc 公共类
+ */
+object CommonUtil {
+ fun doSleep(ms: Int) {
+ try {
+ Thread.sleep(ms.toLong())
+ } catch (e: InterruptedException) {
+ e.printStackTrace()
+ }
+ }
+
+ fun getEditView(et: EditText): String {
+ return et.text.toString().trim { it <= ' ' }.replace(" ", "")
+ }
+
+ fun getCommunicateTime(): Int {
+ var commTime = 2
+ val sysRecord = SPApplication.getInstance().getPos().getSysPara()
+ if (sysRecord != null) {
+ commTime = sysRecord.commTime
+ if (commTime == 0) {
+ commTime = 2
+ }
+ }
+ return commTime
+ }
+
+ fun getSerialNumber(): String? {
+ try {
+ val c = Class.forName("android.os.SystemProperties")
+ val get = c.getMethod("get", String::class.java)
+ return get.invoke(c, "ro.product.firmware") as String
+ } catch (ex: Exception) {
+ ex.printStackTrace()
+ }
+
+ return null
+ }
+
+ fun YuanToFen(yuan: Double): Int {
+ return Math.round(yuan * 100).toInt()
+ }
+
+ fun upgrade(context: Context, filename: String) {
+ val intent = Intent(Intent.ACTION_VIEW)
+ val uri = Uri.fromFile(File(filename))
+ intent.setDataAndType(uri, "application/vnd.android.package-archive")
+ (context as Activity).startActivityForResult(intent, 0)
+ }
+
+ fun isNumeric(str: String): Boolean {
+ val pattern = Pattern.compile("[0-9]*")
+ val isNum = pattern.matcher(str)
+ return isNum.matches()
+ }
+
+ fun showFormatAmount(preHint: String, amount: Int): String {
+ return String.format("%s: %.02f元", preHint, amount / 100.0f)
+ }
+
+ /*优化a811扫码*/
+ fun writeLinnuuxParams() {
+ try {
+ val fos = FileOutputStream("/sys/module/gc0308/parameters/exposure")
+ fos.write("20".toByteArray())
+ fos.close()
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ }
+
+ /**
+ * 判断服务是否开启
+ *
+ * @param mContext
+ * @param serviceName
+ * @return
+ */
+ fun isServiceWork(mContext: Context, serviceName: String): Boolean {
+ val myAM = mContext
+ .getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
+ val myList = myAM.getRunningServices(40)
+ if (myList.size <= 0) {
+ return false
+ }
+ for (i in myList.indices) {
+ val mName = myList[i].service.className.toString()
+ if (mName == serviceName) {
+ return true
+ }
+ }
+ return false
+ }
+
+ fun getExceptionStack(e: Exception?): String {
+ if (e == null) {
+ return "null"
+ }
+ val sw = StringWriter()
+ val pw = PrintWriter(sw)
+ e.printStackTrace(pw)
+ return sw.toString()
+ }
+
+ /**
+ * get App versionName
+ *
+ * @param context
+ * @return
+ */
+ fun getVersionName(context: Context): String {
+ return try {
+ val packageManager = context.packageManager
+ val packageInfo = packageManager.getPackageInfo(context.packageName, 0)
+ packageInfo.versionName
+ } catch (e: PackageManager.NameNotFoundException) {
+ e.printStackTrace()
+ "error:" + e.message
+ }
+
+ }
+
+ /**
+ * 跳转网络设置页;
+ */
+ fun startNetSetting(context: Context) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ context.startActivity(Intent(Settings.ACTION_SETTINGS))
+ } else {
+ context.startActivity(Intent(Settings.ACTION_WIRELESS_SETTINGS))
+ }
+ }
+
+ /**
+ * 唤醒屏幕
+ */
+ fun acquireWakeLock(context: Context) {
+ /*FULL_WAKE_LOCK:保持CPU 运转,保持屏幕高亮显示,键盘灯也保持亮度
+ ACQUIRE_CAUSES_WAKEUP:强制使屏幕亮起,这种锁主要针对一些必须通知用户的操作.
+ ON_AFTER_RELEASE:当锁被释放时,保持屏幕亮起一段时间*/
+ try {
+ val pm = context.getSystemService(Context.POWER_SERVICE) as PowerManager
+ @SuppressLint("InvalidWakeLockTag") val wakeLock = pm.newWakeLock(
+ PowerManager.ON_AFTER_RELEASE
+ or PowerManager.ACQUIRE_CAUSES_WAKEUP
+ or PowerManager.FULL_WAKE_LOCK, "Tag"
+ )
+ wakeLock.acquire()
+ wakeLock.release()
+ } catch (ex: Exception) {
+ ex.printStackTrace()
+ }
+
+ }
+
+ fun getPasswordStar(len: Int): String {
+ return when (len) {
+ 0 -> " "
+ 1 -> "*"
+ 2 -> "**"
+ 3 -> "***"
+ 4 -> "****"
+ 5 -> "*****"
+ 6 -> "******"
+ else -> " "
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/utils/CryptUtil.kt b/app/src/main/java/com/supwisdom/utils/CryptUtil.kt
new file mode 100644
index 0000000..b3d7f97
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/utils/CryptUtil.kt
@@ -0,0 +1,142 @@
+package com.supwisdom.utils
+
+import java.io.InputStream
+import java.io.UnsupportedEncodingException
+import java.security.InvalidKeyException
+import java.security.MessageDigest
+import java.security.NoSuchAlgorithmException
+import javax.crypto.Mac
+import javax.crypto.spec.SecretKeySpec
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+object CryptUtil {
+ fun HASH256(text: String): String? {
+ return algorithm2(text, "SHA-256", true)
+ }
+
+ fun HASH256(fis: InputStream): String? {
+ return algorithm(fis, "SHA-256")
+ }
+
+ fun HASH256(fis: InputStream, extData: String): String? {
+ return algorithm(fis, "SHA-256", extData)
+ }
+
+ fun HASH512(text: String): String? {
+ return algorithm2(text, "SHA-512", true)
+ }
+
+ fun MD5(text: String): String? {
+ return algorithm2(text, "MD5", false)
+ }
+
+ fun HMACSHA1(data: String, key: String): String? {
+ try {
+ val algorithm = "HmacSHA1"
+ val mac = Mac.getInstance(algorithm)
+ val spec = SecretKeySpec(key.toByteArray(), algorithm)
+ mac.init(spec)
+ val byteHMAC = mac.doFinal(data.toByteArray())
+ return byteHMAC.encodeHex()
+ } catch (e: InvalidKeyException) {
+ e.printStackTrace()
+ } catch (ignore: NoSuchAlgorithmException) {
+ ignore.printStackTrace()
+ }
+ return null
+ }
+
+ fun HMACSHA256(data: String, key: String): String? {
+ try {
+ val algorithm = "HmacSHA256"
+ val mac = Mac.getInstance(algorithm)
+ val spec = SecretKeySpec(key.toByteArray(), algorithm)
+ mac.init(spec)
+ val byteHMAC = mac.doFinal(data.toByteArray())
+ return byteHMAC.encodeHex()
+ } catch (e: InvalidKeyException) {
+ e.printStackTrace()
+ } catch (ignore: NoSuchAlgorithmException) {
+ ignore.printStackTrace()
+ }
+ return null
+ }
+
+ private fun algorithm2(text: String?, algorithm: String, isUpperCase: Boolean): String? {
+ if (text != null && text.isNotEmpty()) {
+ try {
+ //创建具有指定算法名称的信息摘要
+ val md = MessageDigest.getInstance(algorithm)
+ //使用指定的字节数组对摘要进行最后更新,然后完成摘要计算
+ val results = md.digest(text.toByteArray(charset("UTF-8")))
+ //将得到的字节数组变成字符串返回
+ val resultString = results.encodeHex()
+ return if (isUpperCase) {
+ resultString.toUpperCase()
+ } else {
+ resultString.toLowerCase()
+ }
+ } catch (ex: NoSuchAlgorithmException) {
+ ex.printStackTrace()
+ } catch (ex: UnsupportedEncodingException) {
+ ex.printStackTrace()
+ }
+ }
+ return null
+ }
+
+ private fun algorithm(fis: InputStream, algorithm: String): String? {
+ try {
+ //拿到一个MD5转换器,如果想使用SHA-1或SHA-256,则传入SHA-1,SHA-256
+ val md = MessageDigest.getInstance(algorithm)
+
+ //分多次将一个文件读入,对于大型文件而言,比较推荐这种方式,占用内存比较少。
+ val buffer = ByteArray(1024)
+ var length: Int
+ while (true) {
+ length = fis.read(buffer, 0, 1024)
+ if (length < 0) {
+ break
+ }
+ md.update(buffer, 0, length)
+ }
+ fis.close()
+ //转换并返回包含16个元素字节数组,返回数值范围为-128到127
+ return md.digest().encodeHex()
+ } catch (e: Exception) {
+ e.printStackTrace()
+ return null
+ }
+
+ }
+
+ private fun algorithm(fis: InputStream, algorithm: String, extData: String): String? {
+ try {
+ //拿到一个MD5转换器,如果想使用SHA-1或SHA-256,则传入SHA-1,SHA-256
+ val md = MessageDigest.getInstance(algorithm)
+
+ //分多次将一个文件读入,对于大型文件而言,比较推荐这种方式,占用内存比较少。
+ val buffer = ByteArray(1024)
+ var length: Int
+ while (true) {
+ length = fis.read(buffer, 0, 1024)
+ if (length < 0) {
+ break
+ }
+ md.update(buffer, 0, length)
+ }
+ fis.close()
+ md.update(extData.toByteArray(charset("UTF-8")))
+
+ //转换并返回包含16个元素字节数组,返回数值范围为-128到127
+ return md.digest().encodeHex()
+ } catch (e: Exception) {
+ e.printStackTrace()
+ return null
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/utils/DateUtil.kt b/app/src/main/java/com/supwisdom/utils/DateUtil.kt
new file mode 100644
index 0000000..6ce7a41
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/utils/DateUtil.kt
@@ -0,0 +1,322 @@
+package com.supwisdom.utils
+
+import java.text.ParseException
+import java.text.SimpleDateFormat
+import java.util.*
+
+/**
+ ** create by zzq on 2019/7/23
+ ** @desc
+ **/
+object DateUtil {
+ private val FORMAT_yyyyMMdd = org.apache.commons.lang3.time.FastDateFormat.getInstance("yyyyMMdd")
+ private val FORMAT_yyMMddHHmmss = org.apache.commons.lang3.time.FastDateFormat.getInstance("yyMMddHHmmss")
+ private val FORMAT_yyMMddHHmmss2 = org.apache.commons.lang3.time.FastDateFormat.getInstance("yy-MM-dd HH:mm:ss")
+ private val FORMAT_HHmmss = org.apache.commons.lang3.time.FastDateFormat.getInstance("HHmmss")
+ private val FORMAT_MMdd = org.apache.commons.lang3.time.FastDateFormat.getInstance("MMdd")
+ private val FORMAT_MM_dd = org.apache.commons.lang3.time.FastDateFormat.getInstance("MM-dd")
+ private val FORMAT_yyyyMMddHHmmss = org.apache.commons.lang3.time.FastDateFormat.getInstance("yyyyMMddHHmmss")
+ private val FORMAT_yyyyMMddHHmm = org.apache.commons.lang3.time.FastDateFormat.getInstance("yyyyMMddHHmm")
+ private val FORMAT_MMddHHmmyy = org.apache.commons.lang3.time.FastDateFormat.getInstance("MMddHHmmyy")
+ private val FORMAT_yyyy_MM_dd_HH_mm_ss =
+ org.apache.commons.lang3.time.FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss")
+ private val FORMAT_yyyy_MM_dd = org.apache.commons.lang3.time.FastDateFormat.getInstance("yyyy-MM-dd")
+ private val FORMAT_HH_mm_ss = org.apache.commons.lang3.time.FastDateFormat.getInstance("HH:mm:ss")
+
+ /**
+ * @return yyyy-MM-dd HH:mm:ss
+ */
+ fun getNow(): String {
+ return FORMAT_yyyy_MM_dd_HH_mm_ss.format(Date())
+ }
+
+ fun getNowDateSpecFormat(): String {
+ return FORMAT_yyyy_MM_dd.format(Date())
+ }
+
+ fun utcToLocal(utctime: String): String {
+ val sdf = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
+ sdf.timeZone = TimeZone.getTimeZone("UTC")
+ return try {
+ val utcDate = sdf.parse(utctime)
+ sdf.timeZone = TimeZone.getDefault()
+ val localTime = sdf.format(utcDate.time)
+ val localDate = sdf.parse(localTime)
+ FORMAT_yyyyMMddHHmmss.format(localDate.time)
+ } catch (ex: ParseException) {
+ ex.printStackTrace()
+ ""
+ }
+ }
+
+ /**
+ * @param date yyyyMMdd
+ * @return yyyy-MM-dd
+ */
+ fun getNowDateFromNoFormat(date: String): String {
+ try {
+ return date.substring(0, 4) + "-" +
+ date.substring(4, 6) + "-" +
+ date.substring(6, 8)
+ } catch (ex: Exception) {
+ }
+ return ""
+ }
+
+ /**
+ * @return HH:mm:ss
+ */
+ fun getNowTimeWithArg(date: Date): String? {
+ return try {
+ FORMAT_HH_mm_ss.format(date)
+ } catch (e: Exception) {
+ null
+ }
+ }
+
+ /**
+ * @param time HHmm
+ * @return HH:mm
+ */
+ fun formatTime(time: String): String? {
+ return try {
+ val sb = StringBuilder()
+ sb.append(time.substring(0, 2)).append(":")
+ .append(time.substring(2, 4))
+ sb.toString()
+ } catch (e: Exception) {
+ null
+ }
+ }
+
+ /**
+ * @return MMdd
+ */
+ fun getDateMMdd(): String? {
+ return try {
+ FORMAT_MMdd.format(Date())
+ } catch (e: Exception) {
+ e.printStackTrace()
+ null
+ }
+ }
+
+ /**
+ * @return MM-dd
+ */
+ fun getDate_MMdd(): String? {
+ try {
+ return FORMAT_MM_dd.format(Date())
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ return null
+ }
+
+ /**
+ * @return yyyy-MM-dd HH:mm:ss
+ */
+ fun getNowDateTime(): String {
+ return FORMAT_yyyy_MM_dd_HH_mm_ss.format(Date())
+ }
+
+ /**
+ * @return yyyy-MM-dd
+ */
+ fun getNowDate(): String {
+ return FORMAT_yyyy_MM_dd.format(Date())
+ }
+
+ /**
+ * @param dateStr yyyy-MM-dd
+ * @return
+ */
+ fun getNowDateTime(dateStr: String): Date? {
+ try {
+ return FORMAT_yyyy_MM_dd.parse(dateStr)
+ } catch (e: ParseException) {
+ e.printStackTrace()
+ }
+ return null
+ }
+
+ /**
+ * @return HH:mm:ss
+ */
+ fun getNowTime(): String {
+ return FORMAT_HH_mm_ss.format(Date())
+ }
+
+ /**
+ * @return format
+ */
+ fun getDayofWeek(offsetWeek: Int, dayOfWeek: Int, format: String): String {
+ val cal = Calendar.getInstance()
+ // n为推迟的周数,1本周,-1向前推迟一周,2下周,依次类推
+ val retday: String
+ cal.add(Calendar.DATE, offsetWeek * 7)
+ cal.set(Calendar.DAY_OF_WEEK, dayOfWeek)
+ retday = org.apache.commons.lang3.time.FastDateFormat.getInstance(format).format(cal.time)
+ return retday
+ }
+
+ /**
+ * 计算超时时间,精确到毫秒
+ *
+ * @param milliSeconds
+ * @return L
+ */
+ fun getExpireTime(milliSeconds: Long): Long {
+ return Date().time + milliSeconds
+ }
+
+ /**
+ * @return yyyyMMddHHmmss
+ */
+ fun getNowDateTimeNoFormat(): String {
+ return FORMAT_yyyyMMddHHmmss.format(Date())
+ }
+
+ /**
+ * @return yyyyMMdd
+ */
+ fun getNowDateNoFormat(): String {
+ return FORMAT_yyyyMMdd.format(Date())
+ }
+
+ /**
+ * @param date
+ * @return yyyyMMdd
+ */
+ fun getNowDateNoFormat(date: Date): String? {
+ try {
+ return FORMAT_yyyyMMdd.format(date)
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ return null
+ }
+
+ /**
+ * @return HHmmss
+ */
+ fun getNowTimeNoFormat(): String {
+ return FORMAT_HHmmss.format(Date())
+ }
+
+ /**
+ * @param datetime yyyyMMddHHmmss
+ * @return ms
+ * @desc 将日期格式的字符串转换为长整型
+ */
+ fun dateFormatConvertToLong(datetime: String): Long {
+ return try {
+ FORMAT_yyyyMMddHHmmss.parse(datetime).time
+ } catch (ex: ParseException) {
+ 0L
+ }
+ }
+
+ /**
+ * @param time ms
+ * @return yyyyMMddHHmmss
+ * @desc 将长整型数字转换为日期格式的字符串
+ */
+ fun dateLongConvertToFormat(time: Long): String {
+ return if (time > 0L) {
+ FORMAT_yyyyMMddHHmmss.format(Date(time))
+ } else ""
+ }
+
+ /**
+ * @param time ms
+ * @return MMddHHmmyy
+ * @desc 将长整型数字转换为日期格式的字符串
+ */
+ fun dateLongConvertToFormat2(time: Long): String {
+ return if (time > 0L) {
+ FORMAT_MMddHHmmyy.format(Date(time))
+ } else ""
+ }
+
+ /**
+ * @param datetime yyyy-MM-dd HH:mm:ss
+ * @return
+ * @desc 将日期格式的字符串转换为长整型
+ */
+ fun dateFormatConvertToDate(datetime: String): Date? {
+ return try {
+ FORMAT_yyyy_MM_dd_HH_mm_ss.parse(datetime)
+ } catch (ex: ParseException) {
+ null
+ }
+ }
+
+ /**
+ * @param daynum 天数
+ * @return 返回当前日期的第 daynum 天前的日期 yyyyMMdd
+ */
+ fun getDayDateNoFormatBefore(daynum: Int): String {
+ val calendar = Calendar.getInstance()
+ calendar.add(Calendar.DATE, -daynum)
+ return FORMAT_yyyyMMdd.format(calendar.time)
+ }
+
+ /**
+ * 获得指定日期的前一天
+ *
+ * @param specifiedDay yyyyMMdd
+ * @return yyyyMMdd
+ */
+ fun getSpecifiedDayBefore(specifiedDay: String): String {
+ return try {
+ val c = Calendar.getInstance()
+ val date = FORMAT_yyyyMMdd.parse(specifiedDay)
+ c.time = date
+ val day = c.get(Calendar.DATE)
+ c.set(Calendar.DATE, day - 1)
+ FORMAT_yyyyMMdd.format(c.time)
+ } catch (e: ParseException) {
+ ""
+ }
+ }
+
+ /**
+ * 获得指定日期的前一天
+ *
+ * @param dayBefore 往前推迟的天数
+ * @return Date
+ */
+ fun getSomeDayBefore(dayBefore: Int): Date {
+ val c = Calendar.getInstance()
+ c.add(Calendar.DAY_OF_MONTH, -dayBefore)
+ return c.time
+ }
+
+ /**
+ * 获得指定日期的后一天
+ *
+ * @param specifiedDay yyyyMMdd
+ * @return yyyyMMdd
+ */
+ fun getSpecifiedDayAfter(specifiedDay: String): String {
+ return try {
+ val c = Calendar.getInstance()
+ val date = FORMAT_yyyyMMdd.parse(specifiedDay)
+ c.time = date
+ val day = c.get(Calendar.DATE)
+ c.set(Calendar.DATE, day + 1)
+ FORMAT_yyyyMMdd.format(c.time)
+ } catch (e: ParseException) {
+ ""
+ }
+ }
+
+ /**
+ * @return yyyyMMddHHmmss
+ */
+ fun getNowDateTimeFormat(): String {
+ return FORMAT_yyyyMMddHHmmss.format(Date())
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/utils/FileUtil.kt b/app/src/main/java/com/supwisdom/utils/FileUtil.kt
new file mode 100644
index 0000000..103d889
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/utils/FileUtil.kt
@@ -0,0 +1,142 @@
+package com.supwisdom.utils
+
+import android.os.Environment
+import java.io.*
+
+/**
+ ** create by zzq on 2019/7/23
+ ** @desc
+ **/
+object FileUtil {
+ private val ROOT_DIR = "/a711/pos/"
+ private val ROOT_PRIVATE_DIR = "/supwisdom/"
+ private val CACHE_FILE_DIR = ROOT_DIR + "cache/"
+ private val CRASH_FILE_DIR = ROOT_DIR + "crash/"
+ private val CRASH_FILE_PRE = "crash-"
+ private val LOG_FILE_DIR = ROOT_DIR + "log/"
+ private val LOG_FILE_PRE = "log-"
+ private val DTL_FILE_DIR = ROOT_DIR + "dtl/"
+ private val DTL_FILE_PRE = "dtl-"
+
+ fun getUpdateFile(fileName: String): File? {
+ return createFile(CACHE_FILE_DIR, fileName)
+ }
+
+ fun getCfgFile(fileName: String): File? {
+ return createFile(ROOT_PRIVATE_DIR, fileName)
+ }
+
+ fun getCfgFileStream(fileName: String): InputStream? {
+ if (android.os.Environment.MEDIA_MOUNTED == android.os.Environment.getExternalStorageState()) {
+ val rootFile = File(Environment.getExternalStorageDirectory().toString() + ROOT_PRIVATE_DIR)
+ if (!rootFile.exists()) {
+ return null
+ }
+ val retFile = File(rootFile, fileName)
+ if (retFile.exists()) {
+ try {
+ return FileInputStream(retFile)
+ } catch (e: FileNotFoundException) {
+ e.printStackTrace()
+ }
+
+ }
+ }
+ return null
+ }
+
+ fun removeDtlFile(beforeday: Int) {
+ removeFile(DTL_FILE_DIR, DTL_FILE_PRE, beforeday)
+ }
+
+ fun removeLogFile(beforeday: Int) {
+ removeFile(LOG_FILE_DIR, LOG_FILE_PRE, beforeday)
+ }
+
+ fun removeCrashFile(beforeday: Int) {
+ removeFile(CRASH_FILE_DIR, CRASH_FILE_PRE, beforeday)
+ }
+
+
+ fun writeDtlFile(msg: String) {
+ val pathfile = DTL_FILE_DIR + DTL_FILE_PRE + DateUtil.getNowDateNoFormat() + ".txt"
+ writeFile(pathfile, msg, true)
+ }
+
+ fun writeCrashFile(msg: String) {
+ val pathfile = CRASH_FILE_DIR + CRASH_FILE_PRE + DateUtil.getNowDateNoFormat() + ".txt"
+ writeFile(pathfile, msg, true)
+ }
+
+ fun writeLogFile(msg: String) {
+ val pathfile = LOG_FILE_DIR + LOG_FILE_PRE + DateUtil.getNowDateNoFormat() + ".txt"
+ writeFile(pathfile, msg, true)
+ }
+
+ private fun writeFile(targetPath: String, msg: String, append: Boolean) {
+ if (android.os.Environment.MEDIA_MOUNTED == android.os.Environment.getExternalStorageState()) {
+ val targetFile = File(Environment.getExternalStorageDirectory().toString() + targetPath)
+ if (!targetFile.parentFile.exists()) {
+ targetFile.parentFile.mkdirs()
+ }
+ try {
+ val osw = OutputStreamWriter(
+ FileOutputStream(targetFile, append), "utf-8"
+ )
+ try {
+ osw.write(msg)
+ osw.write("</br>\n")
+ osw.flush()
+ osw.close()
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+
+ } catch (e1: UnsupportedEncodingException) {
+ e1.printStackTrace()
+ } catch (e1: FileNotFoundException) {
+ e1.printStackTrace()
+ }
+
+ }
+ }
+
+ private fun removeFile(targetPath: String, prefile: String, beforeday: Int) {
+ if (Environment.MEDIA_MOUNTED == Environment.getExternalStorageState()) {
+ val rootFile = File(Environment.getExternalStorageDirectory().toString() + targetPath)
+ if (!rootFile.exists()) {
+ return
+ }
+ val logname = prefile + DateUtil.getDayDateNoFormatBefore(beforeday) + ".txt"
+ val files = rootFile.listFiles()
+ for (file in files!!) {
+ val fullfilename = file.absolutePath
+ val filename = fullfilename.substring(fullfilename.lastIndexOf('/') + 1)
+ if (filename.startsWith(prefile) && filename.endsWith(".txt")) {
+ if (filename.compareTo(logname) < 0) {
+ file.delete()
+ }
+ }
+ }
+ }
+ }
+
+ private fun createFile(path: String, fileName: String): File? {
+ if (android.os.Environment.MEDIA_MOUNTED == android.os.Environment.getExternalStorageState()) {
+ val rootFile = File(Environment.getExternalStorageDirectory().toString() + path)
+ if (!rootFile.exists()) {
+ rootFile.mkdirs()
+ }
+ val retFile = File(rootFile, fileName)
+ if (!retFile.exists()) {
+ try {
+ retFile.createNewFile()
+ } catch (e: IOException) {
+ return null
+ }
+ }
+ return retFile
+ }
+ return null
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/utils/GsonUtil.kt b/app/src/main/java/com/supwisdom/utils/GsonUtil.kt
new file mode 100644
index 0000000..12e9209
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/utils/GsonUtil.kt
@@ -0,0 +1,34 @@
+package com.supwisdom.utils
+
+import com.google.gson.Gson
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+object GsonUtil {
+ private val gson = Gson()
+
+ /**
+ * 转成json
+ *
+ * @param object
+ * @return
+ */
+ fun GsonString(obj: Any): String {
+ return gson.toJson(obj)
+// return JSON.toJSONString(obj)
+ }
+
+ /**
+ * 转成bean
+ *
+ * @param gsonString
+ * @param cls
+ * @return
+ */
+ fun <T> GsonToBean(gsonString: String, cls: Class<T>): T {
+ return gson.fromJson(gsonString, cls)
+// return JSON.parseObject(gsonString, cls)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/utils/LogUtil.kt b/app/src/main/java/com/supwisdom/utils/LogUtil.kt
new file mode 100644
index 0000000..210fbd1
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/utils/LogUtil.kt
@@ -0,0 +1,39 @@
+package com.supwisdom.utils
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+object LogUtil {
+ private val DEBUG = 3
+ private val INFO = 2
+ private val ERROR = 1
+ private var curlevel = DEBUG
+
+ fun setLevel(level: Int) {
+ curlevel = level
+ }
+
+ fun d(tag: String, msg: String) {
+ if (curlevel >= DEBUG) {
+ writeLog(tag, msg)
+ }
+ }
+
+ fun i(tag: String, msg: String) {
+ if (curlevel >= INFO) {
+ writeLog(tag, msg)
+ }
+ }
+
+ fun e(tag: String, msg: String) {
+ if (curlevel >= ERROR) {
+ writeLog(tag, msg)
+ }
+ }
+
+ private fun writeLog(tag: String, msg: String) {
+ val time = DateUtil.getNowDateTime() + "--"
+ FileUtil.writeLogFile("$tag:$time--$msg")
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/utils/PublicDef.kt b/app/src/main/java/com/supwisdom/utils/PublicDef.kt
new file mode 100644
index 0000000..b67e05b
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/utils/PublicDef.kt
@@ -0,0 +1,91 @@
+package com.supwisdom.utils
+
+/**
+ * @author zzq
+ * @date 2018/4/26.
+ * @version 1.0.1
+ * @desc APP module常量定义
+ */
+object PublicDef {
+ /**
+ * 错误码
+ */
+ const val SUCCESS = 0
+ const val ERROR = 1
+ /**
+ * 商户默认密码 111111
+ * 维护默认密码 914387
+ */
+ const val PASSWD_SHOP_DEFAULT = "111111"
+ const val PASSWD_ADMIN_DEFAULT = "914387"
+
+ /**************************************************************/
+ /*************************handler 状态码***********************/
+ const val MSG_CARD_PAYING = 10
+ const val MSG_CARD_READ_AGAIN = 11
+ const val MSG_CARD_PAY_FAIL = 12
+ const val MSG_CARD_PAY_SUC = 13
+ const val MSG_CARD_PAY_QUERY = 14
+ const val MSG_CARD_REVERSE_FAIL = 15
+ const val MSG_CARD_REVERSE_SUC = 16
+ const val MSG_USER_INFO_SHOW = 17
+ const val MSG_USER_INFO_CLEAR = 18
+ const val MSG_LINK_STATUS = 19
+ const val MSG_CODE_PAYING_CANCEL = 19
+ /*************************不能重复*****************************/
+ /**
+ * 卡消费标志(1 byte)
+ */
+ /*high 4 bit*/
+ const val TRANSFLAG_NORMAL_CONSUME = 0x80 // 正常消费
+ const val TRANSFLAG_MEALER_CONSUME = 0xC0 // 搭伙
+ const val TRANSFLAG_DISCNT_CONSUME = 0xA0 // 折扣
+ const val TRANSFLAG_REVS_ML_CONSUME = 0x40 //冲正带搭伙
+ const val TRANSFLAG_REVS_DST_CONSUME = 0x20 // 冲正带折扣
+ const val TRANSFLAG_REVERSE_AUTO_CONSUME = 0x10 // 自动撤销 (0x00 手动冲正)
+ const val TRANSFLAG_REVERSE_CONSUME = 0x00 //&0x80 最高位0标识冲正(统一标识)
+ /*low 4 bit*/
+ const val TRANSFLAG_WRITE_CARD_SUCCESS = 0x01 // 写卡成功
+ const val TRANSFLAG_WRITE_CARD_HALFAWAY = 0x02 // 中途拔卡
+ const val TRANSFLAG_UNWRITE_CARD = 0x03 // 未写卡
+ const val TRANSFLAG_PWD_CONSUME = 0x04 // 密码消费
+
+ const val BG_SERVICE_NAME = "com.supwisdom.service.BackgroundTaskService"
+
+ /**
+ * Toast show
+ */
+ const val TOAST_SHOW_CRY = 1
+ const val TOAST_SHOW_SMILE = 2
+ const val TOAST_SHOW_DOUBT = 3
+
+ const val DIALOG_TYPE_BIG_PICTURE = 1
+ const val DIALOG_TYPE_PURCHASE = 2
+ const val DIALOG_TYPE_PASSWORD = 3
+ const val DIALOG_TYPE_SELECT_ORDER = 4
+ const val DIALOG_TYPE_DPS_CONFIRM = 5
+ const val DIALOG_TYPE_SCAN_RVS_CONFIRM = 6
+ const val DIALOG_TYPE_ORDINARY_CONSUME = 7
+ const val DIALOG_TYPE_DEPOSIT = 8
+ const val DIALOG_TYPE_NSD_CONFIG = 9
+
+ /**
+ * 本地全局控制参数
+ */
+ const val CONTROL_FIXAMT = "fixamt"
+ const val CONTROL_OFFLINE_DAY_DISABLE = "offdaydisable"
+ const val CONTROL_DEBUG_ENABLE = "debugenable"
+ /**
+ * 非定额消费标识
+ */
+ const val CONTROL_NO_FIXPAY_FLAG = "none"
+ /**
+ * 消费冲正时限
+ */
+ const val REVERSE_MS_GAP = 600000
+ /**
+ *
+ */
+ const val APP_ID = "3000004"
+ const val APP_SECRET = "c9ae5b4fe5014b5b9eb19e1a0797a3a3"
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/utils/SoundUtil.kt b/app/src/main/java/com/supwisdom/utils/SoundUtil.kt
new file mode 100644
index 0000000..2c80655
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/utils/SoundUtil.kt
@@ -0,0 +1,70 @@
+package com.supwisdom.utils
+
+import android.content.Context
+import android.media.AudioManager
+import android.media.SoundPool
+import com.supwisdom.R
+
+/**
+ ** create by zzq on 2019/7/26
+ ** @desc
+ **/
+@Suppress("DEPRECATION")
+object SoundUtil {
+ private var soundId: Int = 0
+ private var soundPool: SoundPool? = null
+ private val soundMap = hashMapOf<Int, Int>()
+ private var keyEnable = false
+
+ fun playMusic(context: Context, mid: Int) {
+ if (!keyEnable && isKeyPlay(mid)) {
+ return
+ }
+ if (soundPool == null) {
+ soundPool = SoundPool(30, AudioManager.STREAM_MUSIC, 0) //分别对应声音池数量,AudioManager.STREAM_MUSIC 和 0
+ }
+ if (soundMap.containsKey(mid)) {
+ soundPool!!.play(soundMap[mid]!!, 1.0f, 1.0f, 1, 0, 1.0f)
+ } else {
+ soundId = soundPool!!.load(context, mid, 1)
+ soundPool!!.setOnLoadCompleteListener { pool, sampleId, status ->
+ soundMap[mid] = soundId
+ // 加载完成
+ pool.play(soundId, 1.0f, 1.0f, 1, 0, 1.0f)
+ }
+ }
+ }
+
+ fun releaseMusic() {
+ if (soundPool != null) {
+ soundPool!!.release()
+ soundPool = null
+ }
+ soundMap.clear()
+ }
+
+ fun setKeyPlay(enable: Boolean) {
+ keyEnable = enable
+ }
+
+ private fun isKeyPlay(mid: Int): Boolean {
+ return mid == R.raw.key_one ||
+ mid == R.raw.key_two ||
+ mid == R.raw.key_three ||
+ mid == R.raw.key_four ||
+ mid == R.raw.key_five ||
+ mid == R.raw.key_six ||
+ mid == R.raw.key_seven ||
+ mid == R.raw.key_eight ||
+ mid == R.raw.key_nine ||
+ mid == R.raw.key_zero ||
+ mid == R.raw.key_dot ||
+ mid == R.raw.key_add ||
+ mid == R.raw.key_clear ||
+ mid == R.raw.key_enter ||
+ mid == R.raw.key_fone ||
+ mid == R.raw.key_ftwo ||
+ mid == R.raw.key_fthree ||
+ mid == R.raw.key_ffour
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/utils/ThreadPool.kt b/app/src/main/java/com/supwisdom/utils/ThreadPool.kt
new file mode 100644
index 0000000..eab9150
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/utils/ThreadPool.kt
@@ -0,0 +1,170 @@
+package com.supwisdom.utils
+
+import java.util.concurrent.Executors
+import java.util.concurrent.LinkedBlockingQueue
+import java.util.concurrent.ThreadPoolExecutor
+import java.util.concurrent.TimeUnit
+
+/**
+ ** create by zzq on 2019/7/23
+ ** @desc
+ **/
+object ThreadPool {
+ private val DEFAULT_SINGLE_POOL_NAME = "DEFAULT_SINGLE_POOL_NAME"
+
+ private var mLongPool: ThreadPoolProxy? = null
+ private var mShortPool: ThreadPoolProxy? = null
+ private var mDownloadPool: ThreadPoolProxy? = null
+ private val mMap = hashMapOf<String, ThreadPoolProxy>()
+
+ /**
+ * 获取下载线程
+ */
+ fun getDownloadPool(): ThreadPoolProxy {
+ if (mDownloadPool == null) {
+ synchronized(ThreadPool::class.java) {
+ if (mDownloadPool == null) {
+ //获取CPU核数
+ val num = Runtime.getRuntime().availableProcessors()
+ val corePoolSize = num + 1
+ val maximumPoolSize = 2 * num + 1
+ mDownloadPool = ThreadPoolProxy(corePoolSize, maximumPoolSize, 1L)
+ }
+ }
+ }
+ return mDownloadPool!!
+ }
+
+ /**
+ * 获取一个用于执行长耗时任务的线程池,避免和短耗时任务处在同一个队列而阻塞了重要的短耗时任务,通常用来联网操作
+ */
+
+ fun getLongPool(): ThreadPoolProxy {
+ if (mLongPool == null) {
+ synchronized(ThreadPool::class.java) {
+ if (mLongPool == null) {
+ //获取CPU核数
+ val num = Runtime.getRuntime().availableProcessors()
+ val corePoolSize = num + 1
+ val maximumPoolSize = 2 * num + 1
+ mLongPool = ThreadPoolProxy(corePoolSize, maximumPoolSize, 1L)
+ }
+ }
+ }
+ return mLongPool!!
+ }
+
+ /**
+ * 获取一个用于执行短耗时任务的线程池,避免因为和耗时长的任务处在同一个队列而长时间得不到执行,通常用来执行本地的IO/SQL
+ */
+ fun getShortPool(): ThreadPoolProxy {
+ if (mShortPool == null) {
+ synchronized(ThreadPool::class.java) {
+ if (mShortPool == null) {
+ //获取CPU核数
+ val num = Runtime.getRuntime().availableProcessors()
+ val corePoolSize = num + 1
+ val maximumPoolSize = 2 * num + 1
+ mShortPool = ThreadPoolProxy(corePoolSize, maximumPoolSize, 1L)
+ }
+ }
+ }
+ return mShortPool!!
+ }
+
+ /**
+ * 获取一个单线程池,所有任务将会被按照加入的顺序执行,免除了同步开销的问题
+ */
+ fun getSinglePool(): ThreadPoolProxy {
+ return getSinglePool(DEFAULT_SINGLE_POOL_NAME)
+ }
+
+ /**
+ * 获取一个单线程池,所有任务将会被按照加入的顺序执行,免除了同步开销的问题
+ */
+ fun getSinglePool(name: String): ThreadPoolProxy {
+ synchronized(ThreadPool::class.java) {
+ var singlePool: ThreadPoolProxy? = mMap[name]
+ if (singlePool == null) {
+ singlePool = ThreadPoolProxy(1, 1, 1L)
+ mMap[name] = singlePool
+ }
+ return singlePool
+ }
+ }
+
+ class ThreadPoolProxy constructor(
+ private val mCorePoolSize: Int,
+ private val mMaximumPoolSize: Int,
+ private val mKeepAliveTime: Long
+ ) {
+ private var mPool: ThreadPoolExecutor? = null
+
+ /**
+ * 执行任务,当线程池处于关闭,将会重新创建新的线程池
+ */
+ @Synchronized
+ fun execute(run: Runnable) {
+ if (mPool == null || mPool!!.isShutdown) {
+ //参数说明
+ //当线程池中的线程小于mCorePoolSize,直接创建新的线程加入线程池执行任务
+ //当线程池中的线程数目等于mCorePoolSize,将会把任务放入任务队列BlockingQueue中
+ //当BlockingQueue中的任务放满了,将会创建新的线程去执行,
+ //但是当总线程数大于mMaximumPoolSize时,将会抛出异常,交给RejectedExecutionHandler处理
+ //mKeepAliveTime是线程执行完任务后,且队列中没有可以执行的任务,存活的时间,后面的参数是时间单位
+ //ThreadFactory是每次创建新的线程工厂
+ mPool = ThreadPoolExecutor(
+ mCorePoolSize,
+ mMaximumPoolSize,
+ mKeepAliveTime,
+ TimeUnit.MILLISECONDS,
+ LinkedBlockingQueue(),
+ Executors.defaultThreadFactory(),
+ ThreadPoolExecutor.AbortPolicy()
+ )
+ }
+ mPool!!.execute(run)
+ }
+
+ /**
+ * 取消线程池中某个还未执行的任务
+ */
+ @Synchronized
+ fun cancel(run: Runnable) {
+ if (mPool != null && (!mPool!!.isShutdown || mPool!!.isTerminating)) {
+ mPool!!.queue.remove(run)
+ }
+ }
+
+ /**
+ * 取消线程池中某个还未执行的任务
+ */
+ @Synchronized
+ operator fun contains(run: Runnable): Boolean {
+ return if (mPool != null && (!mPool!!.isShutdown || mPool!!.isTerminating)) {
+ mPool!!.queue.contains(run)
+ } else {
+ false
+ }
+ }
+
+ /**
+ * 立刻关闭线程池,并且正在执行的任务也将会被中断
+ */
+ fun stop() {
+ if (mPool != null && (!mPool!!.isShutdown || mPool!!.isTerminating)) {
+ mPool!!.shutdownNow()
+ }
+ }
+
+ /**
+ * 平缓关闭单任务线程池,但是会确保所有已经加入的任务都将会被执行完毕才关闭
+ */
+ @Synchronized
+ fun shutdown() {
+ if (mPool != null && (!mPool!!.isShutdown || mPool!!.isTerminating)) {
+ mPool!!.shutdownNow()
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/utils/Util.kt b/app/src/main/java/com/supwisdom/utils/Util.kt
new file mode 100644
index 0000000..e9fb0df
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/utils/Util.kt
@@ -0,0 +1,167 @@
+package com.supwisdom.utils
+
+import java.lang.Exception
+import java.util.regex.Pattern
+
+/**
+ * @author zzq
+ * @date 2018/3/20.
+ * @version 1.0.1
+ * @desc TODO
+ */
+fun ByteArray.encodeHex(): String {
+ val res = StringBuilder()
+ forEach {
+ res.append("%02X".format(it.toInt() and 0xFF))
+ }
+ return res.toString()
+}
+
+fun String.decodeHex(): ByteArray {
+ if (this.isEmpty() || this.length % 2 != 0) {
+ throw Exception("不合法的数据")
+ }
+ return (0 until this.length step 2).map {
+ val v = this.substring(it, it + 2).toInt(16)
+ (v and 0xFF).toByte()
+ }.toByteArray()
+}
+
+fun String.encodeBCD(): ByteArray {
+ if (this.isEmpty() || this.length % 2 != 0) {
+ throw Exception("不合法的数据")
+ }
+ return (0 until this.length step 2).map {
+ val d = this.substring(it, it + 2)
+ val b1 = d[0].toInt() - 0x30
+ val b2 = d[1].toInt() - 0x30
+ if (b1 !in 0..9 || b2 !in 0..9) {
+ throw Exception("不合法的BCD格式数据<$this>")
+ }
+ ((b1.shl(4) or b2) and 0xFF).toByte()
+ }.toByteArray()
+}
+
+fun ByteArray.decodeBCD(): String {
+ return joinToString(separator = "") {
+ val b1 = it.unsignedToInt().shr(4)
+ val b2 = it.unsignedToInt() and 0x0F
+ if (b1 !in 0..9 || b2 !in 0..9) {
+ throw Exception("不合法的数据")
+ }
+ "%01d%01d".format(b1, b2)
+ }
+}
+
+fun byteArrayTohex(data: ByteArray, startPos: Int, byteLength: Int): String {
+ val res = StringBuilder()
+ data.forEachIndexed { index, s ->
+ if (index >= startPos && index < startPos + byteLength) {
+ res.append("%02X".format(s.unsignedToInt() and 0xFF))
+ }
+ }
+ return res.toString()
+}
+
+fun Byte.unsignedToInt(): Int {
+ return this.toInt() and 0xFF
+}
+
+fun Byte.unsignedToLong(): Long {
+ return this.toLong() and 0xFF
+}
+
+fun byteArrayToIntLe(data: ByteArray, startPos: Int, byteLength: Int): Int {
+ var res = 0
+ data.forEachIndexed { index, s ->
+ if (index >= startPos && index < startPos + byteLength) {
+ res = res or (s.unsignedToInt() shl ((index - startPos) shl 3))
+ }
+ }
+ return res
+}
+
+fun byteArrayToIntBe(data: ByteArray, startPos: Int, byteLength: Int): Int {
+ var res = 0
+ data.forEachIndexed { index, s ->
+ if (index >= startPos && index < startPos + byteLength) {
+ res = (res shl 8) or s.unsignedToInt()
+ }
+ }
+ return res
+}
+
+fun byteArrayToLongBe(data: ByteArray, startPos: Int, byteLength: Int): Long {
+ var res: Long = 0
+ data.forEachIndexed { index, s ->
+ if (index >= startPos && index < startPos + byteLength) {
+ res = (res shl 8) or s.toLong()
+ }
+ }
+ return res
+}
+
+fun byteArrayToLongLe(data: ByteArray): Long {
+ var res: Long = 0
+ data.forEachIndexed { index, s ->
+ res = res or ((s.toLong() and 0xFF) shl (index shl 3))
+ }
+ return res
+}
+
+
+fun intBeToByteArray(value: Int, byteLen: Int = 4): ByteArray {
+ if (byteLen !in 1..4) {
+ throw Exception("数据长度错误")
+ }
+ val res = "%08X".format(value).decodeHex()
+ return res.copyOfRange(4 - byteLen, 4)
+}
+
+fun intBeToByteArray(value: Int, data: ByteArray, startPos: Int, byteLen: Int) {
+ if (byteLen !in 1..4) {
+ throw Exception("数据长度错误")
+ }
+ val res = "%08X".format(value).decodeHex()
+ (startPos until startPos + byteLen).forEach {
+ data[it] = res[4 - byteLen + it - startPos]
+ }
+
+}
+
+fun longBeToByteArray(value: Long, byteLen: Int = 4): ByteArray {
+ if (byteLen !in 1..8) {
+ throw Exception("数据长度错误")
+ }
+ val res = ByteArray(8) { 0x00 }
+ (0..7).forEach {
+ res[it] = ((value shr ((7 - it) shl 3)) and 0xFF).toByte()
+ }
+ return res.copyOfRange(8 - byteLen, 8)
+}
+
+fun intLeToByteArray(value: Int, byteLen: Int = 4): ByteArray {
+ if (byteLen !in 1..4) {
+ throw Exception("数据长度错误")
+ }
+ val res = ByteArray(4) { 0x00 }
+ (0..3).forEach {
+ res[it] = ((value shr (it shl 3)) and 0xFF).toByte()
+ }
+ return res.copyOfRange(0, byteLen)
+}
+
+fun intLeToByteArray(value: Int, data: ByteArray, startPos: Int, byteLen: Int) {
+ if (byteLen !in 1..4) {
+ throw Exception("数据长度错误")
+ }
+ (0..3).forEach {
+ data[it + startPos] = ((value shr (it shl 3)) and 0xFF).toByte()
+ }
+}
+
+/**验证IP格式*/
+fun verifyIpFormat(ip: String): Boolean {
+ val pattern = Pattern.compile("")
+ return pattern.matcher(ip).matches()
+}
diff --git a/app/src/main/java/com/supwisdom/utils/ZipUtil.kt b/app/src/main/java/com/supwisdom/utils/ZipUtil.kt
new file mode 100644
index 0000000..37f1d09
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/utils/ZipUtil.kt
@@ -0,0 +1,194 @@
+package com.supwisdom.utils
+
+import org.apache.commons.lang3.StringUtils
+import java.io.*
+import java.util.*
+import java.util.zip.*
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+object ZipUtil {
+ /**
+ * 递归压缩文件夹
+ *
+ * @param srcRootDir 压缩文件夹根目录的子路径
+ * @param file 当前递归压缩的文件或目录对象
+ * @param zos 压缩文件存储对象
+ * @throws Exception
+ */
+ @Throws(Exception::class)
+ private fun zip(srcRootDir: String, file: File?, zos: ZipOutputStream) {
+ if (file == null) {
+ throw Exception("file is null")
+ }
+
+ //如果是文件,则直接压缩该文件
+ if (file.isFile) {
+ var count: Int
+ val bufferLen = 1024
+ val data = ByteArray(bufferLen)
+
+ //获取文件相对于压缩文件夹根目录的子路径
+ var subPath = file.absolutePath
+ val index = subPath.indexOf(srcRootDir)
+ if (index != -1) {
+ subPath = subPath.substring(srcRootDir.length + File.separator.length)
+ }
+ val entry = ZipEntry(subPath)
+ zos.putNextEntry(entry)
+ val bis = BufferedInputStream(FileInputStream(file))
+ while (true) {
+ count = bis.read(data, 0, bufferLen)
+ if (count < 0) {
+ break
+ }
+ zos.write(data, 0, count)
+ }
+ bis.close()
+ zos.closeEntry()
+ } else {
+ //压缩目录中的文件或子目录
+ val childFileList = file.listFiles()
+ for (aChildFileList in childFileList!!) {
+ aChildFileList.absolutePath.indexOf(file.absolutePath)
+ zip(srcRootDir, aChildFileList, zos)
+ }
+ }//如果是目录,则压缩整个目录
+ }
+
+ /**
+ * 对文件或文件目录进行压缩
+ *
+ * @param srcPath 要压缩的源文件路径。如果压缩一个文件,则为该文件的全路径;如果压缩一个目录,则为该目录的顶层目录路径
+ * @param zipPath 压缩文件保存的路径。注意:zipPath不能是srcPath路径下的子文件夹
+ * @param zipFileName 压缩文件名
+ * @throws Exception
+ */
+ @Throws(Exception::class)
+ fun zip(srcPath: String, zipPath: String, zipFileName: String) {
+ if (StringUtils.isEmpty(srcPath) || StringUtils.isEmpty(zipPath) || StringUtils.isEmpty(zipFileName)) {
+ throw Exception("传入参数为空")
+ }
+ try {
+ val srcFile = File(srcPath)
+ //判断压缩文件保存的路径是否为源文件路径的子文件夹,如果是,则抛出异常(防止无限递归压缩的发生)
+ if (srcFile.isDirectory && zipPath.contains(srcPath)) {
+ throw Exception("zipPath must not be the child directory of srcPath.")
+ }
+
+ //判断压缩文件保存的路径是否存在,如果不存在,则创建目录
+ val zipDir = File(zipPath)
+ if (!zipDir.exists() || !zipDir.isDirectory) {
+ zipDir.mkdirs()
+ }
+
+ //创建压缩文件保存的文件对象
+ val zipFilePath = zipPath + File.separator + zipFileName
+ val zipFile = File(zipFilePath)
+ if (zipFile.exists()) {
+ //检测文件是否允许删除,如果不允许删除,将会抛出SecurityException
+ val securityManager = SecurityManager()
+ securityManager.checkDelete(zipFilePath)
+ //删除已存在的目标文件
+ zipFile.delete()
+ }
+
+ val cos = CheckedOutputStream(FileOutputStream(zipFile), CRC32())
+ val zos = ZipOutputStream(cos)
+
+ //如果只是压缩一个文件,则需要截取该文件的父目录
+ var srcRootDir = srcPath
+ if (srcFile.isFile) {
+ val index = srcPath.lastIndexOf(File.separator)
+ if (index != -1) {
+ srcRootDir = srcPath.substring(0, index)
+ }
+ }
+ //调用递归压缩方法进行目录或文件压缩
+ zip(srcRootDir, srcFile, zos)
+ zos.flush()
+ zos.close()
+ } catch (e: Exception) {
+ throw e
+ }
+
+ }
+
+ /**
+ * 解压缩zip包
+ *
+ * @param zipFilePath zip文件的全路径
+ * @param unzipFilePath 解压后的文件保存的路径
+ * @param includeZipFileName 解压后的文件保存的路径是否包含压缩文件的文件名。true-包含;false-不包含
+ */
+ @Throws(Exception::class)
+ fun unzip(zipFilePath: String, unzipFilePath: String, includeZipFileName: Boolean) {
+ var unzipFilePath = unzipFilePath
+ if (StringUtils.isEmpty(zipFilePath) || StringUtils.isEmpty(unzipFilePath)) {
+ throw Exception("传入参数为空")
+ }
+ val zipFile = File(zipFilePath)
+ //如果解压后的文件保存路径包含压缩文件的文件名,则追加该文件名到解压路径
+ if (includeZipFileName) {
+ var fileName = zipFile.name
+ if (StringUtils.isNotEmpty(fileName)) {
+ fileName = fileName.substring(0, fileName.lastIndexOf("."))
+ }
+ unzipFilePath = unzipFilePath + File.separator + fileName
+ }
+ //创建解压缩文件保存的路径
+ val unzipFileDir = File(unzipFilePath)
+ if (!unzipFileDir.exists() || !unzipFileDir.isDirectory) {
+ unzipFileDir.mkdirs()
+ }
+
+ //开始解压
+ val bufferSize = 1024
+ val buffer = ByteArray(bufferSize)
+ val zip = ZipFile(zipFile)
+ val entries = zip.entries() as Enumeration<ZipEntry>
+ //循环对压缩包里的每一个文件进行解压
+ while (entries.hasMoreElements()) {
+ val entry = entries.nextElement()
+ //构建压缩包中一个文件解压后保存的文件全路径
+ val entryFilePath = unzipFilePath + File.separator + entry.name
+ //构建解压后保存的文件夹路径
+ val index = entryFilePath.lastIndexOf(File.separator)
+ var entryDirPath = ""
+ if (index != -1) {
+ entryDirPath = entryFilePath.substring(0, index)
+ }
+ val entryDir = File(entryDirPath)
+ //如果文件夹路径不存在,则创建文件夹
+ if (!entryDir.exists() || !entryDir.isDirectory) {
+ entryDir.mkdirs()
+ }
+
+ //创建解压文件
+ val entryFile = File(entryFilePath)
+ if (entryFile.exists()) {
+ //检测文件是否允许删除,如果不允许删除,将会抛出SecurityException
+ val securityManager = SecurityManager()
+ securityManager.checkDelete(entryFilePath)
+ //删除已存在的目标文件
+ entryFile.delete()
+ }
+
+ //写入文件
+ val bos = BufferedOutputStream(FileOutputStream(entryFile))
+ val bis = BufferedInputStream(zip.getInputStream(entry))
+ var count: Int
+ while (true) {
+ count = bis.read(buffer, 0, bufferSize)
+ if (count < 0) {
+ break
+ }
+ bos.write(buffer, 0, count)
+ }
+ bos.flush()
+ bos.close()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/view/BigProgressDialog.kt b/app/src/main/java/com/supwisdom/view/BigProgressDialog.kt
new file mode 100644
index 0000000..9fd9825
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/view/BigProgressDialog.kt
@@ -0,0 +1,47 @@
+package com.supwisdom.view
+
+import android.app.Activity
+import android.app.ProgressDialog
+import android.content.Context
+import android.view.Gravity
+import android.widget.TextView
+import com.supwisdom.R
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+@Suppress("DEPRECATION")
+class BigProgressDialog constructor(context: Context, strMessage: String, cancelable: Boolean) :
+ ProgressDialog(context) {
+ private var tvMsg: TextView
+
+ init {
+ this.show()
+ this.setContentView(R.layout.dialog_progress)
+ this.window!!.attributes.gravity = Gravity.CENTER
+ tvMsg = this.findViewById<TextView>(R.id.loadingmsg)
+ this.setCancelable(cancelable)
+ setCanceledOnTouchOutside(false)
+ tvMsg.text = strMessage
+ }
+
+ fun setMsg(msg: String) {
+ tvMsg.text = msg
+ }
+
+ override fun show() {
+ if (!(context as Activity).isFinishing) {
+ //防止activity处于销毁状态
+ //android.view.WindowManager$BadTokenException: Unable to add window
+ // -- token android.os.BinderProxy@41b43ec0 is not valid; is your activity running
+ super.show()
+ }
+ }
+
+ override fun dismiss() {
+ if (!(context as Activity).isFinishing) {
+ super.dismiss()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/view/BigSwDialog.kt b/app/src/main/java/com/supwisdom/view/BigSwDialog.kt
new file mode 100644
index 0000000..45fa8f3
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/view/BigSwDialog.kt
@@ -0,0 +1,30 @@
+package com.supwisdom.view
+
+import android.content.Context
+import android.view.KeyEvent
+import com.supwisdom.R
+import com.supwisdom.utils.PublicDef
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+class BigSwDialog constructor(context: Context, dialogType: Int) : DialogBase(context) {
+ init {
+ when (dialogType) {
+ PublicDef.DIALOG_TYPE_PASSWORD -> this.setContentView(R.layout.dialog_password)
+ PublicDef.DIALOG_TYPE_NSD_CONFIG -> this.setContentView(R.layout.dialog_init_nsd_config)
+ }
+ this.setCancelable(false)
+ this.setCanceledOnTouchOutside(false)
+ }
+
+ override fun dispatchKeyEvent(event: KeyEvent): Boolean {
+ if (event.action == KeyEvent.ACTION_DOWN) {
+ when (event.keyCode) {
+ KeyEvent.KEYCODE_DEL -> dismiss()
+ }
+ }
+ return super.dispatchKeyEvent(event)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/view/DialogBase.kt b/app/src/main/java/com/supwisdom/view/DialogBase.kt
new file mode 100644
index 0000000..bb6d40b
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/view/DialogBase.kt
@@ -0,0 +1,47 @@
+package com.supwisdom.view
+
+import android.app.Activity
+import android.app.Dialog
+import android.content.Context
+import com.supwisdom.R
+
+/**
+ * @author zzq
+ * @date 2018/6/7
+ * @desc 基类dialog
+ */
+open class DialogBase constructor(context: Context) : Dialog(context, R.style.FloatingDialog) {
+ private val ctx = context
+
+ override fun show() {
+ if (ctx is Activity) {
+ if (!ctx.isFinishing) {
+ //防止activity处于销毁状态
+ //android.view.WindowManager$BadTokenException: Unable to add window
+ // -- token android.os.BinderProxy@41b43ec0 is not valid; is your activity running
+ super.show()
+ }
+ } else {
+// val activity = (ctx as ContextWrapper).baseContext as Activity
+// if (!activity.isFinishing) {
+ //防止activity处于销毁状态
+ //android.view.WindowManager$BadTokenException: Unable to add window
+ // -- token android.os.BinderProxy@41b43ec0 is not valid; is your activity running
+ super.show()
+// }
+ }
+ }
+
+ override fun dismiss() {
+ if (ctx is Activity) {
+ if (!ctx.isFinishing) {
+ super.dismiss()
+ }
+ } else {
+// val activity = (ctx as ContextWrapper).baseContext as Activity
+// if (!activity.isFinishing) {
+ super.dismiss()
+// }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/view/DialogPurchase.kt b/app/src/main/java/com/supwisdom/view/DialogPurchase.kt
new file mode 100644
index 0000000..39b5806
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/view/DialogPurchase.kt
@@ -0,0 +1,223 @@
+package com.supwisdom.view
+
+import android.content.Context
+import android.graphics.Color
+import android.os.CountDownTimer
+import android.view.KeyEvent
+import android.view.View
+import android.widget.TextView
+import com.google.zxing.Result
+import com.newcapec.zxinglib.IDecoderAcquirer
+import com.newcapec.zxinglib.PosDecoder
+import com.supwisdom.R
+import com.supwisdom.activities.consume.bean.CardUserInfoBean
+import com.supwisdom.utils.CommonUtil
+import com.supwisdom.utils.LogUtil
+
+/**
+ ** create by zzq on 2019/7/26
+ ** @desc 消费弹窗
+ **/
+class DialogPurchase constructor(context: Context, callBack: ICallBack) : DialogBase(context), IDecoderAcquirer {
+ private val TAG = "DialogPurchase"
+ private val callBack = callBack
+ private var vCount: TextView
+ private var vPayhint: TextView
+ private var vPayamt: TextView
+ private var vBalance: TextView
+ private var posDec: PosDecoder? = null
+ private var lastFixpayDecoderOpenTime: Long = 0
+ private val waitTime = 60
+ var codePayingNoCancelEnable = false
+ var codePaying = false
+ var isFixPay = false
+
+ init {
+ setContentView(R.layout.dialog_purchase)
+
+ vCount = this.findViewById(R.id.tv_close_count) as TextView
+ vPayhint = this.findViewById(R.id.tv_pay_hint) as TextView
+ vPayamt = this.findViewById(R.id.tv_pay_amount) as TextView
+ vBalance = this.findViewById(R.id.tv_pay_balance) as TextView
+
+ posDec = PosDecoder(this)
+ }
+
+ override fun onFailed() {
+
+ }
+
+ override fun onDecoded(result: String?) {
+
+ }
+
+ override fun onDecoded(result: Result?) {
+ val rawSize = result?.rawBytes?.size ?: 0
+ if (rawSize > 0) {
+ callBack.callback(result!!.text)
+ }
+ }
+
+ override fun dispatchKeyEvent(event: KeyEvent): Boolean {
+ if (event.action == KeyEvent.ACTION_DOWN) {
+ if (codePayingNoCancelEnable) {
+ return super.dispatchKeyEvent(event)
+ }
+ when (event.keyCode) {
+ KeyEvent.KEYCODE_DEL -> {
+ finish(true)
+ }
+ }
+ }
+ return super.dispatchKeyEvent(event)
+ }
+
+ fun show(hint: String, amount: String) {
+ vPayhint.text = hint
+ vPayhint.setTextColor(Color.BLACK)
+ vPayamt.text = amount
+ vPayamt.visibility = View.VISIBLE
+
+ vBalance.visibility = View.GONE
+ show()
+ asyncOpenDecoder()
+ resetCounter(waitTime)
+ }
+
+ fun showProcess(hint: String, amount: String) {
+ vPayhint.text = hint
+ vPayhint.setTextColor(Color.RED)
+ vPayamt.text = amount
+ vPayamt.visibility = View.VISIBLE
+
+ vBalance.visibility = View.GONE
+ resetCounter(waitTime)
+ }
+
+ fun showPaySuccess(info: CardUserInfoBean) {
+ vPayhint.text = info.retmsg
+ vPayhint.setTextColor(Color.GREEN)
+ vPayamt.text = CommonUtil.showFormatAmount("金额", info.payamt)
+ vPayamt.visibility = View.VISIBLE
+ if (info.balance == null) {
+ vBalance.visibility = View.GONE
+ } else {
+ vBalance.text = CommonUtil.showFormatAmount("余额", info.balance!!)
+ vBalance.visibility = View.VISIBLE
+ }
+ show()
+ resetCounter(info.showtime)
+ }
+
+ fun showPayFail(info: CardUserInfoBean) {
+ vPayhint.text = "消费失败"
+ vPayhint.setTextColor(Color.RED)
+ vPayamt.text = info.retmsg
+ vPayamt.visibility = View.VISIBLE
+ vBalance.visibility = View.GONE
+ show()
+ resetCounter(info.showtime)
+ }
+
+ fun showReverseSuccess(info: CardUserInfoBean) {
+ vPayhint.text = info.retmsg
+ vPayhint.setTextColor(Color.GREEN)
+ vPayamt.text = CommonUtil.showFormatAmount("金额", info.amount)
+ vPayamt.visibility = View.VISIBLE
+ vBalance.visibility = View.GONE
+ show()
+ resetCounter(info.showtime)
+ }
+
+ fun showReverseFail(info: CardUserInfoBean) {
+ vPayhint.text = "冲正失败"
+ vPayhint.setTextColor(Color.RED)
+ vPayamt.text = info.retmsg
+ vPayamt.visibility = View.VISIBLE
+ vBalance.visibility = View.GONE
+ show()
+ resetCounter(info.showtime)
+ }
+
+ private fun asyncOpenDecoder() {
+ if (!isFixPay) {
+ try {
+ posDec!!.onResume()
+ } catch (ex: Exception) {
+ ex.printStackTrace()
+ LogUtil.d(TAG, "open camera exception:" + CommonUtil.getExceptionStack(ex))
+ }
+ } else {
+ val time = System.currentTimeMillis()
+ if (time < lastFixpayDecoderOpenTime ||
+ time - lastFixpayDecoderOpenTime > 120000
+ ) {
+ lastFixpayDecoderOpenTime = time
+ try {
+ posDec!!.onPause()
+ } catch (ex: Exception) {
+ ex.printStackTrace()
+ LogUtil.d(TAG, "fix close camera exception:" + CommonUtil.getExceptionStack(ex))
+ }
+ try {
+ posDec!!.onResume()
+ } catch (ex: Exception) {
+ ex.printStackTrace()
+ LogUtil.d(TAG, "fix open camera exception:" + CommonUtil.getExceptionStack(ex))
+ }
+ }
+ }
+ }
+
+ private fun asyncCloseDecoder() {
+ if (!isFixPay) {
+ try {
+ posDec!!.onPause()
+ } catch (ex: Exception) {
+ ex.printStackTrace()
+ LogUtil.d(TAG, "close camera exception:" + CommonUtil.getExceptionStack(ex))
+ }
+ }
+ }
+
+ private fun finish(isManualCancel: Boolean) {
+ codePaying = false
+ codePayingNoCancelEnable = false
+ dismiss()
+ callBack.callback(isManualCancel)
+ asyncCloseDecoder()
+ }
+
+ private var counter: ConsumeHintCount? = null
+
+ private fun resetCounter(times: Int) {
+ counter?.cancel()
+ counter = ConsumeHintCount((times * 1000).toLong(), 200)
+ counter?.start()
+ }
+
+ private inner class ConsumeHintCount
+ /**
+ * @param millisInFuture The number of millis in the future from the call
+ * to [.login] until the countdown is done and [.onFinish]
+ * is called.
+ * @param countDownInterval The interval along the way to receive
+ * [.onTick] callbacks.
+ */
+ (millisInFuture: Long, countDownInterval: Long) : CountDownTimer(millisInFuture, countDownInterval) {
+
+ override fun onTick(millisUntilFinished: Long) {
+ vCount.text = "${millisUntilFinished / 1000}s"
+ }
+
+ override fun onFinish() {
+ finish(false)
+ }
+ }
+
+ interface ICallBack {
+ fun callback(isManualCancel: Boolean)
+
+ fun callback(code: String)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/view/ListViewUtil.kt b/app/src/main/java/com/supwisdom/view/ListViewUtil.kt
new file mode 100644
index 0000000..cef2581
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/view/ListViewUtil.kt
@@ -0,0 +1,43 @@
+package com.supwisdom.view
+
+import android.widget.ListView
+
+/**
+ * @author zzq
+ * @date 2018/5/9.
+ * @version 1.0.1
+ * @desc 动态测量adapter listview的高度
+ */
+object ListViewUtil {
+ fun setListViewHeightBasedOnChildren(listView: ListView) {
+ val listAdapter = listView.adapter ?: return
+
+ var totalHeight = 0
+ for (i in 0 until listAdapter.count) {
+ val listItem = listAdapter.getView(i, null, listView)
+ listItem.measure(0, 0)
+ totalHeight += listItem.measuredHeight
+ }
+
+ val params = listView.layoutParams
+ params.height = totalHeight + listView.dividerHeight * (listAdapter.count - 1)
+ listView.layoutParams = params
+ }
+
+ fun getListViewHeightBasedOnChildren(listView: ListView): Int {
+ val listAdapter = listView.adapter
+ var totalHeight = 0
+ for (i in 0 until listAdapter.count) {
+ val listItem = listAdapter.getView(i, null, listView)
+ listItem.measure(0, 0)
+ totalHeight += listItem.measuredHeight
+ }
+ return totalHeight + listView.dividerHeight * (listAdapter.count - 1)
+ }
+
+ fun setListViewHeight(listView: ListView, height: Int) {
+ val params = listView.layoutParams
+ params.height = height
+ listView.layoutParams = params
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/view/RecyclerViewUtil.kt b/app/src/main/java/com/supwisdom/view/RecyclerViewUtil.kt
new file mode 100644
index 0000000..7af0cd0
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/view/RecyclerViewUtil.kt
@@ -0,0 +1,26 @@
+package com.supwisdom.view
+
+import android.graphics.Rect
+import android.support.v7.widget.RecyclerView
+import android.view.View
+
+/**
+ * @author zzq
+ * @date 2018/6/21
+ * @desc TODO
+ */
+object RecyclerViewUtil {
+ class ItemDecoration constructor(top: Int, bottom: Int, left: Int, right: Int) : RecyclerView.ItemDecoration() {
+ private val top = top
+ private val bottom = bottom
+ private val left = left
+ private val right = right
+ override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
+ super.getItemOffsets(outRect, view, parent, state)
+ outRect!!.top = top
+ outRect.left = left
+ outRect.bottom = bottom
+ outRect.right = right
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/view/SWToast.kt b/app/src/main/java/com/supwisdom/view/SWToast.kt
new file mode 100644
index 0000000..deb3fa2
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/view/SWToast.kt
@@ -0,0 +1,53 @@
+package com.supwisdom.view
+
+import android.content.Context
+import android.view.Gravity
+import android.view.LayoutInflater
+import android.view.View
+import android.widget.ImageView
+import android.widget.TextView
+import android.widget.Toast
+import com.supwisdom.R
+import com.supwisdom.utils.PublicDef
+
+/**
+ ** create by zzq on 2019/7/24
+ ** @desc
+ **/
+object SWToast {
+ fun show(context: Context, msg: String, showway: Int) {
+ val Inflater = LayoutInflater.from(context)
+ val layout = Inflater.inflate(R.layout.sw_toast, null)
+
+ val cry = layout.findViewById(R.id.pic_cry) as ImageView
+ val smile = layout.findViewById(R.id.pic_smile) as ImageView
+ val doubt = layout.findViewById(R.id.pic_doubt) as ImageView
+ if (showway == PublicDef.TOAST_SHOW_CRY) {
+ cry.visibility = View.VISIBLE
+ smile.visibility = View.GONE
+ doubt.visibility = View.GONE
+ } else if (showway == PublicDef.TOAST_SHOW_SMILE) {
+ cry.visibility = View.GONE
+ smile.visibility = View.VISIBLE
+ doubt.visibility = View.GONE
+ } else if (showway == PublicDef.TOAST_SHOW_DOUBT) {
+ cry.visibility = View.GONE
+ smile.visibility = View.GONE
+ doubt.visibility = View.VISIBLE
+ } else {
+ cry.visibility = View.GONE
+ smile.visibility = View.VISIBLE
+ doubt.visibility = View.GONE
+ }
+
+ // set a message
+ val toastText = layout.findViewById(R.id.toasttext) as TextView
+ toastText.text = msg
+ // Toast...
+ val toast = Toast(context)
+ toast.setGravity(Gravity.CENTER, 0, 0)
+ toast.duration = Toast.LENGTH_SHORT
+ toast.view = layout
+ toast.show()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/supwisdom/view/ToastUtil.kt b/app/src/main/java/com/supwisdom/view/ToastUtil.kt
new file mode 100644
index 0000000..7d82257
--- /dev/null
+++ b/app/src/main/java/com/supwisdom/view/ToastUtil.kt
@@ -0,0 +1,86 @@
+package com.supwisdom.view
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.os.CountDownTimer
+import android.view.Gravity
+import android.view.LayoutInflater
+import android.widget.TextView
+import android.widget.Toast
+import com.supwisdom.R
+
+/**
+ * @author zzq
+ * @date 2018/3/20.
+ * @version 1.0.1
+ * @desc 界面操作提示
+ */
+@SuppressLint("StaticFieldLeak")
+object ToastUtil {
+ private var toast: Toast? = null
+ private var toastText: TextView? = null
+ private var counter: CountDownTimer? = null
+
+ private var toast1: Toast? = null
+ private var toastText1: TextView? = null
+
+ fun show(context: Context, msg: String) {
+ if (toast1 == null) {
+ toast1 = Toast(context)
+ val view = LayoutInflater.from(context).inflate(R.layout.toast_util, null)
+ toastText1 = view.findViewById(R.id.toasttext) as TextView
+ toast1!!.setGravity(Gravity.CENTER, 0, 0)
+ toast1!!.duration = Toast.LENGTH_SHORT
+ toast1!!.view = view
+ }
+ toastText1!!.text = msg
+ toast1!!.show()
+ }
+
+ fun show(context: Context, msg: String, listener: ShowListener?) {
+ if (toast == null) {
+ toast = Toast(context)
+ val view = LayoutInflater.from(context).inflate(R.layout.toast_util, null)
+
+ toastText = view.findViewById(R.id.toasttext) as TextView
+ toast!!.setGravity(Gravity.CENTER, 0, 0)
+ toast!!.duration = Toast.LENGTH_LONG
+ toast!!.view = view
+ }
+ toastText!!.text = msg
+ toast!!.show()
+ if (counter == null) {
+ counter = object : CountDownTimer(2000, 200) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ listener?.callback()
+ toast!!.cancel()
+ }
+ }
+ } else {
+ counter!!.cancel()
+ counter = object : CountDownTimer(2000, 200) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ listener?.callback()
+ toast!!.cancel()
+ }
+ }
+ }
+ counter!!.start()
+ }
+
+ fun cancel() {
+ toast!!.cancel()
+ }
+
+ interface ShowListener {
+ fun callback()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/jniLibs/arm64-v8a/libalipay_code_verify.so b/app/src/main/jniLibs/arm64-v8a/libalipay_code_verify.so
new file mode 100644
index 0000000..8437590
--- /dev/null
+++ b/app/src/main/jniLibs/arm64-v8a/libalipay_code_verify.so
Binary files differ
diff --git a/app/src/main/jniLibs/arm64-v8a/libauxScreen.so b/app/src/main/jniLibs/arm64-v8a/libauxScreen.so
new file mode 100644
index 0000000..01741bf
--- /dev/null
+++ b/app/src/main/jniLibs/arm64-v8a/libauxScreen.so
Binary files differ
diff --git a/app/src/main/jniLibs/arm64-v8a/libcrypto.so b/app/src/main/jniLibs/arm64-v8a/libcrypto.so
new file mode 100644
index 0000000..e4841ff
--- /dev/null
+++ b/app/src/main/jniLibs/arm64-v8a/libcrypto.so
Binary files differ
diff --git a/app/src/main/jniLibs/arm64-v8a/libiccV108.so b/app/src/main/jniLibs/arm64-v8a/libiccV108.so
new file mode 100644
index 0000000..608edea
--- /dev/null
+++ b/app/src/main/jniLibs/arm64-v8a/libiccV108.so
Binary files differ
diff --git a/app/src/main/jniLibs/arm64-v8a/libiccV110.so b/app/src/main/jniLibs/arm64-v8a/libiccV110.so
new file mode 100644
index 0000000..c2ef8cc
--- /dev/null
+++ b/app/src/main/jniLibs/arm64-v8a/libiccV110.so
Binary files differ
diff --git a/app/src/main/jniLibs/arm64-v8a/libiccV115.so b/app/src/main/jniLibs/arm64-v8a/libiccV115.so
new file mode 100644
index 0000000..61635a1
--- /dev/null
+++ b/app/src/main/jniLibs/arm64-v8a/libiccV115.so
Binary files differ
diff --git a/app/src/main/jniLibs/arm64-v8a/libiccV116.so b/app/src/main/jniLibs/arm64-v8a/libiccV116.so
new file mode 100644
index 0000000..c2ef8cc
--- /dev/null
+++ b/app/src/main/jniLibs/arm64-v8a/libiccV116.so
Binary files differ
diff --git a/app/src/main/jniLibs/arm64-v8a/libpiccV108.so b/app/src/main/jniLibs/arm64-v8a/libpiccV108.so
new file mode 100644
index 0000000..c62695a
--- /dev/null
+++ b/app/src/main/jniLibs/arm64-v8a/libpiccV108.so
Binary files differ
diff --git a/app/src/main/jniLibs/arm64-v8a/libpiccV115.so b/app/src/main/jniLibs/arm64-v8a/libpiccV115.so
new file mode 100644
index 0000000..df17f28
--- /dev/null
+++ b/app/src/main/jniLibs/arm64-v8a/libpiccV115.so
Binary files differ
diff --git a/app/src/main/jniLibs/arm64-v8a/libpiccV116.so b/app/src/main/jniLibs/arm64-v8a/libpiccV116.so
new file mode 100644
index 0000000..df17f28
--- /dev/null
+++ b/app/src/main/jniLibs/arm64-v8a/libpiccV116.so
Binary files differ
diff --git a/app/src/main/jniLibs/arm64-v8a/libserial_port.so b/app/src/main/jniLibs/arm64-v8a/libserial_port.so
new file mode 100644
index 0000000..7cd1a8a
--- /dev/null
+++ b/app/src/main/jniLibs/arm64-v8a/libserial_port.so
Binary files differ
diff --git a/app/src/main/jniLibs/arm64-v8a/libssl.so b/app/src/main/jniLibs/arm64-v8a/libssl.so
new file mode 100644
index 0000000..cea745d
--- /dev/null
+++ b/app/src/main/jniLibs/arm64-v8a/libssl.so
Binary files differ
diff --git a/app/src/main/jniLibs/arm64-v8a/libswbarcode.so b/app/src/main/jniLibs/arm64-v8a/libswbarcode.so
new file mode 100644
index 0000000..f7c2d94
--- /dev/null
+++ b/app/src/main/jniLibs/arm64-v8a/libswbarcode.so
Binary files differ
diff --git a/app/src/main/jniLibs/armeabi-v7a/libalipay_code_verify.so b/app/src/main/jniLibs/armeabi-v7a/libalipay_code_verify.so
new file mode 100644
index 0000000..2419998
--- /dev/null
+++ b/app/src/main/jniLibs/armeabi-v7a/libalipay_code_verify.so
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/app_logo.png b/app/src/main/res/drawable-hdpi/app_logo.png
new file mode 100644
index 0000000..b4073ad
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/app_logo.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/consume_middle_background.png b/app/src/main/res/drawable-hdpi/consume_middle_background.png
new file mode 100644
index 0000000..9af8c90
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/consume_middle_background.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/iconerrork.png b/app/src/main/res/drawable-hdpi/iconerrork.png
new file mode 100644
index 0000000..57493fe
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/iconerrork.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/iconfont_del.png b/app/src/main/res/drawable-hdpi/iconfont_del.png
new file mode 100644
index 0000000..6c89d1c
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/iconfont_del.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/loading.png b/app/src/main/res/drawable-hdpi/loading.png
new file mode 100644
index 0000000..c9acbab
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/loading.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/loading_white.png b/app/src/main/res/drawable-hdpi/loading_white.png
new file mode 100644
index 0000000..abfb07f
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/loading_white.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/minus.png b/app/src/main/res/drawable-hdpi/minus.png
new file mode 100644
index 0000000..e672aaf
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/minus.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/minus_click.png b/app/src/main/res/drawable-hdpi/minus_click.png
new file mode 100644
index 0000000..580c410
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/minus_click.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/pay_fail.png b/app/src/main/res/drawable-hdpi/pay_fail.png
new file mode 100644
index 0000000..9b0ac71
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/pay_fail.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/pay_success.png b/app/src/main/res/drawable-hdpi/pay_success.png
new file mode 100644
index 0000000..62ed4e2
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/pay_success.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/scrollbar.xml b/app/src/main/res/drawable-hdpi/scrollbar.xml
new file mode 100644
index 0000000..8289699
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/scrollbar.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <gradient
+ android:startColor="#505050"
+ android:endColor="#C0C0C0"
+ android:angle="0" />
+ <corners android:radius="0dp" />
+</shape>
\ No newline at end of file
diff --git a/app/src/main/res/drawable-hdpi/scrollbar_bg.xml b/app/src/main/res/drawable-hdpi/scrollbar_bg.xml
new file mode 100644
index 0000000..2a31b9e
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/scrollbar_bg.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <gradient
+ android:startColor="#ffff792a"
+ android:endColor="#ffff792a"
+ android:angle="0" />
+ <corners android:radius="4dp" />
+</shape>
\ No newline at end of file
diff --git a/app/src/main/res/drawable-hdpi/user_logo.png b/app/src/main/res/drawable-hdpi/user_logo.png
new file mode 100644
index 0000000..138412d
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/user_logo.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/user_logo_default.png b/app/src/main/res/drawable-hdpi/user_logo_default.png
new file mode 100644
index 0000000..2ae652f
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/user_logo_default.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/all_back_focus.png b/app/src/main/res/drawable-mdpi/all_back_focus.png
new file mode 100644
index 0000000..8f98e97
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/all_back_focus.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/all_back_normal.png b/app/src/main/res/drawable-mdpi/all_back_normal.png
new file mode 100644
index 0000000..cb831ce
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/all_back_normal.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/all_home_focus.png b/app/src/main/res/drawable-mdpi/all_home_focus.png
new file mode 100644
index 0000000..23050ea
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/all_home_focus.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/all_home_normal.png b/app/src/main/res/drawable-mdpi/all_home_normal.png
new file mode 100644
index 0000000..db94187
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/all_home_normal.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/arrow.png b/app/src/main/res/drawable-mdpi/arrow.png
new file mode 100644
index 0000000..24bf7da
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/arrow.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/background.jpg b/app/src/main/res/drawable-mdpi/background.jpg
new file mode 100644
index 0000000..dfeb4af
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/background.jpg
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/bak_minus_focus.png b/app/src/main/res/drawable-mdpi/bak_minus_focus.png
new file mode 100644
index 0000000..230fe76
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/bak_minus_focus.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/bak_minus_normal.png b/app/src/main/res/drawable-mdpi/bak_minus_normal.png
new file mode 100644
index 0000000..c6c9d67
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/bak_minus_normal.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/big_picture_count_bak.png b/app/src/main/res/drawable-mdpi/big_picture_count_bak.png
new file mode 100644
index 0000000..4b3aa81
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/big_picture_count_bak.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/btn_red_click.png b/app/src/main/res/drawable-mdpi/btn_red_click.png
new file mode 100644
index 0000000..580c410
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/btn_red_click.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/btn_red_normal.png b/app/src/main/res/drawable-mdpi/btn_red_normal.png
new file mode 100644
index 0000000..f447037
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/btn_red_normal.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/btn_rf_cancel_focus.png b/app/src/main/res/drawable-mdpi/btn_rf_cancel_focus.png
new file mode 100644
index 0000000..622b075
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/btn_rf_cancel_focus.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/btn_rf_cancel_normal.png b/app/src/main/res/drawable-mdpi/btn_rf_cancel_normal.png
new file mode 100644
index 0000000..c6dda8e
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/btn_rf_cancel_normal.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/btn_rf_start_focus.png b/app/src/main/res/drawable-mdpi/btn_rf_start_focus.png
new file mode 100644
index 0000000..93ac164
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/btn_rf_start_focus.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/btn_rf_start_normal.png b/app/src/main/res/drawable-mdpi/btn_rf_start_normal.png
new file mode 100644
index 0000000..2565a57
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/btn_rf_start_normal.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/consume_cancel_focus.png b/app/src/main/res/drawable-mdpi/consume_cancel_focus.png
new file mode 100644
index 0000000..b5a7293
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/consume_cancel_focus.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/consume_cancel_normal.png b/app/src/main/res/drawable-mdpi/consume_cancel_normal.png
new file mode 100644
index 0000000..0ce3a04
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/consume_cancel_normal.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/consume_middle_background.png b/app/src/main/res/drawable-mdpi/consume_middle_background.png
new file mode 100644
index 0000000..4aabc91
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/consume_middle_background.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/consume_pay_focus.png b/app/src/main/res/drawable-mdpi/consume_pay_focus.png
new file mode 100644
index 0000000..f39b8b0
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/consume_pay_focus.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/consume_pay_normal.png b/app/src/main/res/drawable-mdpi/consume_pay_normal.png
new file mode 100644
index 0000000..3488719
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/consume_pay_normal.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/enable_btn_cancel_focus.png b/app/src/main/res/drawable-mdpi/enable_btn_cancel_focus.png
new file mode 100644
index 0000000..80a9edb
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/enable_btn_cancel_focus.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/enable_btn_cancel_normal.png b/app/src/main/res/drawable-mdpi/enable_btn_cancel_normal.png
new file mode 100644
index 0000000..75c0087
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/enable_btn_cancel_normal.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/enable_btn_next_focus.png b/app/src/main/res/drawable-mdpi/enable_btn_next_focus.png
new file mode 100644
index 0000000..1d0c2f4
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/enable_btn_next_focus.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/enable_btn_next_normal.png b/app/src/main/res/drawable-mdpi/enable_btn_next_normal.png
new file mode 100644
index 0000000..4db2d60
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/enable_btn_next_normal.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/enable_btn_next_unable.png b/app/src/main/res/drawable-mdpi/enable_btn_next_unable.png
new file mode 100644
index 0000000..0247799
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/enable_btn_next_unable.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/enable_middle_bak.png b/app/src/main/res/drawable-mdpi/enable_middle_bak.png
new file mode 100644
index 0000000..5ea5683
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/enable_middle_bak.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/main_offline.png b/app/src/main/res/drawable-mdpi/main_offline.png
new file mode 100644
index 0000000..a35326c
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/main_offline.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/main_online.png b/app/src/main/res/drawable-mdpi/main_online.png
new file mode 100644
index 0000000..06aed69
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/main_online.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/main_src_cancel_consume.png b/app/src/main/res/drawable-mdpi/main_src_cancel_consume.png
new file mode 100644
index 0000000..77d3e8e
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/main_src_cancel_consume.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/main_src_consume.png b/app/src/main/res/drawable-mdpi/main_src_consume.png
new file mode 100644
index 0000000..9d94ebf
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/main_src_consume.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/main_src_device_manage.png b/app/src/main/res/drawable-mdpi/main_src_device_manage.png
new file mode 100644
index 0000000..b0d32f1
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/main_src_device_manage.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/main_src_do_transdtl.png b/app/src/main/res/drawable-mdpi/main_src_do_transdtl.png
new file mode 100644
index 0000000..4524728
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/main_src_do_transdtl.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/main_src_hotel_consume.png b/app/src/main/res/drawable-mdpi/main_src_hotel_consume.png
new file mode 100644
index 0000000..cf50434
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/main_src_hotel_consume.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/main_src_manual_auth.png b/app/src/main/res/drawable-mdpi/main_src_manual_auth.png
new file mode 100644
index 0000000..6e69685
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/main_src_manual_auth.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/main_src_net_test.png b/app/src/main/res/drawable-mdpi/main_src_net_test.png
new file mode 100644
index 0000000..7993cae
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/main_src_net_test.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/main_src_online_order.png b/app/src/main/res/drawable-mdpi/main_src_online_order.png
new file mode 100644
index 0000000..7e0e456
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/main_src_online_order.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/main_src_query_para.png b/app/src/main/res/drawable-mdpi/main_src_query_para.png
new file mode 100644
index 0000000..b992a8d
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/main_src_query_para.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/main_src_query_revenue.png b/app/src/main/res/drawable-mdpi/main_src_query_revenue.png
new file mode 100644
index 0000000..30bb3f2
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/main_src_query_revenue.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/main_src_update_blacklist.png b/app/src/main/res/drawable-mdpi/main_src_update_blacklist.png
new file mode 100644
index 0000000..686a5a6
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/main_src_update_blacklist.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/main_src_upload_transdtl.png b/app/src/main/res/drawable-mdpi/main_src_upload_transdtl.png
new file mode 100644
index 0000000..6dc721a
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/main_src_upload_transdtl.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/order_big_picture_close_btn.png b/app/src/main/res/drawable-mdpi/order_big_picture_close_btn.png
new file mode 100644
index 0000000..4a21eef
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/order_big_picture_close_btn.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/order_big_picture_out_bak.png b/app/src/main/res/drawable-mdpi/order_big_picture_out_bak.png
new file mode 100644
index 0000000..6231b4b
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/order_big_picture_out_bak.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/order_btn_purchase.png b/app/src/main/res/drawable-mdpi/order_btn_purchase.png
new file mode 100644
index 0000000..416af7b
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/order_btn_purchase.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/order_clear_focus.png b/app/src/main/res/drawable-mdpi/order_clear_focus.png
new file mode 100644
index 0000000..20699ee
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/order_clear_focus.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/order_clear_normal.png b/app/src/main/res/drawable-mdpi/order_clear_normal.png
new file mode 100644
index 0000000..4a335ec
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/order_clear_normal.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/order_food_self_add_focus.png b/app/src/main/res/drawable-mdpi/order_food_self_add_focus.png
new file mode 100644
index 0000000..c86b446
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/order_food_self_add_focus.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/order_food_self_add_normal.png b/app/src/main/res/drawable-mdpi/order_food_self_add_normal.png
new file mode 100644
index 0000000..75788fc
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/order_food_self_add_normal.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/order_good_add_focus.png b/app/src/main/res/drawable-mdpi/order_good_add_focus.png
new file mode 100644
index 0000000..2d6d7f5
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/order_good_add_focus.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/order_good_add_normal.png b/app/src/main/res/drawable-mdpi/order_good_add_normal.png
new file mode 100644
index 0000000..cf026ba
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/order_good_add_normal.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/order_good_minus_focus.png b/app/src/main/res/drawable-mdpi/order_good_minus_focus.png
new file mode 100644
index 0000000..43a225c
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/order_good_minus_focus.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/order_good_minus_normal.png b/app/src/main/res/drawable-mdpi/order_good_minus_normal.png
new file mode 100644
index 0000000..ac58ec1
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/order_good_minus_normal.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/order_picture_out_bak.png b/app/src/main/res/drawable-mdpi/order_picture_out_bak.png
new file mode 100644
index 0000000..cd2a360
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/order_picture_out_bak.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/order_picture_zoom.png b/app/src/main/res/drawable-mdpi/order_picture_zoom.png
new file mode 100644
index 0000000..07558da
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/order_picture_zoom.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/order_purchase_focus.png b/app/src/main/res/drawable-mdpi/order_purchase_focus.png
new file mode 100644
index 0000000..cbf4d7f
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/order_purchase_focus.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/order_purchase_normal.png b/app/src/main/res/drawable-mdpi/order_purchase_normal.png
new file mode 100644
index 0000000..6907626
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/order_purchase_normal.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/pass_delete_click.png b/app/src/main/res/drawable-mdpi/pass_delete_click.png
new file mode 100644
index 0000000..d05207d
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/pass_delete_click.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/pass_delete_normal.png b/app/src/main/res/drawable-mdpi/pass_delete_normal.png
new file mode 100644
index 0000000..b77fc91
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/pass_delete_normal.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/pass_eight_click.png b/app/src/main/res/drawable-mdpi/pass_eight_click.png
new file mode 100644
index 0000000..c26ffd8
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/pass_eight_click.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/pass_eight_normal.png b/app/src/main/res/drawable-mdpi/pass_eight_normal.png
new file mode 100644
index 0000000..9b2ece0
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/pass_eight_normal.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/pass_five_click.png b/app/src/main/res/drawable-mdpi/pass_five_click.png
new file mode 100644
index 0000000..c555169
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/pass_five_click.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/pass_five_normal.png b/app/src/main/res/drawable-mdpi/pass_five_normal.png
new file mode 100644
index 0000000..3a6460b
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/pass_five_normal.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/pass_four_click.png b/app/src/main/res/drawable-mdpi/pass_four_click.png
new file mode 100644
index 0000000..8b2325f
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/pass_four_click.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/pass_four_normal.png b/app/src/main/res/drawable-mdpi/pass_four_normal.png
new file mode 100644
index 0000000..97bd59f
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/pass_four_normal.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/pass_nine_click.png b/app/src/main/res/drawable-mdpi/pass_nine_click.png
new file mode 100644
index 0000000..0aec332
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/pass_nine_click.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/pass_nine_normal.png b/app/src/main/res/drawable-mdpi/pass_nine_normal.png
new file mode 100644
index 0000000..76f2f37
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/pass_nine_normal.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/pass_one_click.png b/app/src/main/res/drawable-mdpi/pass_one_click.png
new file mode 100644
index 0000000..6dd704f
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/pass_one_click.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/pass_one_normal.png b/app/src/main/res/drawable-mdpi/pass_one_normal.png
new file mode 100644
index 0000000..ac0beaa
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/pass_one_normal.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/pass_seven_click.png b/app/src/main/res/drawable-mdpi/pass_seven_click.png
new file mode 100644
index 0000000..b685327
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/pass_seven_click.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/pass_seven_normal.png b/app/src/main/res/drawable-mdpi/pass_seven_normal.png
new file mode 100644
index 0000000..a1431b1
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/pass_seven_normal.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/pass_six_click.png b/app/src/main/res/drawable-mdpi/pass_six_click.png
new file mode 100644
index 0000000..c8501e2
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/pass_six_click.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/pass_six_normal.png b/app/src/main/res/drawable-mdpi/pass_six_normal.png
new file mode 100644
index 0000000..f4df1ff
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/pass_six_normal.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/pass_three_click.png b/app/src/main/res/drawable-mdpi/pass_three_click.png
new file mode 100644
index 0000000..55959a7
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/pass_three_click.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/pass_three_normal.png b/app/src/main/res/drawable-mdpi/pass_three_normal.png
new file mode 100644
index 0000000..5a76454
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/pass_three_normal.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/pass_two_click.png b/app/src/main/res/drawable-mdpi/pass_two_click.png
new file mode 100644
index 0000000..ba99d1d
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/pass_two_click.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/pass_two_normal.png b/app/src/main/res/drawable-mdpi/pass_two_normal.png
new file mode 100644
index 0000000..1a1e6e3
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/pass_two_normal.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/pass_zero_click.png b/app/src/main/res/drawable-mdpi/pass_zero_click.png
new file mode 100644
index 0000000..2e72719
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/pass_zero_click.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/pass_zero_normal.png b/app/src/main/res/drawable-mdpi/pass_zero_normal.png
new file mode 100644
index 0000000..7463c4a
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/pass_zero_normal.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/password_pwd_frame.png b/app/src/main/res/drawable-mdpi/password_pwd_frame.png
new file mode 100644
index 0000000..52bfc7b
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/password_pwd_frame.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/qrcode_scan_line.png b/app/src/main/res/drawable-mdpi/qrcode_scan_line.png
new file mode 100644
index 0000000..ead6117
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/qrcode_scan_line.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/query_next_focus.png b/app/src/main/res/drawable-mdpi/query_next_focus.png
new file mode 100644
index 0000000..34c49d8
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/query_next_focus.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/query_next_normal.png b/app/src/main/res/drawable-mdpi/query_next_normal.png
new file mode 100644
index 0000000..a026ed4
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/query_next_normal.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/query_prev_focus.png b/app/src/main/res/drawable-mdpi/query_prev_focus.png
new file mode 100644
index 0000000..e4681d0
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/query_prev_focus.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/query_prev_normal.png b/app/src/main/res/drawable-mdpi/query_prev_normal.png
new file mode 100644
index 0000000..d8415b1
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/query_prev_normal.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/star_full.png b/app/src/main/res/drawable-mdpi/star_full.png
new file mode 100644
index 0000000..e1ee5d3
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/star_full.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/star_normal.png b/app/src/main/res/drawable-mdpi/star_normal.png
new file mode 100644
index 0000000..119768c
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/star_normal.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/test_food.png b/app/src/main/res/drawable-mdpi/test_food.png
new file mode 100644
index 0000000..dedd453
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/test_food.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/test_food2.png b/app/src/main/res/drawable-mdpi/test_food2.png
new file mode 100644
index 0000000..4b14037
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/test_food2.png
Binary files differ
diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 0000000..6348baa
--- /dev/null
+++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,34 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:aapt="http://schemas.android.com/aapt"
+ android:width="108dp"
+ android:height="108dp"
+ android:viewportHeight="108"
+ android:viewportWidth="108">
+ <path
+ android:fillType="evenOdd"
+ android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
+ android:strokeColor="#00000000"
+ android:strokeWidth="1">
+ <aapt:attr name="android:fillColor">
+ <gradient
+ android:endX="78.5885"
+ android:endY="90.9159"
+ android:startX="48.7653"
+ android:startY="61.0927"
+ android:type="linear">
+ <item
+ android:color="#44000000"
+ android:offset="0.0"/>
+ <item
+ android:color="#00000000"
+ android:offset="1.0"/>
+ </gradient>
+ </aapt:attr>
+ </path>
+ <path
+ android:fillColor="#FFFFFF"
+ android:fillType="nonZero"
+ android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
+ android:strokeColor="#00000000"
+ android:strokeWidth="1"/>
+</vector>
diff --git a/app/src/main/res/drawable-xxhdpi/bar_progress_style.xml b/app/src/main/res/drawable-xxhdpi/bar_progress_style.xml
new file mode 100644
index 0000000..82dcdae
--- /dev/null
+++ b/app/src/main/res/drawable-xxhdpi/bar_progress_style.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <!-- 设置背景色(蓝色) -->
+ <item android:id="@android:id/background">
+ <shape>
+ <corners android:radius="6dp" />
+ <gradient
+ android:endColor="@color/light_gray"
+ android:startColor="@color/light_gray" />
+ </shape>
+ </item>
+
+ <!-- 设置进度条颜色(红色) -->
+ <item android:id="@android:id/progress">
+ <clip>
+ <shape>
+ <corners android:radius="6dp" />
+ <gradient
+ android:endColor="@color/light_green2"
+ android:startColor="@color/light_green2" />
+ </shape>
+ </clip>
+ </item>
+</layer-list>
\ No newline at end of file
diff --git a/app/src/main/res/drawable-xxhdpi/numbers/1.png b/app/src/main/res/drawable-xxhdpi/numbers/1.png
new file mode 100644
index 0000000..b1bb49f
--- /dev/null
+++ b/app/src/main/res/drawable-xxhdpi/numbers/1.png
Binary files differ
diff --git a/app/src/main/res/drawable/anonymous.jpg b/app/src/main/res/drawable/anonymous.jpg
new file mode 100644
index 0000000..9e4672e
--- /dev/null
+++ b/app/src/main/res/drawable/anonymous.jpg
Binary files differ
diff --git a/app/src/main/res/drawable/bcg.png b/app/src/main/res/drawable/bcg.png
new file mode 100644
index 0000000..1664e83
--- /dev/null
+++ b/app/src/main/res/drawable/bcg.png
Binary files differ
diff --git a/app/src/main/res/drawable/bg_dps_corner.xml b/app/src/main/res/drawable/bg_dps_corner.xml
new file mode 100644
index 0000000..9236194
--- /dev/null
+++ b/app/src/main/res/drawable/bg_dps_corner.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="#ee1"/>
+ <corners android:radius="8dip"/>
+ <stroke
+ android:width="1.0dip"
+ android:color="#e22221"/>
+</shape>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/big_progress_bg.xml b/app/src/main/res/drawable/big_progress_bg.xml
new file mode 100644
index 0000000..55134ec
--- /dev/null
+++ b/app/src/main/res/drawable/big_progress_bg.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<rotate xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/loading_white"
+ android:fromDegrees="0"
+ android:interpolator="@android:anim/cycle_interpolator"
+ android:pivotX="50%"
+ android:pivotY="50%"
+ android:toDegrees="1440" />
diff --git a/app/src/main/res/drawable/btn_cancel_selector.xml b/app/src/main/res/drawable/btn_cancel_selector.xml
new file mode 100644
index 0000000..5543cba
--- /dev/null
+++ b/app/src/main/res/drawable/btn_cancel_selector.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item android:state_focused="true" android:state_pressed="false">
+ <shape>
+ <solid android:color="#cccccc" />
+ <corners android:radius="8.0dip" />
+ </shape>
+ </item>
+ <item android:state_selected="true">
+ <shape>
+ <solid android:color="#bfbfbf" />
+ <corners android:radius="8.0dip" />
+ </shape>
+ </item>
+ <item android:state_pressed="true">
+ <shape>
+ <solid android:color="#bfbfbf" />
+ <corners android:radius="8.0dip" />
+ </shape>
+ </item>
+ <item android:state_pressed="false">
+ <shape>
+ <solid android:color="#cccccc" />
+ <corners android:radius="8.0dip" />
+ </shape>
+ </item>
+
+</selector>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/btn_num_selector.xml b/app/src/main/res/drawable/btn_num_selector.xml
new file mode 100644
index 0000000..498dc49
--- /dev/null
+++ b/app/src/main/res/drawable/btn_num_selector.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item android:state_focused="true" android:state_pressed="false">
+ <shape>
+ <solid android:color="#fff" />
+ <corners android:radius="8.0dip" />
+ <stroke android:width="1.0dip" android:color="#DEDBDE" />
+ </shape>
+ </item>
+ <item android:state_selected="true">
+ <shape>
+ <solid android:color="#bfbfbf" />
+ <corners android:radius="8.0dip" />
+ <stroke android:width="1.0dip" android:color="#DEDBDE" />
+ </shape>
+ </item>
+ <item android:state_pressed="true">
+ <shape>
+ <solid android:color="#bfbfbf" />
+ <corners android:radius="8.0dip" />
+ <stroke android:width="1.0dip" android:color="#DEDBDE" />
+ </shape>
+ </item>
+ <item android:state_pressed="false">
+ <shape>
+ <solid android:color="#fff" />
+ <corners android:radius="8.0dip" />
+ <stroke android:width="1.0dip" android:color="#DEDBDE" />
+ </shape>
+ </item>
+
+</selector>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/btn_ok_selector.xml b/app/src/main/res/drawable/btn_ok_selector.xml
new file mode 100644
index 0000000..8ee6c40
--- /dev/null
+++ b/app/src/main/res/drawable/btn_ok_selector.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item android:state_focused="true" android:state_pressed="false">
+ <shape>
+ <solid android:color="#08ae9e" />
+ <corners android:radius="8.0dip" />
+ </shape>
+ </item>
+ <item android:state_selected="true">
+ <shape>
+ <solid android:color="#08a191" />
+ <corners android:radius="8.0dip" />
+ </shape>
+ </item>
+ <item android:state_pressed="true">
+ <shape>
+ <solid android:color="#08a191" />
+ <corners android:radius="8.0dip" />
+ </shape>
+ </item>
+ <item android:state_pressed="false">
+ <shape>
+ <solid android:color="#08ae9e" />
+ <corners android:radius="8.0dip" />
+ </shape>
+ </item>
+
+</selector>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/btn_ok_selector_nocorner.xml b/app/src/main/res/drawable/btn_ok_selector_nocorner.xml
new file mode 100644
index 0000000..4cdb60c
--- /dev/null
+++ b/app/src/main/res/drawable/btn_ok_selector_nocorner.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item android:state_focused="true" android:state_pressed="false">
+ <shape>
+ <solid android:color="#08ae9e" />
+ </shape>
+ </item>
+ <item android:state_selected="true">
+ <shape>
+ <solid android:color="#08a191" />
+ </shape>
+ </item>
+ <item android:state_pressed="true">
+ <shape>
+ <solid android:color="#08a191" />
+ </shape>
+ </item>
+ <item android:state_pressed="false">
+ <shape>
+ <solid android:color="#08ae9e" />
+ </shape>
+ </item>
+
+</selector>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/btn_ok_white_selector.xml b/app/src/main/res/drawable/btn_ok_white_selector.xml
new file mode 100644
index 0000000..1db82f7
--- /dev/null
+++ b/app/src/main/res/drawable/btn_ok_white_selector.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item android:state_focused="true" android:state_pressed="false">
+ <shape>
+ <solid android:color="#fff" />
+ </shape>
+ </item>
+ <item android:state_selected="true">
+ <shape>
+ <solid android:color="#fff4f4f4" />
+ </shape>
+ </item>
+ <item android:state_pressed="true">
+ <shape>
+ <solid android:color="#fff4f4f4" />
+ </shape>
+ </item>
+ <item android:state_pressed="false">
+ <shape>
+ <solid android:color="#fff" />
+ </shape>
+ </item>
+
+</selector>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/corner_bg.xml b/app/src/main/res/drawable/corner_bg.xml
new file mode 100644
index 0000000..40c5b82
--- /dev/null
+++ b/app/src/main/res/drawable/corner_bg.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="#80ffffff" />
+ <corners android:radius="8dip" />
+ <stroke
+ android:width="1.0dip"
+ android:color="#ffc5c5c5" />
+</shape>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/corner_bg_1.xml b/app/src/main/res/drawable/corner_bg_1.xml
new file mode 100644
index 0000000..e6721a9
--- /dev/null
+++ b/app/src/main/res/drawable/corner_bg_1.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="#e0e0e0e0" />
+ <corners android:radius="8dip" />
+ <stroke
+ android:width="1.0dip"
+ android:color="#80ffffff" />
+</shape>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/corner_bg_dialog.xml b/app/src/main/res/drawable/corner_bg_dialog.xml
new file mode 100644
index 0000000..2276ba2
--- /dev/null
+++ b/app/src/main/res/drawable/corner_bg_dialog.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="#e6e6e6"/>
+ <corners android:radius="12dip"/>
+ <stroke
+ android:width="1.0dip"
+ android:color="#e6e6e6"/>
+</shape>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/corner_bg_dps_crashbtn_focus.xml b/app/src/main/res/drawable/corner_bg_dps_crashbtn_focus.xml
new file mode 100644
index 0000000..1108b54
--- /dev/null
+++ b/app/src/main/res/drawable/corner_bg_dps_crashbtn_focus.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="#7e1508"/>
+ <corners android:radius="12dip"/>
+ <stroke
+ android:width="1.0dip"
+ android:color="#721307"/>
+</shape>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/corner_bg_dps_crashbtn_normal.xml b/app/src/main/res/drawable/corner_bg_dps_crashbtn_normal.xml
new file mode 100644
index 0000000..7b7d04f
--- /dev/null
+++ b/app/src/main/res/drawable/corner_bg_dps_crashbtn_normal.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="#e24c17"/>
+ <corners android:radius="12dip"/>
+ <stroke
+ android:width="1.0dip"
+ android:color="#cc4616"/>
+</shape>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/corner_bg_gray.xml b/app/src/main/res/drawable/corner_bg_gray.xml
new file mode 100644
index 0000000..a198688
--- /dev/null
+++ b/app/src/main/res/drawable/corner_bg_gray.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="@color/light_gray" />
+ <corners android:radius="8dip" />
+ <stroke
+ android:width="1.0dip"
+ android:color="@color/light_gray" />
+</shape>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/corner_bg_keyboard_focus.xml b/app/src/main/res/drawable/corner_bg_keyboard_focus.xml
new file mode 100644
index 0000000..0f93672
--- /dev/null
+++ b/app/src/main/res/drawable/corner_bg_keyboard_focus.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="#807c7c"/>
+ <corners android:radius="12dip"/>
+ <stroke
+ android:width="1.0dip"
+ android:color="#807c7c"/>
+</shape>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/corner_bg_keyboard_normal.xml b/app/src/main/res/drawable/corner_bg_keyboard_normal.xml
new file mode 100644
index 0000000..7732d4b
--- /dev/null
+++ b/app/src/main/res/drawable/corner_bg_keyboard_normal.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="#ffffff"/>
+ <corners android:radius="12dip"/>
+ <stroke
+ android:width="1.0dip"
+ android:color="#ffffff"/>
+</shape>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/corner_bg_order_count_green.xml b/app/src/main/res/drawable/corner_bg_order_count_green.xml
new file mode 100644
index 0000000..fe44a58
--- /dev/null
+++ b/app/src/main/res/drawable/corner_bg_order_count_green.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="@color/light_green"/>
+ <corners android:radius="30dip"/>
+ <!--<stroke-->
+ <!--android:width="1.0dip"-->
+ <!--android:color="@color/light_green"/>-->
+ <gradient
+ android:angle="90"
+ android:endColor="@color/light_green2"
+ android:startColor="@color/light_green1"/>
+ <padding
+ android:bottom="1dp"
+ android:left="1dp"
+ android:right="1dp"
+ android:top="1dp"/>
+</shape>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/corner_bg_order_red.xml b/app/src/main/res/drawable/corner_bg_order_red.xml
new file mode 100644
index 0000000..5fa9c71
--- /dev/null
+++ b/app/src/main/res/drawable/corner_bg_order_red.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <corners android:radius="30dip"/>
+ <!--<stroke-->
+ <!--android:width="1.0dip"-->
+ <!--android:color="@color/cl_red"/>-->
+ <gradient
+ android:angle="90"
+ android:endColor="@color/cl_red"
+ android:startColor="@color/light_purple1"/>
+ <padding
+ android:bottom="1dp"
+ android:left="1dp"
+ android:right="1dp"
+ android:top="1dp"/>
+</shape>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/corner_bg_ordinary_consume_focus.xml b/app/src/main/res/drawable/corner_bg_ordinary_consume_focus.xml
new file mode 100644
index 0000000..0f93672
--- /dev/null
+++ b/app/src/main/res/drawable/corner_bg_ordinary_consume_focus.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="#807c7c"/>
+ <corners android:radius="12dip"/>
+ <stroke
+ android:width="1.0dip"
+ android:color="#807c7c"/>
+</shape>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/corner_bg_ordinary_consume_green.xml b/app/src/main/res/drawable/corner_bg_ordinary_consume_green.xml
new file mode 100644
index 0000000..d644a75
--- /dev/null
+++ b/app/src/main/res/drawable/corner_bg_ordinary_consume_green.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="#E3EFFF"/>
+ <corners android:radius="12dip"/>
+ <stroke
+ android:width="1.0dip"
+ android:color="#E3EFFF"/>
+</shape>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/corner_bg_ordinary_consume_normal.xml b/app/src/main/res/drawable/corner_bg_ordinary_consume_normal.xml
new file mode 100644
index 0000000..19b5879
--- /dev/null
+++ b/app/src/main/res/drawable/corner_bg_ordinary_consume_normal.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="#e0e0e0e0"/>
+ <corners android:radius="12dip"/>
+ <stroke
+ android:width="1.0dip"
+ android:color="#e0e0e0e0"/>
+</shape>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/corner_bg_qrcode_hint.xml b/app/src/main/res/drawable/corner_bg_qrcode_hint.xml
new file mode 100644
index 0000000..4f37389
--- /dev/null
+++ b/app/src/main/res/drawable/corner_bg_qrcode_hint.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="@color/orange1" />
+ <corners android:radius="30dip" />
+ <!--<stroke-->
+ <!--android:width="1.0dip"-->
+ <!--android:color="@color/cl_red" />-->
+</shape>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/corner_bg_simple_order.xml b/app/src/main/res/drawable/corner_bg_simple_order.xml
new file mode 100644
index 0000000..3fd3f7e
--- /dev/null
+++ b/app/src/main/res/drawable/corner_bg_simple_order.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="@color/light_green"/>
+ <corners android:radius="30dip"/>
+ <stroke
+ android:width="0.5dip"
+ android:color="@color/cl_red"/>
+</shape>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/corner_bg_simple_order_1.xml b/app/src/main/res/drawable/corner_bg_simple_order_1.xml
new file mode 100644
index 0000000..a33bba1
--- /dev/null
+++ b/app/src/main/res/drawable/corner_bg_simple_order_1.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="@color/light_yellow_3"/>
+ <corners android:radius="8dip"/>
+ <stroke
+ android:width="1.0dip"
+ android:color="@color/light_yellow_3"/>
+</shape>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/corner_bg_simple_order_2.xml b/app/src/main/res/drawable/corner_bg_simple_order_2.xml
new file mode 100644
index 0000000..10191d2
--- /dev/null
+++ b/app/src/main/res/drawable/corner_bg_simple_order_2.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="@color/order_food_list_bak" />
+ <corners android:radius="8dip" />
+ <stroke
+ android:width="1.0dip"
+ android:color="@color/order_food_list_bak" />
+</shape>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/corner_bg_white.xml b/app/src/main/res/drawable/corner_bg_white.xml
new file mode 100644
index 0000000..48324a8
--- /dev/null
+++ b/app/src/main/res/drawable/corner_bg_white.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="@android:color/white" />
+ <corners android:radius="8dip" />
+ <stroke
+ android:width="1.0dip"
+ android:color="@android:color/white" />
+</shape>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/dps_crash_selector.xml b/app/src/main/res/drawable/dps_crash_selector.xml
new file mode 100644
index 0000000..fa50427
--- /dev/null
+++ b/app/src/main/res/drawable/dps_crash_selector.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:drawable="@drawable/corner_bg_dps_crashbtn_focus" android:state_selected="true"/>
+ <item android:drawable="@drawable/corner_bg_dps_crashbtn_focus" android:state_pressed="true"/>
+ <item android:drawable="@drawable/corner_bg_dps_crashbtn_normal"/>
+</selector>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/food_corner_bg.xml b/app/src/main/res/drawable/food_corner_bg.xml
new file mode 100644
index 0000000..5c1aca5
--- /dev/null
+++ b/app/src/main/res/drawable/food_corner_bg.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="#999999" />
+ <corners android:radius="8dip" />
+ <stroke
+ android:width="1.0dip"
+ android:color="#999999" />
+</shape>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/fudan_logo.png b/app/src/main/res/drawable/fudan_logo.png
new file mode 100644
index 0000000..1a53460
--- /dev/null
+++ b/app/src/main/res/drawable/fudan_logo.png
Binary files differ
diff --git a/app/src/main/res/drawable/fudan_logo2.png b/app/src/main/res/drawable/fudan_logo2.png
new file mode 100644
index 0000000..350562b
--- /dev/null
+++ b/app/src/main/res/drawable/fudan_logo2.png
Binary files differ
diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..a0ad202
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="108dp"
+ android:width="108dp"
+ android:viewportHeight="108"
+ android:viewportWidth="108">
+ <path android:fillColor="#008577"
+ android:pathData="M0,0h108v108h-108z"/>
+ <path android:fillColor="#00000000" android:pathData="M9,0L9,108"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M19,0L19,108"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M29,0L29,108"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M39,0L39,108"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M49,0L49,108"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M59,0L59,108"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M69,0L69,108"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M79,0L79,108"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M89,0L89,108"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M99,0L99,108"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,9L108,9"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,19L108,19"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,29L108,29"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,39L108,39"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,49L108,49"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,59L108,59"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,69L108,69"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,79L108,79"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,89L108,89"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M0,99L108,99"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M19,29L89,29"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M19,39L89,39"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M19,49L89,49"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M19,59L89,59"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M19,69L89,69"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M19,79L89,79"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M29,19L29,89"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M39,19L39,89"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M49,19L49,89"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M59,19L59,89"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M69,19L69,89"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+ <path android:fillColor="#00000000" android:pathData="M79,19L79,89"
+ android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+</vector>
diff --git a/app/src/main/res/drawable/item_pressed_selector.xml b/app/src/main/res/drawable/item_pressed_selector.xml
new file mode 100644
index 0000000..d1e814b
--- /dev/null
+++ b/app/src/main/res/drawable/item_pressed_selector.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:drawable="@android:color/darker_gray" android:state_pressed="true"/>
+ <item android:drawable="@android:color/darker_gray" android:state_focused="true"/>
+ <item android:drawable="@android:color/white" android:state_enabled="true"/>
+ <item android:drawable="@android:color/white"/>
+</selector>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/minus_btn_selector.xml b/app/src/main/res/drawable/minus_btn_selector.xml
new file mode 100644
index 0000000..5f5ba45
--- /dev/null
+++ b/app/src/main/res/drawable/minus_btn_selector.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_selected="true" android:drawable="@drawable/minus_click" />
+ <item android:state_pressed="true" android:drawable="@drawable/minus_click" />
+ <item android:drawable="@drawable/corner_bg_order_red" />
+</selector>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/pay_ret_dialog_bg.xml b/app/src/main/res/drawable/pay_ret_dialog_bg.xml
new file mode 100644
index 0000000..705a8f3
--- /dev/null
+++ b/app/src/main/res/drawable/pay_ret_dialog_bg.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<shape android:shape="rectangle"
+ xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="@color/viewfinder_mask" />
+ <corners android:radius="6.0dip" />
+</shape>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/progress_bg.xml b/app/src/main/res/drawable/progress_bg.xml
new file mode 100644
index 0000000..55134ec
--- /dev/null
+++ b/app/src/main/res/drawable/progress_bg.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<rotate xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/loading_white"
+ android:fromDegrees="0"
+ android:interpolator="@android:anim/cycle_interpolator"
+ android:pivotX="50%"
+ android:pivotY="50%"
+ android:toDegrees="1440" />
diff --git a/app/src/main/res/drawable/progress_horizontal.xml b/app/src/main/res/drawable/progress_horizontal.xml
new file mode 100644
index 0000000..8014563
--- /dev/null
+++ b/app/src/main/res/drawable/progress_horizontal.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
+
+<item
+ android:id="@android:id/background"
+ android:drawable="@color/pos_theme_color">
+</item>
+<item android:id="@android:id/secondaryProgress">
+ <scale
+ android:drawable="@color/light_gray"
+ android:scaleWidth="100%" />
+</item>
+<item android:id="@android:id/progress">
+ <scale
+ android:drawable="@color/cl_red"
+ android:scaleWidth="100%" />
+</item>
+
+</layer-list>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/purchase_cardagain.jpg b/app/src/main/res/drawable/purchase_cardagain.jpg
new file mode 100644
index 0000000..ae09d7f
--- /dev/null
+++ b/app/src/main/res/drawable/purchase_cardagain.jpg
Binary files differ
diff --git a/app/src/main/res/drawable/purchase_cardread.jpg b/app/src/main/res/drawable/purchase_cardread.jpg
new file mode 100644
index 0000000..5ab9972
--- /dev/null
+++ b/app/src/main/res/drawable/purchase_cardread.jpg
Binary files differ
diff --git a/app/src/main/res/drawable/purchase_fail.jpg b/app/src/main/res/drawable/purchase_fail.jpg
new file mode 100644
index 0000000..68c4cb9
--- /dev/null
+++ b/app/src/main/res/drawable/purchase_fail.jpg
Binary files differ
diff --git a/app/src/main/res/drawable/purchase_suc.jpg b/app/src/main/res/drawable/purchase_suc.jpg
new file mode 100644
index 0000000..f39ebdb
--- /dev/null
+++ b/app/src/main/res/drawable/purchase_suc.jpg
Binary files differ
diff --git a/app/src/main/res/drawable/qr_none320.png b/app/src/main/res/drawable/qr_none320.png
new file mode 100644
index 0000000..99b9039
--- /dev/null
+++ b/app/src/main/res/drawable/qr_none320.png
Binary files differ
diff --git a/app/src/main/res/drawable/select_bg_keyboard.xml b/app/src/main/res/drawable/select_bg_keyboard.xml
new file mode 100644
index 0000000..83ae4c5
--- /dev/null
+++ b/app/src/main/res/drawable/select_bg_keyboard.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:drawable="@drawable/corner_bg_keyboard_normal" android:state_selected="true"/>
+ <item android:drawable="@drawable/corner_bg_keyboard_normal" android:state_pressed="true"/>
+ <item android:drawable="@drawable/corner_bg_keyboard_focus"/>
+</selector>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/select_ordinary_consume.xml b/app/src/main/res/drawable/select_ordinary_consume.xml
new file mode 100644
index 0000000..e44edf1
--- /dev/null
+++ b/app/src/main/res/drawable/select_ordinary_consume.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:drawable="@drawable/corner_bg_ordinary_consume_focus" android:state_selected="true"/>
+ <item android:drawable="@drawable/corner_bg_ordinary_consume_focus" android:state_pressed="true"/>
+ <item android:drawable="@drawable/corner_bg_ordinary_consume_normal"/>
+</selector>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/shape_image_border.xml b/app/src/main/res/drawable/shape_image_border.xml
new file mode 100644
index 0000000..6d801b9
--- /dev/null
+++ b/app/src/main/res/drawable/shape_image_border.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ <!-- Bottom 2dp Shadow -->
+ <item>
+
+ <shape android:shape="rectangle">
+
+ <solid android:color="#BBB"/>
+
+ <corners android:radius="7dp"/>
+ </shape>
+ </item>
+
+ <!-- White Top color -->
+ <item android:bottom="3px">
+
+ <shape android:shape="rectangle">
+
+ <solid android:color="#FFF"/>
+
+ <corners android:radius="7dp"/>
+
+ <padding
+ android:bottom="5dp"
+ android:left="5dp"
+ android:right="5dp"
+ android:top="5dp"/>
+ </shape>
+ </item>
+</layer-list>
diff --git a/app/src/main/res/drawable/toast_cry.jpg b/app/src/main/res/drawable/toast_cry.jpg
new file mode 100644
index 0000000..6c54f93
--- /dev/null
+++ b/app/src/main/res/drawable/toast_cry.jpg
Binary files differ
diff --git a/app/src/main/res/drawable/toast_doubt.jpg b/app/src/main/res/drawable/toast_doubt.jpg
new file mode 100644
index 0000000..1ed3097
--- /dev/null
+++ b/app/src/main/res/drawable/toast_doubt.jpg
Binary files differ
diff --git a/app/src/main/res/drawable/toast_smile.jpg b/app/src/main/res/drawable/toast_smile.jpg
new file mode 100644
index 0000000..b74ff81
--- /dev/null
+++ b/app/src/main/res/drawable/toast_smile.jpg
Binary files differ
diff --git a/app/src/main/res/drawable/wireless_off.png b/app/src/main/res/drawable/wireless_off.png
new file mode 100644
index 0000000..c9e117e
--- /dev/null
+++ b/app/src/main/res/drawable/wireless_off.png
Binary files differ
diff --git a/app/src/main/res/drawable/wireless_on.png b/app/src/main/res/drawable/wireless_on.png
new file mode 100644
index 0000000..61a9506
--- /dev/null
+++ b/app/src/main/res/drawable/wireless_on.png
Binary files differ
diff --git a/app/src/main/res/layout/activity_cardlib.xml b/app/src/main/res/layout/activity_cardlib.xml
new file mode 100644
index 0000000..f15e962
--- /dev/null
+++ b/app/src/main/res/layout/activity_cardlib.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ style="@style/head_title_out_style">
+
+ <LinearLayout style="@style/head_title_inner_style">
+
+ <TextView
+ style="@style/head_title_text_style"
+ android:text="欢迎使用智能设备" />
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="30dp"
+ android:gravity="center"
+ android:text="加载卡库资源"
+ android:textColor="@color/light_blue2"
+ android:textSize="30sp"
+ android:visibility="visible" />
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="10dp"
+ android:gravity="center"
+ android:text="请耐心等待..."
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="@color/light_blue2"
+ android:textSize="30sp" />
+
+ <ProgressBar
+ android:id="@+id/cardlib_bar"
+ style="?android:attr/progressBarStyleHorizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="10dp"
+ android:layout_marginRight="10dp"
+ android:layout_marginTop="10dp"
+ android:max="100"
+ android:progress="5"
+ android:progressDrawable="@drawable/bar_progress_style" />
+
+ <TextView
+ android:id="@+id/cardlib_result"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="30dp"
+ android:gravity="center"
+ android:text="加载失败:原因"
+ android:textColor="@color/light_blue2"
+ android:textSize="30sp"
+ android:visibility="gone" />
+
+ </LinearLayout>
+
+</LinearLayout>
diff --git a/app/src/main/res/layout/activity_check_mngpwd.xml b/app/src/main/res/layout/activity_check_mngpwd.xml
new file mode 100644
index 0000000..1394d96
--- /dev/null
+++ b/app/src/main/res/layout/activity_check_mngpwd.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ style="@style/head_title_out_style">
+
+ <LinearLayout style="@style/head_title_inner_style">
+
+ <TextView
+ android:id="@+id/title"
+ style="@style/head_title_text_style"
+ android:text="密码界面" />
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="20dp"
+ android:layout_marginTop="10dp"
+ android:text="等待密码校验"
+ android:textColor="@color/light_blue2"
+ android:textSize="30sp" />
+
+ <TextView
+ android:id="@+id/content"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="20dp"
+ android:layout_marginTop="10dp"
+ android:text=""
+ android:textColor="@color/light_blue2"
+ android:textSize="30sp" />
+ </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_communicate.xml b/app/src/main/res/layout/activity_communicate.xml
new file mode 100644
index 0000000..d66e4ca
--- /dev/null
+++ b/app/src/main/res/layout/activity_communicate.xml
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ style="@style/head_title_out_style">
+
+ <LinearLayout style="@style/head_title_inner_style">
+
+ <TextView
+ style="@style/head_title_text_style"
+ android:text="通讯参数设置"/>
+
+ <ScrollView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <LinearLayout style="@style/comm_ll_para_style">
+
+ <TextView
+ style="@style/init_param_name_style"
+ android:text="终端MODE"/>
+
+ <RadioGroup
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <RadioButton
+ android:id="@+id/rb_pay_mode"
+ style="@style/comm_rb_para_style"
+ android:checked="true"
+ android:text="消费模式"/>
+
+ <RadioButton
+ android:id="@+id/rb_deposit_mode"
+ style="@style/comm_rb_para_style"
+ android:text="充值模式"
+ android:visibility="gone"/>
+
+ <RadioButton
+ android:id="@+id/rb_third_pay_mode"
+ style="@style/comm_rb_para_style"
+ android:text="对接消费模式"
+ android:visibility="gone"/>
+
+ <RadioButton
+ android:id="@+id/rb_third_login_mode"
+ style="@style/comm_rb_para_style"
+ android:text="对接签到模式"
+ android:visibility="gone"/>
+
+ <RadioButton
+ android:id="@+id/rb_gate_mode"
+ style="@style/comm_rb_para_style"
+ android:visibility="gone"/>
+ </RadioGroup>
+ </LinearLayout>
+
+ <LinearLayout style="@style/comm_ll_para_style">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="start|center"
+ android:text="设备编号"
+ android:textColor="@color/light_blue2"
+ android:textSize="@dimen/enable_devphyid_font_size"/>
+
+ <TextView
+ android:id="@+id/comm_devphyid"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="start|center"
+ android:inputType="numberDecimal"
+ android:lines="1"
+ android:maxLength="8"
+ android:text="00000000"
+ android:textColor="@color/light_blue2"
+ android:textSize="@dimen/enable_devphyid_font_size"/>
+ </LinearLayout>
+ <!--第一行-->
+ <LinearLayout style="@style/comm_ll_para_style">
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="start|center"
+ android:text="服务器地址"
+ android:textColor="@color/light_blue2"
+ android:textSize="@dimen/enable_devphyid_font_size"/>
+
+ <EditText
+ android:id="@+id/comm_epay_url"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="10dp"
+ android:gravity="start|center"
+ android:text="172.28.201.101"
+ android:textColor="@color/light_blue2"
+ android:textSize="@dimen/enable_devphyid_font_size"/>
+ </LinearLayout>
+
+ <LinearLayout style="@style/comm_ll_para_style">
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="start|center"
+ android:text="服务器标识"
+ android:textColor="@color/light_blue2"
+ android:textSize="@dimen/enable_devphyid_font_size"/>
+
+ <EditText
+ android:id="@+id/comm_epay_uri"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="epayapi"
+ android:textColor="@color/light_blue2"
+ android:textSize="@dimen/enable_devphyid_font_size"/>
+ </LinearLayout>
+ <!--第二行-->
+ <LinearLayout style="@style/comm_ll_para_style">
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="服务器端口"
+ android:textColor="@color/light_blue2"
+ android:textSize="@dimen/enable_devphyid_font_size"/>
+
+ <EditText
+ android:id="@+id/comm_epay_port"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:inputType="numberDecimal"
+ android:lines="1"
+ android:maxLength="5"
+ android:text="9116"
+ android:textColor="@color/light_blue2"
+ android:textSize="@dimen/enable_devphyid_font_size"/>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:padding="10dp"
+ android:weightSum="2">
+
+ <TextView
+ android:id="@+id/btn_cancel"
+ style="@style/param_item_text_btn_style"
+ android:text="取消"/>
+
+ <TextView
+ android:id="@+id/btn_confirm"
+ style="@style/param_item_text_btn_style"
+ android:layout_marginLeft="10dp"
+ android:text="保存"/>
+ </LinearLayout>
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="500dp"/>
+ </LinearLayout>
+ </ScrollView>
+ </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_consume.xml b/app/src/main/res/layout/activity_consume.xml
new file mode 100644
index 0000000..b4565e0
--- /dev/null
+++ b/app/src/main/res/layout/activity_consume.xml
@@ -0,0 +1,437 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@color/light_blue2"
+ android:focusable="true"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="20dp"
+ android:layout_marginTop="20dp"
+ android:layout_marginRight="20dp"
+ android:background="@drawable/corner_bg_white"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="304dp"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="130dp"
+ android:orientation="horizontal"
+ android:padding="@dimen/consume_text_pad_size"
+ android:weightSum="3">
+
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="2"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:layout_width="60dp"
+ android:layout_height="60dp"
+ android:layout_gravity="center"
+ android:scaleType="fitXY"
+ android:src="@mipmap/shop_logo" />
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ android:layout_marginLeft="10dp"
+ android:layout_marginTop="8dp"
+ android:orientation="vertical"
+ android:padding="1dp">
+
+ <TextView
+ android:id="@+id/consume_shopname"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:maxLines="2"
+ android:text=""
+ android:textColor="@color/blue"
+ android:textSize="28sp" />
+
+ <TextView
+ android:id="@+id/consume_time"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="start"
+ android:maxLines="1"
+ android:text=""
+ android:textColor="@color/blue"
+ android:textSize="22sp" />
+ </LinearLayout>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ android:layout_weight="1"
+ android:gravity="right"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:id="@+id/consume_linklogo"
+ android:layout_width="30dp"
+ android:layout_height="30dp"
+ android:scaleType="fitXY"
+ android:src="@drawable/wireless_on" />
+
+ <TextView
+ android:id="@+id/consume_linkstat"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:maxLines="1"
+ android:text="已联网"
+ android:textColor="@color/blue"
+ android:textSize="22sp" />
+ </LinearLayout>
+ </LinearLayout>
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:layout_marginLeft="10dp"
+ android:layout_marginRight="10dp"
+ android:background="@color/black" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal"
+ android:padding="@dimen/consume_text_pad_size">
+
+ <TextView
+ android:id="@+id/tv_consume_hint"
+ android:layout_width="300dp"
+ android:layout_height="match_parent"
+ android:gravity="start|center"
+ android:text="消费金额"
+ android:textColor="@color/blue"
+ android:textSize="50sp"
+ android:textStyle="bold" />
+
+ <TextView
+ android:id="@+id/consume_amt"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:maxLines="1"
+ android:text="0"
+ android:textColor="@color/orange1"
+ android:textSize="65sp"
+ android:textStyle="bold" />
+ </LinearLayout>
+ </LinearLayout>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="20dp"
+ android:layout_marginTop="10dp"
+ android:layout_marginRight="20dp"
+ android:background="@drawable/corner_bg_ordinary_consume_green"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:padding="10dp">
+
+ <ImageView
+ android:layout_width="40dp"
+ android:layout_height="40dp"
+ android:scaleType="fitXY"
+ android:src="@mipmap/show_card_info" />
+
+ <TextView
+ android:id="@+id/tv_card_info"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="校园卡信息"
+ android:textColor="@color/blue"
+ android:textSize="@dimen/consume_text_size2" />
+ </LinearLayout>
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:layout_marginLeft="10dp"
+ android:layout_marginTop="5dp"
+ android:layout_marginRight="10dp"
+ android:layout_marginBottom="5dp"
+ android:background="@color/black" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginLeft="10dp"
+ android:layout_marginTop="5dp"
+ android:orientation="vertical">
+
+ <ImageView
+ android:layout_width="80dp"
+ android:layout_height="80dp"
+ android:layout_gravity="center"
+ android:scaleType="fitXY"
+ android:src="@mipmap/default_photo"
+ android:visibility="gone" />
+
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="@dimen/consume_text_pad_size1"
+ android:text="如需查询余额,请刷卡!"
+ android:textColor="@color/blue"
+ android:textSize="@dimen/consume_text_size2" />
+
+ <LinearLayout style="@style/consume_wait_account_ll_style">
+
+ <TextView
+ style="@style/consume_wait_account_paraname_style"
+ android:text="姓 名: " />
+
+ <TextView
+ android:id="@+id/consume_custname"
+ style="@style/consume_wait_account_paraval_style" />
+ </LinearLayout>
+
+ <LinearLayout style="@style/consume_wait_account_ll_style">
+
+ <TextView
+ style="@style/consume_wait_account_paraname_style"
+ android:text="学工号: " />
+
+ <TextView
+ android:id="@+id/consume_stuempno"
+ style="@style/consume_wait_account_paraval_style" />
+ </LinearLayout>
+
+ <LinearLayout style="@style/consume_wait_account_ll_style">
+
+ <TextView
+ style="@style/consume_wait_account_paraname_style"
+ android:text="余 额: " />
+
+ <TextView
+ android:id="@+id/consume_balance"
+ style="@style/consume_wait_account_paraval_style" />
+ </LinearLayout>
+
+ <LinearLayout style="@style/consume_wait_account_ll_style">
+
+ <TextView
+ style="@style/consume_wait_account_paraname_style"
+ android:text="卡状态: " />
+
+ <TextView
+ android:id="@+id/consume_cardstatus"
+ style="@style/consume_wait_account_paraval_style" />
+ </LinearLayout>
+ </LinearLayout>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginLeft="20dp"
+ android:layout_marginTop="10dp"
+ android:layout_marginRight="20dp"
+ android:layout_marginBottom="20dp"
+ android:background="@drawable/corner_bg_ordinary_consume_green"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:padding="@dimen/consume_text_pad_size1">
+
+ <ImageView
+ android:layout_width="40dp"
+ android:layout_height="40dp"
+ android:scaleType="fitXY"
+ android:src="@mipmap/bill_lastdtl" />
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="最近一笔"
+ android:textColor="@color/blue"
+ android:textSize="@dimen/consume_text_size2" />
+ </LinearLayout>
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:layout_marginLeft="10dp"
+ android:layout_marginTop="10dp"
+ android:layout_marginRight="10dp"
+ android:layout_marginBottom="5dp"
+ android:background="@color/black" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:paddingLeft="10dp"
+ android:paddingTop="10dp">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:text="支付结果: "
+ android:textColor="@color/black"
+ android:textSize="@dimen/consume_text_size2" />
+
+ <TextView
+ android:id="@+id/consume_last_result"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:maxLines="1"
+ android:text=""
+ android:textColor="@color/blue"
+ android:textSize="@dimen/consume_text_size2"
+ android:textStyle="bold" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:id="@+id/ll_consume_last_failreason"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:paddingLeft="10dp"
+ android:paddingTop="5dp"
+ android:visibility="gone">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:text="失败提示: "
+ android:textColor="@color/cl_red"
+ android:textSize="@dimen/consume_text_size2" />
+
+ <TextView
+ android:id="@+id/consume_last_failreason"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:maxLines="1"
+ android:text=""
+ android:textColor="@color/cl_red"
+ android:textSize="@dimen/consume_text_size2"
+ android:textStyle="bold" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:id="@+id/ll_consume_last_payamt"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:paddingLeft="10dp"
+ android:paddingTop="5dp">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:text="支付金额: "
+ android:textColor="@color/black"
+ android:textSize="@dimen/consume_text_size2" />
+
+ <TextView
+ android:id="@+id/consume_last_payamt"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:maxLines="1"
+ android:text=""
+ android:textColor="@color/blue"
+ android:textSize="@dimen/consume_text_size2"
+ android:textStyle="bold" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:paddingLeft="10dp"
+ android:paddingTop="5dp">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:text="支付方式: "
+ android:textColor="@color/black"
+ android:textSize="@dimen/consume_text_size2" />
+
+ <TextView
+ android:id="@+id/consume_last_payway"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:maxLines="1"
+ android:text=""
+ android:textColor="@color/blue"
+ android:textSize="@dimen/consume_text_size2"
+ android:textStyle="bold" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:paddingLeft="10dp"
+ android:paddingTop="5dp">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:text="支付日期: "
+ android:textColor="@color/black"
+ android:textSize="@dimen/consume_text_size2" />
+
+ <TextView
+ android:id="@+id/consume_last_payday"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:maxLines="1"
+ android:text=""
+ android:textColor="@color/blue"
+ android:textSize="@dimen/consume_text_size2"
+ android:textStyle="bold" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:paddingLeft="10dp"
+ android:paddingTop="5dp">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:text="支付时间: "
+ android:textColor="@color/black"
+ android:textSize="@dimen/consume_text_size2" />
+
+ <TextView
+ android:id="@+id/consume_last_paytime"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:maxLines="1"
+ android:text=""
+ android:textColor="@color/blue"
+ android:textSize="@dimen/consume_text_size2"
+ android:textStyle="bold" />
+ </LinearLayout>
+ </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_consume_mode.xml b/app/src/main/res/layout/activity_consume_mode.xml
new file mode 100644
index 0000000..99e494f
--- /dev/null
+++ b/app/src/main/res/layout/activity_consume_mode.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ style="@style/head_title_out_style">
+
+ <LinearLayout style="@style/head_title_inner_style">
+
+ <TextView
+ style="@style/head_title_text_style"
+ android:text="消费模式" />
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:padding="10dp"
+ android:text="0-普通消费\n非0定额消费\n单位(分)"
+ android:textColor="@color/light_blue2"
+ android:textSize="20sp" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="10dp"
+ android:text="金额: "
+ android:textColor="@color/light_blue2"
+ android:textSize="30sp" />
+
+ <TextView
+ android:id="@+id/tv_consume_mode_payamt"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:maxLength="6"
+ android:padding="10dp"
+ android:text="0"
+ android:textColor="@color/light_blue2"
+ android:textSize="30sp" />
+ </LinearLayout>
+
+ </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_control.xml b/app/src/main/res/layout/activity_control.xml
new file mode 100644
index 0000000..e1168df
--- /dev/null
+++ b/app/src/main/res/layout/activity_control.xml
@@ -0,0 +1,84 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ style="@style/head_title_out_style">
+
+ <LinearLayout style="@style/head_title_inner_style">
+ <TextView
+ style="@style/head_title_text_style"
+ android:text="本地参数设置"/>
+ <ScrollView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:scrollbars="none">
+
+ <LinearLayout android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <LinearLayout style="@style/control_item_ll_style">
+
+ <TextView
+ style="@style/init_param_name_style"
+ android:text="脱机天数判断"/>
+
+ <RadioGroup
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <RadioButton
+ android:id="@+id/rb_offline_enable"
+ style="@style/comm_rb_para_style"
+ android:checked="true"
+ android:text="开启"/>
+
+ <RadioButton
+ android:id="@+id/rb_offline_disable"
+ style="@style/comm_rb_para_style"
+ android:text="关闭"/>
+ </RadioGroup>
+ </LinearLayout>
+
+ <LinearLayout style="@style/control_item_ll_style">
+
+ <TextView
+ style="@style/init_param_name_style"
+ android:text="调试模式"/>
+
+ <RadioGroup
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <RadioButton
+ android:id="@+id/rb_debug_enable"
+ style="@style/comm_rb_para_style"
+ android:text="开启"/>
+
+ <RadioButton
+ android:id="@+id/rb_debug_disable"
+ style="@style/comm_rb_para_style"
+ android:checked="true"
+ android:text="关闭"/>
+ </RadioGroup>
+
+ </LinearLayout>
+ </LinearLayout>
+ </ScrollView>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="20dp"
+ android:orientation="horizontal"
+ android:weightSum="2">
+
+ <TextView
+ android:id="@+id/btn_cancel"
+ style="@style/control_text_btn_style"
+ android:text="取消"/>
+
+ <TextView
+ android:id="@+id/btn_save"
+ style="@style/control_text_btn_style"
+ android:text="保存"/>
+ </LinearLayout>
+ </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_init.xml b/app/src/main/res/layout/activity_init.xml
new file mode 100644
index 0000000..24c9d45
--- /dev/null
+++ b/app/src/main/res/layout/activity_init.xml
@@ -0,0 +1,160 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:background="@color/light_blue2"
+ tools:context="com.supwisdom.activities.init.InitActivity">
+ <!--终端编号输入界面-->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_margin="20dp"
+ android:background="@drawable/corner_bg_white"
+ android:gravity="center_horizontal"
+ android:orientation="vertical">
+ <!--标题-->
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="10dp"
+ android:gravity="center"
+ android:text="请填写以下信息"
+ android:textColor="@color/light_blue2"
+ android:textSize="@dimen/enable_title_text_size"/>
+
+ <ScrollView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scrollbars="none">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:padding="10dp">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:weightSum="2">
+
+ <Button
+ android:id="@+id/tv_nsd_query"
+ style="@style/init_param_title_btn_name_style"
+ android:text="动态参数获取"/>
+
+ <Button
+ android:id="@+id/tv_settings"
+ style="@style/init_param_title_btn_name_style"
+ android:text="进入设置界面"/>
+ </LinearLayout>
+
+ <TextView
+ android:id="@+id/tv_nsd_result"
+ style="@style/init_param_name_style"/>
+
+ <TextView
+ style="@style/init_param_name_style"
+ android:text="终端MODE"/>
+
+ <RadioGroup
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <RadioButton
+ android:id="@+id/rb_pay_mode"
+ style="@style/init_param_mode_style"
+ android:checked="true"
+ android:text="消费模式"/>
+
+ <RadioButton
+ android:id="@+id/rb_deposit_mode"
+ style="@style/init_param_mode_style"
+ android:visibility="gone"
+ android:text="充值模式"/>
+
+ <RadioButton
+ android:id="@+id/rb_third_pay_mode"
+ style="@style/init_param_mode_style"
+ android:visibility="gone"
+ android:text="对接消费模式"/>
+
+ <RadioButton
+ android:id="@+id/rb_third_login_mode"
+ style="@style/init_param_mode_style"
+ android:visibility="gone"
+ android:text="对接签到模式"/>
+
+ <RadioButton
+ android:id="@+id/rb_gate_mode"
+ style="@style/init_param_mode_style"
+ android:visibility="gone"
+ android:text="闸机(入)模式(点击切换)"/>
+ </RadioGroup>
+
+ <TextView
+ style="@style/init_param_name_style"
+ android:text="终端物理ID"/>
+
+ <EditText
+ android:id="@+id/tv_devphyid"
+ style="@style/init_param_name_style"
+ android:inputType="numberDecimal"
+ android:maxLength="8"
+ android:text="20000001"/>
+
+ <TextView
+ style="@style/init_param_name_style"
+ android:text="服务器IP"/>
+
+ <EditText
+ android:id="@+id/tv_server_ip"
+ style="@style/init_param_name_style"
+ android:text="172.28.201.101"/>
+
+ <TextView
+ style="@style/init_param_name_style"
+ android:text="服务器URI"/>
+
+ <EditText
+ android:id="@+id/tv_uri_root"
+ style="@style/init_param_name_style"
+ android:maxLines="1"
+ android:text="epayapi"/>
+
+
+ <TextView
+ style="@style/init_param_name_style"
+ android:text="服务器PORT"/>
+
+ <EditText
+ android:id="@+id/tv_server_port"
+ style="@style/init_param_name_style"
+ android:inputType="numberDecimal"
+ android:maxLength="5"
+ android:maxLines="1"
+ android:text="9100"/>
+
+ <TextView
+ android:id="@+id/btn_save"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_marginTop="20dp"
+ android:background="@drawable/select_bg_keyboard"
+ android:paddingLeft="20dp"
+ android:paddingTop="10dp"
+ android:paddingRight="20dp"
+ android:paddingBottom="10dp"
+ android:text="保 存"
+ android:textColor="@color/light_blue2"
+ android:textSize="35sp"/>
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="500dp"/>
+ </LinearLayout>
+ </ScrollView>
+ </LinearLayout>
+</LinearLayout>
diff --git a/app/src/main/res/layout/activity_load.xml b/app/src/main/res/layout/activity_load.xml
new file mode 100644
index 0000000..b6d9c86
--- /dev/null
+++ b/app/src/main/res/layout/activity_load.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:background="@color/light_blue2">
+
+ <LinearLayout
+ android:id="@+id/ll_enable_step"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_margin="20dp"
+ android:background="@drawable/corner_bg_white"
+ android:gravity="center_horizontal"
+ android:orientation="vertical">
+ <!--标题-->
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="10dp"
+ android:gravity="center"
+ android:text="正在加载设备参数"
+ android:textColor="@color/light_blue2"
+ android:textSize="@dimen/enable_title_text_size"/>
+ <!--中间内容-->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="400dp"
+ android:layout_gravity="center_horizontal"
+ android:layout_marginTop="20dp"
+ android:orientation="vertical"
+ android:padding="10dp">
+
+ <TextView
+ android:id="@+id/tv_load_pro"
+ style="@style/load_info_text_style"
+ android:text=" "/>
+ </LinearLayout>
+ <!--底下俩按钮-->
+ <TextView
+ android:id="@+id/btn_back"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="10dp"
+ android:background="@drawable/select_bg_keyboard"
+ android:paddingLeft="20dp"
+ android:paddingTop="10dp"
+ android:paddingRight="20dp"
+ android:paddingBottom="10dp"
+ android:text="返 回"
+ android:textColor="@color/light_blue2"
+ android:textSize="30sp"/>
+ </LinearLayout>
+</LinearLayout>
diff --git a/app/src/main/res/layout/activity_manage.xml b/app/src/main/res/layout/activity_manage.xml
new file mode 100644
index 0000000..7537388
--- /dev/null
+++ b/app/src/main/res/layout/activity_manage.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ style="@style/head_title_out_style">
+
+ <LinearLayout style="@style/head_title_inner_style">
+ <TextView
+ style="@style/head_title_text_style"
+ android:text="维护管理界面"/>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginLeft="10dp"
+ android:orientation="vertical"
+ android:padding="10dp">
+
+ <TextView
+ style="@style/menu_item_text_style"
+ android:text="@string/consume_menu_shop_passwd"/>
+
+ <TextView
+ style="@style/menu_item_text_style"
+ android:text="@string/consume_menu_comm_set"/>
+
+ <TextView
+ style="@style/menu_item_text_style"
+ android:text="@string/consume_menu_unconfirm_transdtl"/>
+
+ <TextView
+ style="@style/menu_item_text_style"
+ android:text="@string/consume_menu_out_dtl"/>
+
+ <TextView
+ style="@style/menu_item_text_style"
+ android:text="@string/consume_menu_upgrade"/>
+
+ <TextView
+ style="@style/menu_item_text_style"
+ android:text="@string/consume_menu_app_exit"/>
+
+ <TextView
+ style="@style/menu_item_text_style"
+ android:text="@string/consume_menu_setting"/>
+
+ <TextView
+ style="@style/menu_item_text_style"
+ android:text="@string/consume_menu_clear_blklist"/>
+
+ <TextView
+ style="@style/menu_item_text_style"
+ android:text="@string/consume_menu_control_set"/>
+ </LinearLayout>
+ </LinearLayout>
+</LinearLayout>
diff --git a/app/src/main/res/layout/activity_menu.xml b/app/src/main/res/layout/activity_menu.xml
new file mode 100644
index 0000000..e938845
--- /dev/null
+++ b/app/src/main/res/layout/activity_menu.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@color/light_blue2"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_margin="20dp"
+ android:background="@drawable/corner_bg_white"
+ android:orientation="vertical">
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="10dp"
+ android:gravity="center"
+ android:text="管理界面"
+ android:textColor="@color/light_blue2"
+ android:textSize="45sp" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginLeft="10dp"
+ android:orientation="vertical"
+ android:padding="10dp">
+
+ <TextView
+ style="@style/menu_item_text_style"
+ android:text="@string/consume_menu_revenue" />
+
+ <TextView
+ style="@style/menu_item_text_style"
+ android:text="@string/consume_menu_transdtl_upload" />
+
+ <TextView
+ style="@style/menu_item_text_style"
+ android:text="@string/consume_menu_link_check" />
+
+ <TextView
+ style="@style/menu_item_text_style"
+ android:text="@string/consume_menu_auth" />
+
+ <TextView
+ style="@style/menu_item_text_style"
+ android:text="@string/consume_menu_syspara_query" />
+
+ <TextView
+ style="@style/menu_item_text_style"
+ android:text="@string/consume_menu_manage" />
+
+ <TextView
+ style="@style/menu_item_text_style"
+ android:text="@string/consume_menu_shop_password_set" />
+
+ <TextView
+ style="@style/menu_item_text_style"
+ android:text="@string/consume_menu_consume_mode" />
+
+ <TextView
+ android:id="@+id/tv_reverse"
+ style="@style/menu_item_text_style"
+ android:text="@string/consume_menu_reverse" />
+ </LinearLayout>
+ </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_password.xml b/app/src/main/res/layout/activity_password.xml
new file mode 100644
index 0000000..f1943ea
--- /dev/null
+++ b/app/src/main/res/layout/activity_password.xml
@@ -0,0 +1,26 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@color/light_blue2"
+ android:orientation="vertical">
+ <!--上半部分-->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_margin="20dp"
+ android:background="@drawable/corner_bg_white"
+ android:orientation="vertical">
+ <!--提示文字-->
+ <TextView
+ android:id="@+id/passwd_title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="10dp"
+ android:gravity="center"
+ android:text="商户密码修改"
+ android:textColor="@color/light_blue2"
+ android:textSize="@dimen/password_hint_size" />
+
+ </LinearLayout>
+</LinearLayout>
+
diff --git a/app/src/main/res/layout/activity_revenue.xml b/app/src/main/res/layout/activity_revenue.xml
new file mode 100644
index 0000000..45541ba
--- /dev/null
+++ b/app/src/main/res/layout/activity_revenue.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@color/light_blue2"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_margin="10dp"
+ android:background="@drawable/corner_bg_white"
+ android:orientation="vertical">
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:padding="20dp"
+ android:text="营业额查询"
+ android:textColor="@color/light_blue2"
+ android:textSize="50sp" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="10dp"
+ android:orientation="horizontal"
+ android:padding="10dp">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="查询日期: "
+ android:textColor="@color/light_blue2"
+ android:textSize="30sp" />
+
+ <TextView
+ android:id="@+id/revenue_date"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="20180818"
+ android:textColor="@color/light_blue2"
+ android:textSize="30sp" />
+ </LinearLayout>
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="10dp"
+ android:padding="10dp"
+ android:text="查询结果: "
+ android:textColor="@color/light_blue2"
+ android:textSize="30sp" />
+
+ <TextView
+ android:id="@+id/revenue_content"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="10dp"
+ android:padding="10dp"
+ android:text=""
+ android:textColor="@color/light_blue2"
+ android:textSize="30sp" />
+ </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml
new file mode 100644
index 0000000..c89c3e3
--- /dev/null
+++ b/app/src/main/res/layout/activity_splash.xml
@@ -0,0 +1,48 @@
+<!--
+android:gravity是对元素本身说的,元素本身的文本显示在什么地方靠着换个属性设置,不过不设置默认是在左侧的。
+android:layout_gravity是相对与它的父元素说的,说明元素显示在父元素的什么位置
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/LinearLayout01"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:background="@color/light_blue2"
+ android:orientation="vertical">
+ <!--
+ android:scaleType是控制图片如何resized/moved来匹对ImageView的size
+ CENTER_INSIDE / centerInside 将图片的内容完整居中显示,通过按比例缩小或原来的size使得图片长/宽等于或小于View的长/宽
+ -->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_margin="20dp"
+ android:background="@drawable/corner_bg_white"
+ android:gravity="center|center"
+ android:orientation="vertical">
+
+ <ImageView
+ android:id="@+id/wordpress_logo"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:scaleType="centerInside"
+ android:src="@drawable/app_logo"></ImageView>
+ <!--
+ android:typeface 字体风格
+ -->
+ <TextView
+ android:id="@+id/versionNumber"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="20dip"
+ android:gravity="bottom"
+ android:shadowColor="#FFFFFF"
+ android:shadowDx="0"
+ android:shadowDy="2"
+ android:shadowRadius="1"
+ android:text="0.0.0"
+ android:textColor="@color/pos_theme_color"
+ android:textSize="@dimen/main_caption_size"
+ android:typeface="serif" />
+ </LinearLayout>
+</LinearLayout>
diff --git a/app/src/main/res/layout/activity_syspara.xml b/app/src/main/res/layout/activity_syspara.xml
new file mode 100644
index 0000000..c2f781a
--- /dev/null
+++ b/app/src/main/res/layout/activity_syspara.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@color/light_blue2"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_margin="10dp"
+ android:background="@drawable/corner_bg_white"
+ android:orientation="vertical">
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="10dp"
+ android:gravity="center"
+ android:text="参数查询"
+ android:textColor="@color/light_blue2"
+ android:textSize="50sp" />
+
+ <ListView
+ android:id="@+id/lv_param"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:divider="@null"
+ android:dividerHeight="2dp" />
+ </LinearLayout>
+</LinearLayout>
diff --git a/app/src/main/res/layout/activity_transdtl.xml b/app/src/main/res/layout/activity_transdtl.xml
new file mode 100644
index 0000000..0c44701
--- /dev/null
+++ b/app/src/main/res/layout/activity_transdtl.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@color/light_blue2"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_margin="10dp"
+ android:background="@drawable/corner_bg_white"
+ android:orientation="vertical">
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:padding="20dp"
+ android:text="流水查询"
+ android:textColor="@color/light_blue2"
+ android:textSize="50sp" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="10dp"
+ android:orientation="horizontal"
+ android:padding="10dp">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="查询记录: "
+ android:textColor="@color/light_blue2"
+ android:textSize="30sp" />
+
+ <TextView
+ android:id="@+id/transdtl_seqno"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text=""
+ android:textColor="@color/light_blue2"
+ android:textSize="30sp" />
+ </LinearLayout>
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="10dp"
+ android:padding="10dp"
+ android:text="查询结果: "
+ android:textColor="@color/light_blue2"
+ android:textSize="30sp" />
+
+ <TextView
+ android:id="@+id/transdtl_content"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="10dp"
+ android:padding="10dp"
+ android:text=""
+ android:textColor="@color/light_blue2"
+ android:textSize="30sp" />
+ </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_unregister.xml b/app/src/main/res/layout/activity_unregister.xml
new file mode 100644
index 0000000..5bcd6cb
--- /dev/null
+++ b/app/src/main/res/layout/activity_unregister.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:background="@color/light_blue2">
+
+ <LinearLayout
+ android:id="@+id/ll_enable_step"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_margin="20dp"
+ android:background="@drawable/corner_bg_white"
+ android:gravity="center_horizontal"
+ android:orientation="vertical">
+ <!--标题-->
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="10dp"
+ android:gravity="center"
+ android:text="设备未注册"
+ android:textColor="@color/light_blue2"
+ android:textSize="@dimen/enable_title_text_size" />
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="10dp"
+ android:padding="10dp"
+ android:text="说明: 设备参数配置已保存,后续只需签到认证成功即可使用"
+ android:textColor="@color/light_blue2"
+ android:textSize="30sp" />
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="10dp"
+ android:padding="10dp"
+ android:text="设备注册失败信息:"
+ android:textColor="@color/light_blue2"
+ android:textSize="30sp" />
+
+ <TextView
+ android:id="@+id/tv_errmsg"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:padding="10dp"
+ android:textColor="@color/cl_red"
+ android:textSize="30sp" />
+
+ <TextView
+ android:id="@+id/tv_back"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="10dp"
+ android:background="@drawable/select_bg_keyboard"
+ android:paddingBottom="10dp"
+ android:paddingLeft="20dp"
+ android:paddingRight="20dp"
+ android:paddingTop="10dp"
+ android:text="返 回"
+ android:textColor="@color/light_blue2"
+ android:textSize="30sp" />
+ </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_upgrade.xml b/app/src/main/res/layout/activity_upgrade.xml
new file mode 100644
index 0000000..f4e1fa0
--- /dev/null
+++ b/app/src/main/res/layout/activity_upgrade.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@color/light_blue2"
+ android:orientation="vertical">
+
+ <ScrollView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_margin="20dp"
+ android:background="@drawable/corner_bg_white"
+ android:fillViewport="true"
+ android:scrollbars="none">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="10dp"
+ android:gravity="center"
+ android:text="软件在线升级"
+ android:textColor="@color/light_blue2"
+ android:textSize="30sp"/>
+ <TableLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <TableRow>
+
+ <TextView
+ style="@style/upgrade_text_value_style"
+ android:text="结\u3000\u3000果:"/>
+
+ <TextView
+ android:id="@+id/tv_result"
+ style="@style/upgrade_text_value_style"/>
+ </TableRow>
+
+ <TableRow android:layout_marginTop="15dp">
+
+ <TextView
+ style="@style/upgrade_text_value_style"
+ android:text="升级地址:"/>
+
+ <TextView
+ android:id="@+id/tv_server_url"
+ style="@style/upgrade_text_value_style"/>
+ </TableRow>
+
+ <TableRow android:layout_marginTop="15dp">
+
+ <TextView
+ style="@style/upgrade_text_value_style"
+ android:text="当前版本:"/>
+
+ <TextView
+ android:id="@+id/tv_old_version"
+ style="@style/upgrade_text_value_style"/>
+ </TableRow>
+
+ <TableRow android:layout_marginTop="15dp">
+
+ <TextView
+ style="@style/upgrade_text_value_style"
+ android:text="升级版本:"/>
+
+ <TextView
+ android:id="@+id/tv_pos_version"
+ style="@style/upgrade_text_value_style"/>
+ </TableRow>
+
+ <TableRow android:layout_marginTop="15dp">
+
+ <TextView
+ style="@style/upgrade_text_value_style"
+ android:text="升级进度:"/>
+
+ <TextView
+ android:id="@+id/tv_upgrade_msg"
+ style="@style/upgrade_text_value_style"/>
+ </TableRow>
+ </TableLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="30dp"
+ android:gravity="center_vertical"
+ android:orientation="horizontal">
+
+ <Button
+ android:id="@+id/tv_upgrade"
+ style="@style/upgrade_text_value_style"
+ android:layout_marginStart="50dp"
+ android:layout_marginEnd="50dp"
+ android:text="升级"/>
+
+ </LinearLayout>
+ </LinearLayout>
+ </ScrollView>
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/dialog_init_nsd_config.xml b/app/src/main/res/layout/dialog_init_nsd_config.xml
new file mode 100644
index 0000000..301e484
--- /dev/null
+++ b/app/src/main/res/layout/dialog_init_nsd_config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="400dp"
+ android:layout_height="500dp"
+ android:layout_gravity="center"
+ android:background="@drawable/corner_bg_white"
+ android:orientation="vertical">
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="10dp"
+ android:gravity="center"
+ android:text="参数配置列表"
+ android:textColor="@color/light_blue2"
+ android:textSize="35sp"
+ android:textStyle="bold" />
+
+ <android.support.v7.widget.RecyclerView
+ android:id="@+id/rv_config_list"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginTop="10dp"
+ android:orientation="vertical" />
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/dialog_password.xml b/app/src/main/res/layout/dialog_password.xml
new file mode 100644
index 0000000..7b62bbd
--- /dev/null
+++ b/app/src/main/res/layout/dialog_password.xml
@@ -0,0 +1,281 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout
+ android:id="@+id/ll_float_password"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="@drawable/order_btn_purchase"
+ android:orientation="vertical">
+ <!--上半部分-->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:orientation="vertical">
+ <!--提示文字-->
+ <TextView
+ android:id="@+id/tv_float_password_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/float_password_left_word_margin_top"
+ android:text="请输入卡密码"
+ android:textColor="@color/password_hint"
+ android:textSize="@dimen/float_password_hint_size"
+ android:textStyle="bold"/>
+ <!--密码输入框-->
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/float_password_left_obj_gap"
+ android:orientation="horizontal">
+ <!--密码1-->
+ <RelativeLayout
+ android:layout_width="@dimen/float_password_pwd_size"
+ android:layout_height="@dimen/float_password_pwd_size">
+
+ <ImageView
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:background="@drawable/password_pwd_frame"/>
+
+ <ImageView
+ android:id="@+id/float_password_img1"
+ android:layout_width="20dp"
+ android:layout_height="20dp"
+ android:layout_margin="26dp"
+ android:layout_marginTop="26dp"
+ android:scaleType="fitXY"
+ android:src="@drawable/purchase_cardread"/>
+ </RelativeLayout>
+ <!--密码2-->
+ <RelativeLayout
+ android:layout_width="@dimen/float_password_pwd_size"
+ android:layout_height="@dimen/float_password_pwd_size"
+ android:layout_marginLeft="@dimen/float_password_left_obj_gap">
+
+ <ImageView
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:background="@drawable/password_pwd_frame"/>
+
+ <ImageView
+ android:id="@+id/float_password_img2"
+ android:layout_width="20dp"
+ android:layout_height="20dp"
+ android:layout_margin="26dp"
+ android:layout_marginTop="26dp"
+ android:scaleType="fitXY"
+ android:src="@drawable/purchase_cardread"/>
+ </RelativeLayout>
+ <!--密码3-->
+ <RelativeLayout
+ android:layout_width="@dimen/float_password_pwd_size"
+ android:layout_height="@dimen/float_password_pwd_size"
+ android:layout_marginLeft="@dimen/float_password_left_obj_gap">
+
+ <ImageView
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:background="@drawable/password_pwd_frame"/>
+
+ <ImageView
+ android:id="@+id/float_password_img3"
+ android:layout_width="20dp"
+ android:layout_height="20dp"
+ android:layout_margin="26dp"
+ android:layout_marginTop="26dp"
+ android:scaleType="fitXY"
+ android:src="@drawable/purchase_cardread"/>
+ </RelativeLayout>
+ <!--密码4-->
+ <RelativeLayout
+ android:layout_width="@dimen/float_password_pwd_size"
+ android:layout_height="@dimen/float_password_pwd_size"
+ android:layout_marginLeft="@dimen/float_password_left_obj_gap">
+
+ <ImageView
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:background="@drawable/password_pwd_frame"/>
+
+ <ImageView
+ android:id="@+id/float_password_img4"
+ android:layout_width="20dp"
+ android:layout_height="20dp"
+ android:layout_margin="26dp"
+ android:layout_marginTop="26dp"
+ android:scaleType="fitXY"
+ android:src="@drawable/purchase_cardread"/>
+ </RelativeLayout>
+ <!--密码5-->
+ <RelativeLayout
+ android:layout_width="@dimen/float_password_pwd_size"
+ android:layout_height="@dimen/float_password_pwd_size"
+ android:layout_marginLeft="@dimen/float_password_left_obj_gap">
+
+ <ImageView
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:background="@drawable/password_pwd_frame"/>
+
+ <ImageView
+ android:id="@+id/float_password_img5"
+ android:layout_width="20dp"
+ android:layout_height="20dp"
+ android:layout_margin="26dp"
+ android:layout_marginTop="26dp"
+ android:scaleType="fitXY"
+ android:src="@drawable/purchase_cardread"/>
+ </RelativeLayout>
+ <!--密码6-->
+ <RelativeLayout
+ android:layout_width="@dimen/float_password_pwd_size"
+ android:layout_height="@dimen/float_password_pwd_size"
+ android:layout_marginLeft="@dimen/float_password_left_obj_gap">
+
+ <ImageView
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:background="@drawable/password_pwd_frame"/>
+
+ <ImageView
+ android:id="@+id/float_password_img6"
+ android:layout_width="20dp"
+ android:layout_height="20dp"
+ android:layout_margin="26dp"
+ android:layout_marginTop="26dp"
+ android:scaleType="fitXY"
+ android:src="@drawable/purchase_cardread"/>
+ </RelativeLayout>
+ </LinearLayout>
+ </LinearLayout>
+
+ <!--下半部分-->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="10dp"
+ android:layout_marginTop="@dimen/float_password_right_margin_top"
+ android:gravity="center_horizontal"
+ android:orientation="vertical">
+ <!--第一行按键-->
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/float_password_btn_size"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:id="@+id/float_password_btn1"
+ android:layout_width="@dimen/float_password_btn_size"
+ android:layout_height="@dimen/float_password_btn_size"
+ android:src="@drawable/pass_one_normal"/>
+
+ <ImageView
+ android:id="@+id/float_password_btn2"
+ android:layout_width="@dimen/float_password_btn_size"
+ android:layout_height="@dimen/float_password_btn_size"
+ android:layout_marginLeft="@dimen/float_password_right_btn_margin"
+ android:src="@drawable/pass_two_normal"/>
+
+ <ImageView
+ android:id="@+id/float_password_btn3"
+ android:layout_width="@dimen/float_password_btn_size"
+ android:layout_height="@dimen/float_password_btn_size"
+ android:layout_marginLeft="@dimen/float_password_right_btn_margin"
+ android:src="@drawable/pass_three_normal"/>
+ </LinearLayout>
+ <!--第二行按钮-->
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/float_password_btn_size"
+ android:layout_marginTop="@dimen/float_password_right_btn_margin"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:id="@+id/float_password_btn4"
+ android:layout_width="@dimen/float_password_btn_size"
+ android:layout_height="@dimen/float_password_btn_size"
+ android:src="@drawable/pass_four_normal"/>
+
+ <ImageView
+ android:id="@+id/float_password_btn5"
+ android:layout_width="@dimen/float_password_btn_size"
+ android:layout_height="@dimen/float_password_btn_size"
+ android:layout_marginLeft="@dimen/float_password_right_btn_margin"
+ android:src="@drawable/pass_five_normal"/>
+
+ <ImageView
+ android:id="@+id/float_password_btn6"
+ android:layout_width="@dimen/float_password_btn_size"
+ android:layout_height="@dimen/float_password_btn_size"
+ android:layout_marginLeft="@dimen/float_password_right_btn_margin"
+ android:src="@drawable/pass_six_normal"/>
+ </LinearLayout>
+ <!--第三行按钮-->
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/float_password_btn_size"
+ android:layout_marginTop="@dimen/float_password_right_btn_margin"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:id="@+id/float_password_btn7"
+ android:layout_width="@dimen/float_password_btn_size"
+ android:layout_height="@dimen/float_password_btn_size"
+ android:src="@drawable/pass_seven_normal"/>
+
+ <ImageView
+ android:id="@+id/float_password_btn8"
+ android:layout_width="@dimen/float_password_btn_size"
+ android:layout_height="@dimen/float_password_btn_size"
+ android:layout_marginLeft="@dimen/float_password_right_btn_margin"
+ android:src="@drawable/pass_eight_normal"/>
+
+ <ImageView
+ android:id="@+id/float_password_btn9"
+ android:layout_width="@dimen/float_password_btn_size"
+ android:layout_height="@dimen/float_password_btn_size"
+ android:layout_marginLeft="@dimen/float_password_right_btn_margin"
+ android:src="@drawable/pass_nine_normal"/>
+ </LinearLayout>
+ <!--第四行按钮-->
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/float_password_btn_size"
+ android:layout_marginBottom="10dp"
+ android:layout_marginTop="@dimen/float_password_right_btn_margin"
+ android:orientation="horizontal">
+
+ <TextView
+ android:id="@+id/float_password_cancel"
+ android:layout_width="@dimen/float_password_btn_size"
+ android:layout_height="@dimen/float_password_btn_size"
+ android:background="@drawable/btn_red_normal"
+ android:gravity="center"
+ android:text="取消"
+ android:textColor="@color/white"
+ android:textSize="30sp"/>
+
+ <ImageView
+ android:id="@+id/float_password_btn0"
+ android:layout_width="@dimen/float_password_btn_size"
+ android:layout_height="@dimen/float_password_btn_size"
+ android:layout_marginLeft="@dimen/float_password_right_btn_margin"
+ android:src="@drawable/pass_zero_normal"/>
+
+ <ImageView
+ android:id="@+id/float_password_btn_delete"
+ android:layout_width="@dimen/float_password_btn_size"
+ android:layout_height="@dimen/float_password_btn_size"
+ android:layout_marginLeft="@dimen/float_password_right_btn_margin"
+ android:src="@drawable/pass_delete_normal"/>
+ </LinearLayout>
+ </LinearLayout>
+ </LinearLayout>
+</RelativeLayout>
+
+
diff --git a/app/src/main/res/layout/dialog_progress.xml b/app/src/main/res/layout/dialog_progress.xml
new file mode 100644
index 0000000..f2c8fb8
--- /dev/null
+++ b/app/src/main/res/layout/dialog_progress.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="@drawable/pay_ret_dialog_bg"
+ android:orientation="vertical"
+ android:gravity="center"
+ android:paddingTop="30dp"
+ android:paddingBottom="30dp"
+ android:paddingLeft="30dp"
+ android:paddingRight="30dp">
+
+ <ProgressBar
+ android:id="@+id/loadingImageView"
+ style="@style/myProgressBarStyleLarge"
+ android:layout_width="200dp"
+ android:layout_height="200dp"
+ android:layout_gravity="center"
+ android:padding="20dp" />
+
+ <TextView
+ android:id="@+id/loadingmsg"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:textColor="@android:color/white"
+ android:text="正在处理,请不要拿走卡片..."
+ android:textSize="30dp"
+ android:layout_marginBottom="30dp"
+ android:layout_marginTop="10dp" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/dialog_purchase.xml b/app/src/main/res/layout/dialog_purchase.xml
new file mode 100644
index 0000000..e43ef15
--- /dev/null
+++ b/app/src/main/res/layout/dialog_purchase.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="450dp"
+ android:layout_height="300dp"
+ android:background="@color/light_blue2"
+ android:layout_gravity="center"
+ android:orientation="vertical">
+ <RelativeLayout android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ android:layout_margin="10dp"
+ android:background="@drawable/corner_bg_white"
+ android:gravity="center_horizontal"
+ android:orientation="vertical">
+ <!--倒计时-->
+ <TextView
+ android:id="@+id/tv_close_count"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="15dp"
+ android:layout_marginTop="10dp"
+ android:gravity="start|center"
+ android:text="30s"
+ android:textColor="@color/blue"
+ android:textSize="30sp"/>
+ <LinearLayout
+ style="@style/purchase_ll_text_style"
+ android:layout_below="@+id/tv_close_count">
+
+ <TextView
+ android:id="@+id/tv_pay_hint"
+ style="@style/purchase_tv_text_hint_style"
+ android:text="消费成功"
+ android:textColor="@color/light_green"/>
+
+ <TextView
+ android:id="@+id/tv_pay_amount"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="10dp"
+ android:text="金额: 10.00元"
+ android:textColor="@color/black"
+ android:textSize="@dimen/ordinary_consume_text_size"/>
+
+ <TextView
+ android:id="@+id/tv_pay_balance"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="余额: 123.00元"
+ android:textColor="@color/black"
+ android:textSize="@dimen/ordinary_consume_text_size"/>
+
+ </LinearLayout>
+ </RelativeLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_init_nsd_config_list.xml b/app/src/main/res/layout/item_init_nsd_config_list.xml
new file mode 100644
index 0000000..735e6f9
--- /dev/null
+++ b/app/src/main/res/layout/item_init_nsd_config_list.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/ll_config"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="@drawable/corner_bg_gray"
+ android:orientation="horizontal">
+
+ <TextView
+ android:id="@+id/tv_config_id"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:maxLines="1"
+ android:padding="10dp"
+ android:textColor="@color/light_blue2"
+ android:textSize="30sp"
+ android:textStyle="bold" />
+
+ <TextView
+ android:id="@+id/tv_config_name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="10dp"
+ android:maxLines="1"
+ android:padding="10dp"
+ android:textColor="@color/light_blue2"
+ android:textSize="30sp"
+ android:textStyle="bold" />
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_syspara.xml b/app/src/main/res/layout/item_syspara.xml
new file mode 100644
index 0000000..cdaccac
--- /dev/null
+++ b/app/src/main/res/layout/item_syspara.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal"
+ android:weightSum="2">
+
+ <TextView
+ android:id="@+id/tv_name"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:textColor="@color/light_blue2"
+ android:textSize="30sp"/>
+
+ <TextView
+ android:id="@+id/tv_value"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:textColor="@color/light_blue2"
+ android:textSize="30sp"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/sw_toast.xml b/app/src/main/res/layout/sw_toast.xml
new file mode 100644
index 0000000..bdc5081
--- /dev/null
+++ b/app/src/main/res/layout/sw_toast.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@drawable/corner_bg"
+ android:gravity="center"
+ android:orientation="horizontal"
+ android:padding="5dp">
+
+ <ImageView
+ android:id="@+id/pic_cry"
+ android:layout_width="60dp"
+ android:layout_height="60dp"
+ android:layout_gravity="center"
+ android:scaleType="fitXY"
+ android:src="@drawable/toast_cry"
+ android:visibility="gone"/>
+
+ <ImageView
+ android:id="@+id/pic_smile"
+ android:layout_width="60dp"
+ android:layout_height="60dp"
+ android:layout_gravity="center"
+ android:scaleType="fitXY"
+ android:src="@drawable/toast_smile"/>
+
+ <ImageView
+ android:id="@+id/pic_doubt"
+ android:layout_width="60dp"
+ android:layout_height="60dp"
+ android:layout_gravity="center"
+ android:scaleType="fitXY"
+ android:src="@drawable/toast_doubt"
+ android:visibility="gone"/>
+
+ <TextView
+ android:id="@+id/toasttext"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="链路检测失败"
+ android:textColor="@color/black"
+ android:textSize="45dp"
+ android:textStyle="bold"/>
+</LinearLayout>
diff --git a/app/src/main/res/layout/toast_util.xml b/app/src/main/res/layout/toast_util.xml
new file mode 100644
index 0000000..765f9cd
--- /dev/null
+++ b/app/src/main/res/layout/toast_util.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/toasttext"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:background="@drawable/corner_bg"
+ android:padding="30dp"
+ android:text="测试"
+ android:textColor="@color/black"
+ android:textSize="35sp"
+ android:textStyle="bold"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..bbd3e02
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@drawable/ic_launcher_background"/>
+ <foreground android:drawable="@drawable/ic_launcher_foreground"/>
+</adaptive-icon>
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..bbd3e02
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@drawable/ic_launcher_background"/>
+ <foreground android:drawable="@drawable/ic_launcher_foreground"/>
+</adaptive-icon>
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-hdpi/bill_lastdtl.png b/app/src/main/res/mipmap-hdpi/bill_lastdtl.png
new file mode 100644
index 0000000..de03aa0
--- /dev/null
+++ b/app/src/main/res/mipmap-hdpi/bill_lastdtl.png
Binary files differ
diff --git a/app/src/main/res/mipmap-hdpi/default_photo.png b/app/src/main/res/mipmap-hdpi/default_photo.png
new file mode 100644
index 0000000..ca377a9
--- /dev/null
+++ b/app/src/main/res/mipmap-hdpi/default_photo.png
Binary files differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..898f3ed
--- /dev/null
+++ b/app/src/main/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..dffca36
--- /dev/null
+++ b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
Binary files differ
diff --git a/app/src/main/res/mipmap-hdpi/pay_with_bar.png b/app/src/main/res/mipmap-hdpi/pay_with_bar.png
new file mode 100644
index 0000000..9c1f31a
--- /dev/null
+++ b/app/src/main/res/mipmap-hdpi/pay_with_bar.png
Binary files differ
diff --git a/app/src/main/res/mipmap-hdpi/pay_with_card.png b/app/src/main/res/mipmap-hdpi/pay_with_card.png
new file mode 100644
index 0000000..1b2d929
--- /dev/null
+++ b/app/src/main/res/mipmap-hdpi/pay_with_card.png
Binary files differ
diff --git a/app/src/main/res/mipmap-hdpi/pay_with_scan.png b/app/src/main/res/mipmap-hdpi/pay_with_scan.png
new file mode 100644
index 0000000..afc2bb1
--- /dev/null
+++ b/app/src/main/res/mipmap-hdpi/pay_with_scan.png
Binary files differ
diff --git a/app/src/main/res/mipmap-hdpi/pay_with_virtualcard.png b/app/src/main/res/mipmap-hdpi/pay_with_virtualcard.png
new file mode 100644
index 0000000..f8cf8a6
--- /dev/null
+++ b/app/src/main/res/mipmap-hdpi/pay_with_virtualcard.png
Binary files differ
diff --git a/app/src/main/res/mipmap-hdpi/scan_default_photo.jpg b/app/src/main/res/mipmap-hdpi/scan_default_photo.jpg
new file mode 100644
index 0000000..34adcad
--- /dev/null
+++ b/app/src/main/res/mipmap-hdpi/scan_default_photo.jpg
Binary files differ
diff --git a/app/src/main/res/mipmap-hdpi/shop_logo.png b/app/src/main/res/mipmap-hdpi/shop_logo.png
new file mode 100644
index 0000000..79ba1ec
--- /dev/null
+++ b/app/src/main/res/mipmap-hdpi/shop_logo.png
Binary files differ
diff --git a/app/src/main/res/mipmap-hdpi/show_card_info.png b/app/src/main/res/mipmap-hdpi/show_card_info.png
new file mode 100644
index 0000000..c622914
--- /dev/null
+++ b/app/src/main/res/mipmap-hdpi/show_card_info.png
Binary files differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..64ba76f
--- /dev/null
+++ b/app/src/main/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..dae5e08
--- /dev/null
+++ b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
Binary files differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..e5ed465
--- /dev/null
+++ b/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..14ed0af
--- /dev/null
+++ b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
Binary files differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..b0907ca
--- /dev/null
+++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..d8ae031
--- /dev/null
+++ b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
Binary files differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..2c18de9
--- /dev/null
+++ b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..beed3cd
--- /dev/null
+++ b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
Binary files differ
diff --git a/app/src/main/res/raw/beep.ogg b/app/src/main/res/raw/beep.ogg
new file mode 100644
index 0000000..1419947
--- /dev/null
+++ b/app/src/main/res/raw/beep.ogg
Binary files differ
diff --git a/app/src/main/res/raw/card_passwd.wav b/app/src/main/res/raw/card_passwd.wav
new file mode 100644
index 0000000..f53ffb4
--- /dev/null
+++ b/app/src/main/res/raw/card_passwd.wav
Binary files differ
diff --git a/app/src/main/res/raw/consume_fail.wav b/app/src/main/res/raw/consume_fail.wav
new file mode 100644
index 0000000..37905b9
--- /dev/null
+++ b/app/src/main/res/raw/consume_fail.wav
Binary files differ
diff --git a/app/src/main/res/raw/consume_suc.wav b/app/src/main/res/raw/consume_suc.wav
new file mode 100644
index 0000000..29dba78
--- /dev/null
+++ b/app/src/main/res/raw/consume_suc.wav
Binary files differ
diff --git a/app/src/main/res/raw/dps_fail.wav b/app/src/main/res/raw/dps_fail.wav
new file mode 100644
index 0000000..3dd255e
--- /dev/null
+++ b/app/src/main/res/raw/dps_fail.wav
Binary files differ
diff --git a/app/src/main/res/raw/dps_feeamt_suc.wav b/app/src/main/res/raw/dps_feeamt_suc.wav
new file mode 100644
index 0000000..976f337
--- /dev/null
+++ b/app/src/main/res/raw/dps_feeamt_suc.wav
Binary files differ
diff --git a/app/src/main/res/raw/dps_login_fail.wav b/app/src/main/res/raw/dps_login_fail.wav
new file mode 100644
index 0000000..cc7f082
--- /dev/null
+++ b/app/src/main/res/raw/dps_login_fail.wav
Binary files differ
diff --git a/app/src/main/res/raw/dps_login_suc.wav b/app/src/main/res/raw/dps_login_suc.wav
new file mode 100644
index 0000000..f93d948
--- /dev/null
+++ b/app/src/main/res/raw/dps_login_suc.wav
Binary files differ
diff --git a/app/src/main/res/raw/dps_suc.wav b/app/src/main/res/raw/dps_suc.wav
new file mode 100644
index 0000000..7fc83cf
--- /dev/null
+++ b/app/src/main/res/raw/dps_suc.wav
Binary files differ
diff --git a/app/src/main/res/raw/eastcompeace_a711.json b/app/src/main/res/raw/eastcompeace_a711.json
new file mode 100644
index 0000000..c768ceb
--- /dev/null
+++ b/app/src/main/res/raw/eastcompeace_a711.json
@@ -0,0 +1,16 @@
+{
+ "desc": "东信和平(哈工程)",
+ "manufactory": "eastcompeace",
+ "fingerprint": [
+ {
+ "fingerprint": "127880B0024D540081",
+ "offset": 4,
+ "defaultRootKey": "00000000000000000000000000000000"
+ },
+ {
+ "fingerprint": "057880B002",
+ "offset": 4,
+ "defaultRootKey": "00000000000000000000000000000000"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/app/src/main/res/raw/epaycard.cfg b/app/src/main/res/raw/epaycard.cfg
new file mode 100644
index 0000000..c55ad32
--- /dev/null
+++ b/app/src/main/res/raw/epaycard.cfg
@@ -0,0 +1,122 @@
+{
+ "version": "1.0",
+ "custname": "supwisdom",
+ "id": "com.supwisdom.epaycard.cpucard.a711",
+ "desc": "新开普A711读卡器",
+ "issue_date": "20171221",
+ "custom_version": "v1.0",
+ "authcode": "08712016070002",
+ "atr_pretend": true,
+ "support_platform": [
+ "linux"
+ ],
+ "expire_date": "20300517",
+ "cardtype": [
+ {
+ "name": "SupCpuCardType",
+ "class": "com.supwisdom.epaycard.impl.SupCpuCardtype",
+ "psamcard": "sup_psamcard",
+ "keymachine": "SupKeyMachine",
+ "debug": false,
+ "fingerprint": [
+ {
+ "initializer": "com.supwisdom.epaycard.impl.FM201810Initializer",
+ "config": [
+ "classpath:res/raw/fmcos_a711.json"
+ ]
+ },
+ {
+ "config": [
+ "classpath:fingerprint/goldpac_e711.json"
+ ],
+ "initializer": "com.supwisdom.epaycard.impl.GoldPacCardInitializer"
+ }
+ ]
+ },
+ {
+ "name": "SupCpuCardTypeWithoutMac",
+ "class": "com.supwisdom.epaycard.impl.SupCardtypeRWOM",
+ "psamcard": "sup_psamcard",
+ "keymachine": "SupKeyMachine",
+ "debug": false,
+ "fingerprint": [
+ {
+ "config": [
+ "classpath:res/raw/eastcompeace_a711.json"
+ ],
+ "initializer": "com.supwisdom.epaycard.impl.GoldPacCardInitializer"
+ }
+ ]
+ },
+ {
+ "name": "SupM1Cardtype",
+ "class": "com.supwisdom.epaycard.impl.SupM1CardType",
+ "psamcard": "sup_psamcard",
+ "keymachine": "SupKeyMachine",
+ "keyalg": "normal2",
+ "version": 2008,
+ "water_packet": 6,
+ "minsect": 0,
+ "maxsect": 6,
+ "init_sections": [
+ 1,
+ 2,
+ 4,
+ 5,
+ 6
+ ],
+ "debug": false
+ }
+ ],
+ "reader": [
+ {
+ "name": "a711_reader",
+ "class": "com.supwisdom.epaycard.android.A711Reader",
+ "picc_req_times": 1,
+ "rf_interval": 100,
+ "rf_timeout": 300,
+ "debug": false
+ }
+ ],
+ "psamcard": [
+ {
+ "name": "sup_psamcard",
+ "reader": "a711_reader",
+ "keymachine": "SupKeyMachine",
+ "class": "com.supwisdom.epaycard.impl.SupPsamCard",
+ "debug": false,
+ "max_sect_len": 48,
+ "fingerprint": [
+ {
+ "manufactory": "einolda",
+ "fingerprint": "FFFF",
+ "max_block": 56,
+ "offset": 4,
+ "default": true
+ },
+ {
+ "manufactory": "broadstar",
+ "fingerprint": "4253",
+ "offset": 5,
+ "defaultRootKey": "57415443484441544154696D65434F53"
+ }
+ ]
+ }
+ ],
+ "keymachine": [
+ {
+ "name": "SupKeyMachine",
+ "reader": "a711_reader",
+ "debug": false,
+ "class": "com.supwisdom.epaycard.impl.SupKeyCard"
+ }
+ ],
+ "water_setting_card": [
+ {
+ "name": "sup_watercard",
+ "reader": "a711_reader",
+ "keymachine": "SupKeyMachine",
+ "class": "com.supwisdom.epaycard.impl.SupWaterSettingCard"
+ }
+ ]
+}
diff --git a/app/src/main/res/raw/epaycard_hit.cfg b/app/src/main/res/raw/epaycard_hit.cfg
new file mode 100644
index 0000000..7b99201
--- /dev/null
+++ b/app/src/main/res/raw/epaycard_hit.cfg
@@ -0,0 +1,101 @@
+{
+ "version": "1.0",
+ "custname": "supwisdom",
+ "id": "com.supwisdom.epaycard.cpucard.a711",
+ "desc": "新开普A711读卡器",
+ "issue_date": "20171221",
+ "custom_version": "v1.0",
+ "authcode": "08712016070002",
+ "atr_pretend": true,
+ "support_platform": [
+ "linux"
+ ],
+ "expire_date": "20300517",
+ "cardtype": [
+ {
+ "name": "SupCpuCardTypeWithoutMac",
+ "class": "com.supwisdom.epaycard.impl.SupCardtypeRWOM",
+ "psamcard": "sup_psamcard",
+ "keymachine": "SupKeyMachine",
+ "debug": false,
+ "fingerprint": [
+ {
+ "config": [
+ "classpath:res/raw/eastcompeace_a711.json"
+ ],
+ "initializer": "com.supwisdom.epaycard.impl.GoldPacCardInitializer"
+ }
+ ]
+ },
+ {
+ "name": "SupM1Cardtype",
+ "class": "com.supwisdom.epaycard.impl.SupM1CardType",
+ "psamcard": "sup_psamcard",
+ "keymachine": "SupKeyMachine",
+ "keyalg": "normal2",
+ "version": 2008,
+ "water_packet": 6,
+ "minsect": 0,
+ "maxsect": 6,
+ "init_sections": [
+ 1,
+ 2,
+ 4,
+ 5,
+ 6
+ ],
+ "debug": false
+ }
+ ],
+ "reader": [
+ {
+ "name": "a711_reader",
+ "class": "com.supwisdom.epaycard.android.A711Reader",
+ "picc_req_times": 1,
+ "rf_interval": 100,
+ "rf_timeout": 300,
+ "debug": false
+ }
+ ],
+ "psamcard": [
+ {
+ "name": "sup_psamcard",
+ "reader": "a711_reader",
+ "keymachine": "SupKeyMachine",
+ "class": "com.supwisdom.epaycard.impl.SupPsamCard",
+ "debug": false,
+ "max_sect_len": 48,
+ "fingerprint": [
+ {
+ "manufactory": "einolda",
+ "fingerprint": "FFFF",
+ "max_block": 56,
+ "offset": 4,
+ "default": true
+ },
+ {
+ "manufactory": "broadstar",
+ "fingerprint": "4253",
+ "offset": 5,
+ "defaultRootKey": "57415443484441544154696D65434F53"
+ }
+ ]
+ }
+ ],
+ "keymachine": [
+ {
+ "name": "SupKeyMachine",
+ "reader": "a711_reader",
+ "debug": false,
+ "class": "com.supwisdom.epaycard.impl.SupKeyCard"
+ }
+ ],
+ "water_setting_card": [
+ {
+ "name": "sup_watercard",
+ "reader": "a711_reader",
+ "keymachine": "SupKeyMachine",
+ "class": "com.supwisdom.epaycard.impl.SupWaterSettingCard"
+ }
+ ]
+}
diff --git a/app/src/main/res/raw/fmcos_a711.json b/app/src/main/res/raw/fmcos_a711.json
new file mode 100644
index 0000000..20035ee
--- /dev/null
+++ b/app/src/main/res/raw/fmcos_a711.json
@@ -0,0 +1,11 @@
+{
+ "desc" : "FM1208卡",
+ "manufactory" :"fmcos1208",
+ "fingerprint" : [
+ {
+ "fingerprint": "20900000000000",
+ "offset": 0,
+ "defaultRootKey": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/app/src/main/res/raw/gatein_fail.wav b/app/src/main/res/raw/gatein_fail.wav
new file mode 100644
index 0000000..0de1b71
--- /dev/null
+++ b/app/src/main/res/raw/gatein_fail.wav
Binary files differ
diff --git a/app/src/main/res/raw/gatein_suc.wav b/app/src/main/res/raw/gatein_suc.wav
new file mode 100644
index 0000000..56b106c
--- /dev/null
+++ b/app/src/main/res/raw/gatein_suc.wav
Binary files differ
diff --git a/app/src/main/res/raw/gateout_fail.wav b/app/src/main/res/raw/gateout_fail.wav
new file mode 100644
index 0000000..4b2c39c
--- /dev/null
+++ b/app/src/main/res/raw/gateout_fail.wav
Binary files differ
diff --git a/app/src/main/res/raw/gateout_suc.wav b/app/src/main/res/raw/gateout_suc.wav
new file mode 100644
index 0000000..e04a659
--- /dev/null
+++ b/app/src/main/res/raw/gateout_suc.wav
Binary files differ
diff --git a/app/src/main/res/raw/goldpac_a711.json b/app/src/main/res/raw/goldpac_a711.json
new file mode 100644
index 0000000..20a5f2d
--- /dev/null
+++ b/app/src/main/res/raw/goldpac_a711.json
@@ -0,0 +1,16 @@
+{
+ "desc" : "金邦达卡",
+ "manufactory" :"goldpac",
+ "fingerprint" : [
+ {
+ "fingerprint": "80318066",
+ "offset": 2,
+ "defaultRootKey": "00000000000000000000000000000000"
+ },
+ {
+ "fingerprint": "057880A002",
+ "offset": 4,
+ "defaultRootKey": "00000000000000000000000000000000"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/app/src/main/res/raw/key_add.wav b/app/src/main/res/raw/key_add.wav
new file mode 100644
index 0000000..8fe2703
--- /dev/null
+++ b/app/src/main/res/raw/key_add.wav
Binary files differ
diff --git a/app/src/main/res/raw/key_clear.wav b/app/src/main/res/raw/key_clear.wav
new file mode 100644
index 0000000..3c29559
--- /dev/null
+++ b/app/src/main/res/raw/key_clear.wav
Binary files differ
diff --git a/app/src/main/res/raw/key_dot.wav b/app/src/main/res/raw/key_dot.wav
new file mode 100644
index 0000000..69232dc
--- /dev/null
+++ b/app/src/main/res/raw/key_dot.wav
Binary files differ
diff --git a/app/src/main/res/raw/key_eight.wav b/app/src/main/res/raw/key_eight.wav
new file mode 100644
index 0000000..484f755
--- /dev/null
+++ b/app/src/main/res/raw/key_eight.wav
Binary files differ
diff --git a/app/src/main/res/raw/key_enter.wav b/app/src/main/res/raw/key_enter.wav
new file mode 100644
index 0000000..5386f86
--- /dev/null
+++ b/app/src/main/res/raw/key_enter.wav
Binary files differ
diff --git a/app/src/main/res/raw/key_ffour.wav b/app/src/main/res/raw/key_ffour.wav
new file mode 100644
index 0000000..6b94cb9
--- /dev/null
+++ b/app/src/main/res/raw/key_ffour.wav
Binary files differ
diff --git a/app/src/main/res/raw/key_five.wav b/app/src/main/res/raw/key_five.wav
new file mode 100644
index 0000000..830e234
--- /dev/null
+++ b/app/src/main/res/raw/key_five.wav
Binary files differ
diff --git a/app/src/main/res/raw/key_fone.wav b/app/src/main/res/raw/key_fone.wav
new file mode 100644
index 0000000..59adfde
--- /dev/null
+++ b/app/src/main/res/raw/key_fone.wav
Binary files differ
diff --git a/app/src/main/res/raw/key_four.wav b/app/src/main/res/raw/key_four.wav
new file mode 100644
index 0000000..5580975
--- /dev/null
+++ b/app/src/main/res/raw/key_four.wav
Binary files differ
diff --git a/app/src/main/res/raw/key_fthree.wav b/app/src/main/res/raw/key_fthree.wav
new file mode 100644
index 0000000..1291d25
--- /dev/null
+++ b/app/src/main/res/raw/key_fthree.wav
Binary files differ
diff --git a/app/src/main/res/raw/key_ftwo.wav b/app/src/main/res/raw/key_ftwo.wav
new file mode 100644
index 0000000..07fd91c
--- /dev/null
+++ b/app/src/main/res/raw/key_ftwo.wav
Binary files differ
diff --git a/app/src/main/res/raw/key_nine.wav b/app/src/main/res/raw/key_nine.wav
new file mode 100644
index 0000000..7013cb5
--- /dev/null
+++ b/app/src/main/res/raw/key_nine.wav
Binary files differ
diff --git a/app/src/main/res/raw/key_one.wav b/app/src/main/res/raw/key_one.wav
new file mode 100644
index 0000000..3b998f3
--- /dev/null
+++ b/app/src/main/res/raw/key_one.wav
Binary files differ
diff --git a/app/src/main/res/raw/key_seven.wav b/app/src/main/res/raw/key_seven.wav
new file mode 100644
index 0000000..e5226ce
--- /dev/null
+++ b/app/src/main/res/raw/key_seven.wav
Binary files differ
diff --git a/app/src/main/res/raw/key_six.wav b/app/src/main/res/raw/key_six.wav
new file mode 100644
index 0000000..2e25469
--- /dev/null
+++ b/app/src/main/res/raw/key_six.wav
Binary files differ
diff --git a/app/src/main/res/raw/key_three.wav b/app/src/main/res/raw/key_three.wav
new file mode 100644
index 0000000..ad00780
--- /dev/null
+++ b/app/src/main/res/raw/key_three.wav
Binary files differ
diff --git a/app/src/main/res/raw/key_two.wav b/app/src/main/res/raw/key_two.wav
new file mode 100644
index 0000000..56fc1de
--- /dev/null
+++ b/app/src/main/res/raw/key_two.wav
Binary files differ
diff --git a/app/src/main/res/raw/key_zero.wav b/app/src/main/res/raw/key_zero.wav
new file mode 100644
index 0000000..4fd1864
--- /dev/null
+++ b/app/src/main/res/raw/key_zero.wav
Binary files differ
diff --git a/app/src/main/res/raw/login_fail.wav b/app/src/main/res/raw/login_fail.wav
new file mode 100644
index 0000000..3e901c7
--- /dev/null
+++ b/app/src/main/res/raw/login_fail.wav
Binary files differ
diff --git a/app/src/main/res/raw/login_suc.wav b/app/src/main/res/raw/login_suc.wav
new file mode 100644
index 0000000..70a4ee2
--- /dev/null
+++ b/app/src/main/res/raw/login_suc.wav
Binary files differ
diff --git a/app/src/main/res/raw/pay_fail.wav b/app/src/main/res/raw/pay_fail.wav
new file mode 100644
index 0000000..85dbb67
--- /dev/null
+++ b/app/src/main/res/raw/pay_fail.wav
Binary files differ
diff --git a/app/src/main/res/raw/pay_suc.wav b/app/src/main/res/raw/pay_suc.wav
new file mode 100644
index 0000000..e0e8945
--- /dev/null
+++ b/app/src/main/res/raw/pay_suc.wav
Binary files differ
diff --git a/app/src/main/res/raw/query_fail.wav b/app/src/main/res/raw/query_fail.wav
new file mode 100644
index 0000000..4532286
--- /dev/null
+++ b/app/src/main/res/raw/query_fail.wav
Binary files differ
diff --git a/app/src/main/res/raw/query_suc.wav b/app/src/main/res/raw/query_suc.wav
new file mode 100644
index 0000000..d156756
--- /dev/null
+++ b/app/src/main/res/raw/query_suc.wav
Binary files differ
diff --git a/app/src/main/res/raw/reversal_done.wav b/app/src/main/res/raw/reversal_done.wav
new file mode 100644
index 0000000..72804bb
--- /dev/null
+++ b/app/src/main/res/raw/reversal_done.wav
Binary files differ
diff --git a/app/src/main/res/raw/reversal_fail.wav b/app/src/main/res/raw/reversal_fail.wav
new file mode 100644
index 0000000..2e314be
--- /dev/null
+++ b/app/src/main/res/raw/reversal_fail.wav
Binary files differ
diff --git a/app/src/main/res/raw/reversal_suc.wav b/app/src/main/res/raw/reversal_suc.wav
new file mode 100644
index 0000000..61f1c8a
--- /dev/null
+++ b/app/src/main/res/raw/reversal_suc.wav
Binary files differ
diff --git a/app/src/main/res/raw/scan_beep.ogg b/app/src/main/res/raw/scan_beep.ogg
new file mode 100644
index 0000000..1419947
--- /dev/null
+++ b/app/src/main/res/raw/scan_beep.ogg
Binary files differ
diff --git a/app/src/main/res/raw/sound_key_eight.wav b/app/src/main/res/raw/sound_key_eight.wav
new file mode 100644
index 0000000..82d8b26
--- /dev/null
+++ b/app/src/main/res/raw/sound_key_eight.wav
Binary files differ
diff --git a/app/src/main/res/raw/sound_key_five.wav b/app/src/main/res/raw/sound_key_five.wav
new file mode 100644
index 0000000..b35596c
--- /dev/null
+++ b/app/src/main/res/raw/sound_key_five.wav
Binary files differ
diff --git a/app/src/main/res/raw/sound_key_four.wav b/app/src/main/res/raw/sound_key_four.wav
new file mode 100644
index 0000000..f56c4ee
--- /dev/null
+++ b/app/src/main/res/raw/sound_key_four.wav
Binary files differ
diff --git a/app/src/main/res/raw/sound_key_nine.wav b/app/src/main/res/raw/sound_key_nine.wav
new file mode 100644
index 0000000..20722db
--- /dev/null
+++ b/app/src/main/res/raw/sound_key_nine.wav
Binary files differ
diff --git a/app/src/main/res/raw/sound_key_one.wav b/app/src/main/res/raw/sound_key_one.wav
new file mode 100644
index 0000000..faf8bdb
--- /dev/null
+++ b/app/src/main/res/raw/sound_key_one.wav
Binary files differ
diff --git a/app/src/main/res/raw/sound_key_seven.wav b/app/src/main/res/raw/sound_key_seven.wav
new file mode 100644
index 0000000..9baaafc
--- /dev/null
+++ b/app/src/main/res/raw/sound_key_seven.wav
Binary files differ
diff --git a/app/src/main/res/raw/sound_key_six.wav b/app/src/main/res/raw/sound_key_six.wav
new file mode 100644
index 0000000..cb4b14e
--- /dev/null
+++ b/app/src/main/res/raw/sound_key_six.wav
Binary files differ
diff --git a/app/src/main/res/raw/sound_key_three.wav b/app/src/main/res/raw/sound_key_three.wav
new file mode 100644
index 0000000..354a26d
--- /dev/null
+++ b/app/src/main/res/raw/sound_key_three.wav
Binary files differ
diff --git a/app/src/main/res/raw/sound_key_two.wav b/app/src/main/res/raw/sound_key_two.wav
new file mode 100644
index 0000000..87898f3
--- /dev/null
+++ b/app/src/main/res/raw/sound_key_two.wav
Binary files differ
diff --git a/app/src/main/res/raw/sound_key_zero.wav b/app/src/main/res/raw/sound_key_zero.wav
new file mode 100644
index 0000000..be4f0cb
--- /dev/null
+++ b/app/src/main/res/raw/sound_key_zero.wav
Binary files differ
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..07cae7a
--- /dev/null
+++ b/app/src/main/res/values/colors.xml
@@ -0,0 +1,105 @@
+<resources>
+ <color name="black_overlay">#66000000</color>
+ <color name="btn_light_blue">#5bc0de</color>
+ <color name="light_gray">#ffa2a2a2</color>
+ <color name="light_gray1">#cdcdcd</color>
+ <color name="light_green">#46d608</color>
+ <color name="light_green1">#83f800</color>
+ <color name="light_green2">#05a910</color>
+ <color name="light_blue1">#00bb9c</color>
+ <color name="light_purple">#ed07d0</color>
+ <color name="light_purple1">#f57cc3</color>
+ <color name="light_purple2">#b20469</color>
+ <color name="light_blue">#7899c4</color>
+ <color name="light_yellow">#e1cb28</color>
+ <color name="light_yellow_2">#ffffe928</color>
+ <color name="light_yellow_3">#fffe9f</color>
+ <color name="light_black">#424652</color>
+ <color name="white_gray">#f9f9f9</color>
+ <color name="white">#FFFFFF</color>
+ <color name="pwdColor">#999999</color>
+ <color name="password_hint">#666666</color>
+ <color name="orange">#FD7201</color>
+ <color name="orange1">#FF6600</color>
+ <color name="black">#000</color>
+ <color name="blue">#0c0de1</color>
+ <color name="dark_blue1">#13227a</color>
+ <color name="light_blue2">#2D95E0</color>
+ <color name="dark_blue">#0E1C36</color>
+ <color name="lit_light_gray">#23292E</color>
+ <color name="light_gray_white">#EEEEEE</color>
+ <color name="result_view">#b0000000</color>
+ <color name="viewfinder_mask">#60000000</color>
+ <color name="possible_result_points">#c0ffff00</color>
+ <color name="key_btn_color">#EEEEEE</color>
+ <color name="cl_red">#FF0000</color>
+ <color name="pos_theme_color">#08ae9e</color>
+ <color name="consume_caption">#434343</color>
+ <color name="consume_font">#666666</color>
+ <color name="consume_background">#f3f3f3</color>
+ <color name="main_back_consume_normal">#F15D5D</color>
+ <color name="main_back_consume_click">#E55A5A</color>
+ <color name="main_back_online_deposit_normal">#7E62F8</color>
+ <color name="main_back_online_deposit_click">#785EEB</color>
+ <color name="main_back_device_manage_normal">#7E62F8</color>
+ <color name="main_back_device_manage_click">#785EEB</color>
+ <!--<color custname="main_back_cancel_consume_normal">#25A3B3</color>-->
+ <!--<color custname="main_back_cancel_consume_click">#2396A6</color>-->
+ <color name="main_back_query_revenue_normal">#999999</color>
+ <!--<color custname="main_back_query_revenue_click">#85A629</color>-->
+ <color name="main_back_library_normal">#8EB32C</color>
+ <color name="main_back_library_click">#85A629</color>
+ <color name="main_back_manual_auth_normal">#8EB32C</color>
+ <color name="main_back_manual_auth_click">#85A629</color>
+ <color name="bk_set_block">#F3F3F3</color>
+ <!--<color custname="main_back_update_blacklist_normal">#7E62F8</color>-->
+ <!--<color custname="main_back_update_blacklist_click">#785EEB</color>-->
+ <color name="main_back_update_blacklist_normal">#F28923</color>
+ <color name="main_back_update_blacklist_click">#F28923</color>
+ <color name="main_back_online_order_normal">#F28923</color>
+ <color name="main_back_online_order_click">#F28923</color>
+ <color name="main_back_transdtl_normal">#20A193</color>
+ <color name="main_back_transdtl_click">#1E9486</color>
+ <!--<color custname="main_back_test_net_normal">#F15D5D</color>-->
+ <!--<color custname="main_back_test_net_click">#E55A5A</color>-->
+ <color name="main_back_test_net_normal">#F15D5D</color>
+ <color name="main_back_test_net_click">#E55A5A</color>
+
+ <color name="main_back_query_para_normal">#20A193</color>
+ <color name="main_back_query_para_click">#1E9486</color>
+ <!--<color custname="main_back_device_manage_normal">#2f87d2</color>-->
+ <!--<color custname="main_back_device_manage_click">#2b7dc4</color>-->
+ <color name="main_online_bak">#f1f1f1</color>
+ <color name="main_offline_font">#888888</color>
+ <!--启用界面-->
+ <color name="enable_text_font_color">#333333</color>
+ <color name="enable_devphyid_edit_font_color">#666666</color>
+ <color name="enable_bak">#f1f1f1</color>
+ <color name="enable_step_doing">#333333</color>
+ <color name="enable_step_fail">#ff0000</color>
+ <color name="enable_step_success">#8fccc6</color>
+ <!--设置界面-->
+ <color name="main_divide_line">#e8e8e8</color>
+ <color name="set_menu_bak_normal">#f3f3f3</color>
+ <color name="set_menu_bak_focus">#e4e4e4</color>
+ <color name="set_menu_words">#333333</color>
+ <color name="rf_words_info">#666666</color>
+ <color name="pos_theme_font_color">#333333</color>
+ <!--查询界面下一页按钮的颜色-->
+ <color name="query_next_btn_focus">#08a191</color>
+ <color name="query_next_btn_normal">#08ae9e</color>
+ <!--点餐-->
+ <color name="order_food_list_bak">#fffece</color>
+ <color name="order_picture_food_price">#434343</color>
+ <color name="order_picture_dec">#333333</color>
+ <color name="order_left_count_one">#434343</color>
+ <color name="order_left_count_over_two">#ff0000</color>
+ <color name="order_count_price_col">#ff6a00</color>
+ <color name="order_picture_price_bak">#80161616</color>
+ <color name="order_dec_btn_normal">#333333</color>
+ <color name="order_dec_btn_focus">#FF9900</color>
+ <color name="order_picture_history">#999999</color>
+ <color name="bak_order">#eeeeee</color>
+ <color name="query_font_color">#ffffff</color>
+ <color name="query_background_color">#eeeeee</color>
+</resources>
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..2d50789
--- /dev/null
+++ b/app/src/main/res/values/dimens.xml
@@ -0,0 +1,309 @@
+<resources>
+ <!-- Example customization of dimensions originally defined in res/values/dimens.xml
+ (such as screen margins) for screens with more than 820dp of available width. This
+ would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
+ <dimen name="activity_horizontal_margin">64dp</dimen>
+ <!--dimen custname="activity_horizontal_margin">16dp</dimen-->
+ <dimen name="activity_vertical_margin">16dp</dimen>
+ <dimen name="key_text_size">100sp</dimen>
+ <!--密码界面-->
+ <dimen name="password_margin_horizontal">10dip</dimen>
+ <dimen name="password_margin_vertical">1dip</dimen>
+ <dimen name="password_left_width">320dip</dimen>
+ <dimen name="password_left_obj_gap">10dip</dimen>
+ <dimen name="password_left_word_margin_top">50dip</dimen>
+ <dimen name="password_hint_size">50sp</dimen>
+ <dimen name="password_char_size">80sp</dimen>
+ <dimen name="password_pwd_char_margin_top">-13dip</dimen>
+ <!--密码界面下-->
+ <dimen name="password_right_btn_margin">20dip</dimen>
+ <dimen name="password_right_margin_left">50dip</dimen>
+ <dimen name="password_pwd_size">110dip</dimen>
+ <dimen name="password_pwd_inner_size">102dip</dimen>
+ <dimen name="password_pwd_inner_length">4dip</dimen>
+ <dimen name="password_btn_size">150dip</dimen>
+ <dimen name="password_right_margin_top">30dip</dimen>
+
+ <!--消费界面左-->
+ <dimen name="consume_left_middle_height">241dip</dimen>
+ <dimen name="consume_waiting_margin_left">18dip</dimen>
+ <dimen name="consume_waiting_margin_top">104dip</dimen>
+ <dimen name="consume_waiting_size">19sp</dimen>
+ <dimen name="consume_left_middle_line_height">52dip</dimen>
+ <dimen name="consume_left_middle_line_margin_left">18dip</dimen>
+ <dimen name="consume_left_middle_line_margin_top">18dip</dimen>
+ <dimen name="consume_caption_width">78dip</dimen>
+ <dimen name="consume_caption_size">19sp</dimen>
+ <dimen name="consume_left_down_height">62dip</dimen>
+ <dimen name="consume_left_down_words_margin_left">18dip</dimen>
+ <dimen name="consume_left_down_words_margin_top">12dip</dimen>
+ <dimen name="consume_amount_margin_top">12dip</dimen>
+ <dimen name="consume_title_size">22sp</dimen>
+ <dimen name="consume_amount_size">21sp</dimen>
+ <dimen name="consume_left_width">250dip</dimen>
+ <!--消费界面右-->
+ <dimen name="consume_right_margin_left">12dip</dimen>
+ <dimen name="consume_right_line_height">67dip</dimen>
+ <dimen name="consume_key_button_width">128dip</dimen>
+ <dimen name="consume_right_down_btn_width">181dip</dimen>
+ <dimen name="main_words_size">20sp</dimen>
+ <dimen name="main_caption_size">26sp</dimen>
+ <dimen name="main_top_caption_indent">10dip</dimen>
+ <dimen name="main_icon_marginRight">27dip</dimen>
+ <dimen name="main_icon_marginBottom">45dip</dimen>
+ <!---普通消费界面-->
+ <dimen name="consume_ordinary_key_height">580dp</dimen>
+ <!--主界面-->
+ <dimen name="main_top_height">485dip</dimen>
+ <dimen name="main_top_line_height">241.5dip</dimen>
+ <dimen name="main_bottom_line_height">119.75dip</dimen>
+ <dimen name="main_bottom_icon_size">49dip</dimen>
+ <dimen name="main_transdtl_icon_size">41dip</dimen>
+ <dimen name="main_words_margin">26dip</dimen>
+ <dimen name="main_top_icon_size">100dip</dimen>
+ <dimen name="main_divide_horizontal">2dip</dimen>
+ <dimen name="main_divide_vertical">2dip</dimen>
+ <dimen name="main_online_height">69dip</dimen>
+ <dimen name="main_online_img_size">40dip</dimen>
+ <dimen name="main_online_font_size">22sp</dimen>
+ <dimen name="main_online_gap">39dip</dimen>
+ <!--主界面上-->
+ <dimen name="main_top_img_margin_top">38dip</dimen>
+ <dimen name="main_query_revenue_margin_big">29dip</dimen>
+ <dimen name="main_query_revenue_margin_title">248dip</dimen>
+ <dimen name="main_query_revenue_margin_giant">88dip</dimen>
+ <dimen name="main_query_revenue_words_gap_vertical">4dip</dimen>
+ <!--主界面上左-->
+ <dimen name="main_top_left_width">508.67dip</dimen>
+ <dimen name="main_transdtl_width">508.67dip</dimen>
+ <dimen name="main_button_width">253.33dip</dimen>
+ <dimen name="main_transdtl_hint_margin_left">156dip</dimen>
+ <dimen name="main_transdtl_hint_margin_top">98dip</dimen>
+ <dimen name="main_trussdtl_hint_margin_top">138dip</dimen>
+ <dimen name="main_transdtl_icon_marginBottom">10dip</dimen>
+ <dimen name="main_transdtl_icon_marginRight">142dip</dimen>
+ <dimen name="main_transdtl_words_marginBottom">10dip</dimen>
+ <dimen name="main_transdtl_words_marginRight">40dip</dimen>
+ <!--主界面底部-->
+ <dimen name="main_bottom_icon_margin_top">38dip</dimen>
+ <dimen name="main_bottom_icon_margin_left">8dip</dimen>
+ <dimen name="main_bottom_words_margin_left">23dip</dimen>
+ <dimen name="main_upd_blacklist_words_margin_left">15dip</dimen>
+ <dimen name="main_bottom_words_margin_top">48dip</dimen>
+ <!--查询界面-->
+ <dimen name="query_title_height">55dip</dimen>
+ <dimen name="query_thick_line_width">3dip</dimen>
+ <dimen name="query_thick_line_height">18dip</dimen>
+ <dimen name="query_content_height">55dip</dimen>
+ <dimen name="query_line_margin_top">3dip</dimen>
+ <dimen name="query_words_margin_left">144dip</dimen>
+ <dimen name="query_words_size">26sp</dimen>
+ <dimen name="query_icon_margin_left">12dip</dimen>
+ <dimen name="query_title_margin_left">6dip</dimen>
+ <dimen name="query_half_width">320dip</dimen>
+ <dimen name="query_right_block_margin_top">6dip</dimen>
+ <!--查询界面翻页按钮-->
+ <dimen name="query_turn_page_words_margin_left">6dip</dimen>
+ <dimen name="query_turn_page_btn_size">25dip</dimen>
+ <dimen name="query_turn_page_btn_margin_left">220dip</dimen>
+ <dimen name="query_prev_margin_top">230dip</dimen>
+ <!--消费流水界面-->
+ <dimen name="revenue_btn_size">35dp</dimen>
+ <dimen name="revenue_serch_text_size">30dp</dimen>
+ <dimen name="revenue_list_size">25dp</dimen>
+ <dimen name="revenue_item_size">22dp</dimen>
+ <!--设置界面通用-->
+ <dimen name="set_menu_height">100dip</dimen>
+ <dimen name="set_menu_text_size">30sp</dimen>
+ <dimen name="set_block_words_margin_left">12dip</dimen>
+ <dimen name="set_block_words_width">360dip</dimen>
+ <dimen name="set_arrow_size">19dip</dimen>
+ <dimen name="set_block_width">300dip</dimen>
+ <dimen name="set_block_margin_top">35dip</dimen>
+ <dimen name="set_block_margin_bottom">35dip</dimen>
+
+ <!--恢复出厂界面-->
+ <dimen name="rf_middle_btn_width">108dip</dimen>
+ <dimen name="rf_middle_btn_height">49dip</dimen>
+ <dimen name="rf_middle_words_height">117dip</dimen>
+ <dimen name="rf_words_size">25sp</dimen>
+ <dimen name="rf_middle_btn_margin_bottom">18dip</dimen>
+ <dimen name="rf_progress_bar_height">3dip</dimen>
+ <dimen name="rf_progress_bar_width">481dip</dimen>
+ <!--启用界面-->
+ <dimen name="enable_devphyid_line_inner_gap">15dip</dimen>
+ <dimen name="enable_title_text_size">32sp</dimen>
+ <dimen name="enable_devphyid_font_size">28sp</dimen>
+ <dimen name="enable_devphyid_line_gap">20dip</dimen>
+ <dimen name="enable_devphyid_btn_margin_top">50dip</dimen>
+ <dimen name="enable_devphyid_line_margin_top">80dip</dimen>
+ <dimen name="enable_devphyid_text_width">110dip</dimen>
+ <dimen name="enable_devphyid_edit_width">560dip</dimen>
+ <dimen name="enable_confirm_width">100dip</dimen>
+ <dimen name="enable_confirm_height">50dip</dimen>
+ <dimen name="enable_devphyid_middle_width">668dip</dimen>
+ <dimen name="enable_devphyid_middle_height">660dip</dimen>
+ <dimen name="enable_devphyid_margin_top">70dip</dimen>
+ <dimen name="enable_devphyid_middle_margin_top">20dip</dimen>
+ <dimen name="enable_btn_width">150dip</dimen>
+ <dimen name="enable_btn_height">80dip</dimen>
+ <dimen name="enable_devphyid_btn_gap">150dip</dimen>
+ <!--启用步骤页面-->
+ <dimen name="enable_step_text_size">26sp</dimen>
+ <dimen name="enable_step_line_margin_top">35dip</dimen>
+ <dimen name="enable_step_line_gap">32dip</dimen>
+ <dimen name="enable_step_words_margin_left">20dip</dimen>
+ <dimen name="enable_step_middle_width">668dip</dimen>
+ <dimen name="enable_step_middle_height">660dip</dimen>
+ <dimen name="enable_auth_btn_margin_top">520dip</dimen>
+ <dimen name="enable_auth_text_margin_top">360dip</dimen>
+ <!--设置通讯参数界面-->
+ <dimen name="set_server_line_height">120dip</dimen>
+ <dimen name="set_server_middle_width">600dip</dimen>
+ <dimen name="set_server_middle_height">570dip</dimen>
+ <dimen name="set_server_btn_width">150dip</dimen>
+ <dimen name="set_server_btn_height">60dip</dimen>
+ <dimen name="set_server_btns_text_size">22sp</dimen>
+ <dimen name="set_server_btn_margin_right">100dip</dimen>
+ <!--所有界面的返回按钮-->
+ <dimen name="all_back_line_height">72dip</dimen>
+ <dimen name="all_back_img_size">45dip</dimen>
+ <dimen name="all_back_word_width">115dip</dimen>
+ <dimen name="all_back_word_height">58dip</dimen>
+ <dimen name="all_back_word_margin_left">5dip</dimen>
+ <dimen name="all_back_words_size">30sp</dimen>
+ <dimen name="all_back_img_padtop">60dp</dimen>
+ <dimen name="all_back_img_padleft">20dp</dimen>
+ <!--本地控制参数-->
+ <dimen name="control_para_gap">10dp</dimen>
+ <dimen name="control_para_text_size">28dp</dimen>
+ <!--行间间隔-->
+ <dimen name="line_divide">20dp</dimen>
+ <!--点餐上-->
+ <dimen name="order_picture_section_line_height">252dip</dimen>
+ <dimen name="order_picture_out_width">184dip</dimen>
+ <dimen name="order_picture_inner_width">183dip</dimen>
+ <dimen name="order_picture_inner_height">196dip</dimen>
+ <dimen name="order_picture_simple_inner_width">252dip</dimen>
+ <dimen name="order_picture_simple_inner_height18">135dip</dimen>
+ <dimen name="order_picture_simple_inner_height21">115dip</dimen>
+ <dimen name="order_picture_simple_inner_height24">100dip</dimen>
+ <dimen name="order_picture_simple_inner_height27">90dip</dimen>
+ <dimen name="order_picture_simple_inner_height30">80dip</dimen>
+ <dimen name="order_picture_inner_margin">5dip</dimen>
+ <dimen name="order_picture_out_margin">2dip</dimen>
+ <dimen name="order_picture_price_margin_left">5dip</dimen>
+ <dimen name="order_picture_price_left_width">100dip</dimen>
+ <dimen name="order_picture_big_price_text_size">40sp</dimen>
+ <dimen name="order_picture_price_text_size">28sp</dimen>
+ <dimen name="order_picture_dec_text_size">20sp</dimen>
+ <dimen name="order_zoom_btn_width">57dip</dimen>
+ <dimen name="order_zoom_btn_height">67dip</dimen>
+ <dimen name="order_picture_count_text_size">28sp</dimen>
+ <dimen name="order_picture_section_height">830dip</dimen>
+ <dimen name="order_picture_food_name_height">57dip</dimen>
+ <dimen name="order_order_num_control_btn_size">55dip</dimen>
+ <dimen name="order_purchase_count_margin">10dip</dimen>
+ <dimen name="order_picture_text_si">10dip</dimen>
+ <!--点餐下-->
+ <dimen name="order_food_count_pack_margin_left">20dip</dimen>
+ <dimen name="order_food_name_margin_left">5dip</dimen>
+ <dimen name="order_down_height">200dip</dimen>
+ <dimen name="order_food_name_width">150dip</dimen>
+ <dimen name="order_food_count_width">50dip</dimen>
+ <dimen name="order_food_count_pack_width">170dip</dimen>
+ <dimen name="order_down_btn_text">45sp</dimen>
+ <dimen name="order_down_btn_margin_top">45dip</dimen>
+ <dimen name="order_down_gap">10dip</dimen>
+ <dimen name="order_down_left_width">324dip</dimen>
+ <dimen name="order_list_item_text_size">24sp</dimen>
+ <dimen name="order_total_price_text_size">48sp</dimen>
+ <dimen name="order_clear_btn_width">132dip</dimen>
+ <dimen name="order_clear_btn_height">100dip</dimen>
+ <dimen name="order_purchase_btn_width">216dip</dimen>
+ <dimen name="order_list_item_height">38dip</dimen>
+ <dimen name="order_purchase_btn_height">100dip</dimen>
+ <dimen name="order_total_price_margin_top">20dip</dimen>
+ <dimen name="order_picture_text_size1">30dip</dimen>
+ <dimen name="order_picture_text_size2">35dip</dimen>
+ <dimen name="order_picture_text_size3">40dip</dimen>
+ <!--点餐等待-->
+ <dimen name="order_purchase_star_gap">20dip</dimen>
+ <dimen name="order_purchase_title_height">100dip</dimen>
+ <dimen name="order_purchase_star_height">100dip</dimen>
+ <dimen name="order_wait_purchase_width">650dip</dimen>
+ <dimen name="order_wait_purchase_height">500dip</dimen>
+ <!--普通消费弹窗-->
+ <dimen name="ordinary_consume_home_width">600dip</dimen>
+ <dimen name="ordinary_consume_home_height">450dip</dimen>
+ <dimen name="ordinary_consume_text_size">40sp</dimen>
+ <dimen name="ordinary_consume_uint_size">30dp</dimen>
+ <!--点餐大图-->
+ <dimen name="order_big_picture_price_margin_left">25dip</dimen>
+ <dimen name="order_big_picture_margin_top">70dip</dimen>
+ <dimen name="order_add_food_btn_size">60dip</dimen>
+ <dimen name="order_big_picture_out_width">670dip</dimen>
+ <dimen name="order_big_picture_out_height">562dip</dimen>
+ <dimen name="order_big_picture_inner_width">654dip</dimen>
+ <dimen name="order_big_picture_inner_height">457dip</dimen>
+ <dimen name="order_big_picture_inner_margin">8dip</dimen>
+ <dimen name="order_big_picture_text">50sp</dimen>
+ <dimen name="order_big_picture_food_info_height">119dip</dimen>
+ <dimen name="order_big_picture_food_info_height_half">59dip</dimen>
+ <dimen name="order_big_picture_close_btn_size">75dip</dimen>
+ <dimen name="order_big_picture_confirm_btn_width">200dip</dimen>
+ <dimen name="order_big_picture_confirm_btn_height">75dip</dimen>
+ <dimen name="order_big_picture_confirm_btn_margin_left">170dip</dimen>
+ <dimen name="order_big_picture_count_width">140dip</dimen>
+ <dimen name="order_big_picture_count_height">70dip</dimen>
+ <dimen name="order_big_picture_price_width">200dip</dimen>
+ <dimen name="order_big_picture_dec_margin_left">150dip</dimen>
+ <dimen name="order_picture_history_text_size">12sp</dimen>
+ <dimen name="order_picture_minus_height">43dip</dimen>
+ <dimen name="order_picture_minus_width">80dip</dimen>
+ <dimen name="order_picture_minus_margin_right">6dip</dimen>
+ <dimen name="main_bottom_button_width">381dip</dimen>
+ <!--悬浮密码界面-->
+ <dimen name="float_password_margin_horizontal">5dip</dimen>
+ <dimen name="float_password_margin_vertical">1dip</dimen>
+ <dimen name="float_password_left_width">160dip</dimen>
+ <dimen name="float_password_left_obj_gap">5dip</dimen>
+ <dimen name="float_password_left_word_margin_top">25dip</dimen>
+ <dimen name="float_password_hint_size">35sp</dimen>
+ <dimen name="float_password_char_size">40sp</dimen>
+ <dimen name="float_password_pwd_char_margin_top">-7dip</dimen>
+ <!--悬浮密码界面下-->
+ <dimen name="float_password_right_btn_margin">20dip</dimen>
+ <dimen name="float_password_right_margin_left">25dip</dimen>
+ <dimen name="float_password_pwd_size">70dip</dimen>
+ <dimen name="float_password_pwd_inner_size">70dip</dimen>
+ <dimen name="float_password_pwd_inner_length">2dip</dimen>
+ <dimen name="float_password_btn_size">100dip</dimen>
+ <dimen name="float_password_right_margin_top">15dip</dimen>
+ <!--充值界面-->
+ <dimen name="deposit_userinfo_gap">20dp</dimen>
+ <dimen name="deposit_text_gap">15dp</dimen>
+ <dimen name="deposit_text_size">30sp</dimen>
+ <dimen name="deposit_item_size">20sp</dimen>
+ <dimen name="deposit_bg_crash_width">200dp</dimen>
+ <dimen name="deposit_bg_crash_height">80dp</dimen>
+ <dimen name="deposit_crash_size">50dp</dimen>
+ <dimen name="deposit_dialog_width">300dp</dimen>
+ <dimen name="deposit_dialog_size">40dp</dimen>
+ <dimen name="deposit_shopname_text_size_small">28sp</dimen>
+ <dimen name="deposit_shopname_text_size_normal">35sp</dimen>
+ <!--支付界面-->
+ <dimen name="pay_text_pad_size">10dp</dimen>
+ <dimen name="pay_text_marginleft">30dp</dimen>
+ <dimen name="pay_module_top_size">10dp</dimen>
+ <dimen name="pay_text_size">35sp</dimen>
+ <dimen name="pay_text_title_size">25sp</dimen>
+ <!--待机界面-->
+ <dimen name="consume_text_pad_size">10dp</dimen>
+ <dimen name="consume_text_size">25sp</dimen>
+ <dimen name="consume_text_size1">30sp</dimen>
+ <dimen name="consume_text_size2">30sp</dimen>
+ <dimen name="consume_text_pad_size1">5dp</dimen>
+ <dimen name="consume_shopname_text_size_middle">28sp</dimen>
+ <dimen name="consume_shopname_text_size_normal">35sp</dimen>
+</resources>
diff --git a/app/src/main/res/values/ids.xml b/app/src/main/res/values/ids.xml
new file mode 100644
index 0000000..056a511
--- /dev/null
+++ b/app/src/main/res/values/ids.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?><!--
+ Copyright (C) 2008 ZXing authors
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<resources>
+ <!-- Messages IDs -->
+ <item name="auto_focus" type="id" />
+ <item name="decode" type="id" />
+ <item name="decode_failed" type="id" />
+ <item name="jump_to_read_card" type="id" />
+ <item name="decode_succeeded" type="id" />
+ <item name="encode_failed" type="id" />
+ <item name="encode_succeeded" type="id" />
+ <item name="launch_product_query" type="id" />
+ <item name="quit" type="id" />
+ <item name="restart_preview" type="id" />
+ <item name="return_scan_result" type="id" />
+ <item name="search_book_contents_failed" type="id" />
+ <item name="search_book_contents_succeeded" type="id" />
+
+
+ <item name="gridview" type="id" />
+ <item name="webview" type="id" />
+
+ <item name="about_version_code" type="id" />
+ <item name="split" type="id" />
+
+</resources>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..c26513d
--- /dev/null
+++ b/app/src/main/res/values/strings.xml
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="app_name">消费POS机</string>
+ <string name="title_activity_base">基类</string>
+ <string name="action_settings">设置</string>
+ <string name="title_activity_main">主界面</string>
+ <string name="title_activity_psam">操作psam卡</string>
+ <string name="title_activity_readcard">读卡</string>
+ <string name="title_activity_mode">模式</string>
+ <string name="title_activity_init">初始化</string>
+ <string name="title_activity_load">加载</string>
+ <string name="title_activity_comm">通讯</string>
+ <string name="title_activity_control">控制参数</string>
+ <string name="title_activity_consumecancel">消费撤销</string>
+ <string name="title_activity_library">图书缴费</string>
+ <string name="title_activity_recharge">在线充值</string>
+ <string name="cardlib_name">supwisdom.kscpucard</string>
+ <string name="connfail">连接失败</string>
+ <string name="msg_read_card_error">读卡错误</string>
+ <string name="msg_notsupport_card_oper">不支持卡操作</string>
+ <string name="msg_card_data_error">卡数据错误</string>
+ <string name="nfc_not_support">不支持NFC</string>
+ <string name="nfc_disabled">NFC未启动</string>
+ <string name="confirm_open_nfc">是否打开NFC</string>
+ <string name="action_exit">退出</string>
+ <string name="wait_msg">请刷卡</string>
+ <string name="menu_name_set">设置</string>
+ <string name="menu_name_purchase">消费</string>
+ <string name="title_activity_set">设置</string>
+ <string name="hello_world">hello</string>
+ <string name="devtimefmt">yyyyMMddHHmmss</string>
+ <string name="title_activity_transdtl">交易流水查询</string>
+ <string name="no_mf_files">\"无MF文件\"</string>
+ <string name="creat_mf_files">创建MF文件</string>
+ <string name="creat_mf_success">创建MF文件成功</string>
+ <string name="creat_mf_fail">创建MF文件失败</string>
+ <string name="mf_exist">MF退出</string>
+ <string name="error">错误</string>
+ <string name="reset_psam1_success">重设PSAM1成功</string>
+ <string name="reset_psam1_failed">重设psam1失败</string>
+ <string name="reset_psam2_success">重设psam2成功</string>
+ <string name="reset_psam2_failed">重设psam2失败</string>
+ <string name="get_random_number_failed">获取随机数失败</string>
+ <string name="reset_import1">初始化1失败</string>
+ <string name="reset_failed_cannot_get_random_number1">不能获取随机数1</string>
+ <string name="reset_import2">重设2失败</string>
+ <string name="reset_failed_cannot_get_random_number2">获取随机数2失败</string>
+ <string name="title_activity_show_day_consume">营业额查询</string>
+ <string name="title_activity_password">密码设置</string>
+ <string name="isPasswordCancel">isPassWordCancel</string>
+ <string name="consume_img">消费</string>
+ <string name="title_activity_auth">签到</string>
+ <string name="action_saoma">扫码</string>
+ <string name="scan_text">将二维码或条码放入框内完成扫描</string>
+ <string name="home_back">返回</string>
+ <string name="title_activity_consume">普通消费</string>
+ <string name="title_activity_qrcamera">扫码</string>
+ <string name="title_activity_splash">树维pos</string>
+ <string name="waiting_msg">正在识别,请稍后…</string>
+ <string name="username">姓 名</string>
+ <string name="userStuEmpNo">学工号</string>
+ <string name="userExpireDate">有效期</string>
+ <string name="userBalance">余 额</string>
+ <string name="consumeAmount">消费额(元)</string>
+ <string name="title_activity_consume_cancel">消费撤销</string>
+ <string name="title_activity_update_blacklist">更新黑名单</string>
+ <string name="title_activity_recover_factory">恢复出厂</string>
+ <string name="dialogTitle">提示</string>
+ <string name="all_home_words">主页</string>
+ <string name="all_back_words">返回</string>
+ <string name="title_activity_order_online">在线点餐</string>
+ <string name="title_activity_query_parameter_second">查询第二页</string>
+ <string name="devphyid">终端机编号</string>
+ <string name="samNo">SAM卡号</string>
+ <string name="softVerNo">软件版本号</string>
+ <string name="feerateVerNo">收费参数版本号</string>
+ <string name="sysparaVerNo">主参数版本号</string>
+ <string name="cardverno">黑名单参数版本号</string>
+ <string name="devseqno">POS当前流水号</string>
+ <string name="opentime">开机时间</string>
+ <string name="nextPage">下一页</string>
+ <string name="queryParameters">终端参数查询</string>
+ <string name="title_activity_change_mode">更改模式</string>
+ <string name="title_activity_enable">设备启用</string>
+ <string name="offline_words">脱机状态</string>
+ <string name="online_words">联机状态</string>
+ <string name="title_activity_set_server_info">设置通讯参数</string>
+ <string name="title_activity_test_touch">TestTouchActivity</string>
+ <string name="wait_put_card_words"><![CDATA[请刷卡 >>]]></string>
+ <string name="title_activity_hotel">酒店消费</string>
+ <string name="title_activity_manage">设备管理</string>
+ <string name="title_activity_revenue">营业额</string>
+ <string name="title_activity_pay">支付</string>
+ <string name="title_activity_modifypwd">修改密码</string>
+ <string name="title_activity_syspara">系统参数</string>
+ <string name="title_activity_department">部门限制</string>
+ <string name="title_activity_sddtl">SD卡流水</string>
+ <string name="title_activity_cardlib">卡库</string>
+ <string name="title_activity_upgrade">本地升级</string>
+ <!--消费菜单-->
+ <string name="consume_menu_revenue">1-营业额</string>
+ <string name="consume_menu_transdtl_upload">2-上传流水</string>
+ <string name="consume_menu_link_check">3-链路检测</string>
+ <string name="consume_menu_auth">4-手工签到</string>
+ <string name="consume_menu_syspara_query">5-参数查询</string>
+ <string name="consume_menu_manage">6-管理功能</string>
+ <string name="consume_menu_shop_password_set">7-商户密码</string>
+ <string name="consume_menu_consume_mode">8-消费模式</string>
+ <string name="consume_menu_reverse">9-手工冲正</string>
+ <!--消费维护菜单-->
+ <string name="consume_menu_shop_passwd">1-查看商户密码</string>
+ <string name="consume_menu_comm_set">2-通讯参数设置</string>
+ <string name="consume_menu_unconfirm_transdtl">3-查询未上传流水</string>
+ <string name="consume_menu_out_dtl">4-导出本地流水</string>
+ <string name="consume_menu_upgrade">5-软件在线升级</string>
+ <string name="consume_menu_app_exit">6-退出应用程序</string>
+ <string name="consume_menu_setting">7-进入设置界面</string>
+ <string name="consume_menu_clear_blklist">8-清空黑名单</string>
+ <string name="consume_menu_control_set">9-本地参数设置</string>
+ <!--充值菜单-->
+ <string name="deposit_menu_revenue">1-营业额查询</string>
+ <string name="deposit_menu_login_out">2-退出登录</string>
+ <string name="deposit_menu_reverse">3-手工冲正</string>
+ <string name="deposit_menu_param_query">4-参数查询</string>
+ <string name="deposit_menu_param_manage">5-设备管理</string>
+ <string name="deposit_menu_param_link">6-链路检测</string>
+ <!--充值维护菜单-->
+ <string name="deposit_manage_transdtl_clear">1-清空流水</string>
+ <string name="deposit_manage_comm_set">2-参数设置</string>
+ <string name="deposit_manage_upgrade">3-在线升级</string>
+ <string name="deposit_manage_app_exit">4-退出应用</string>
+ <string name="deposit_manage_setting">5-网络设置</string>
+ <!--充值参数-->
+ <string name="deposit_param_opername">操作员</string>
+</resources>
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..d16cba1
--- /dev/null
+++ b/app/src/main/res/values/styles.xml
@@ -0,0 +1,511 @@
+<resources>
+
+ <!-- Base application theme. -->
+ <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
+ <!-- Customize your theme here. -->
+ </style>
+
+ <style name="FloatingDialog" parent="@android:style/Theme.Dialog">
+ <item name="android:windowFrame">@null</item>
+ <item name="android:windowIsFloating">true</item>
+ <item name="android:windowContentOverlay">@null</item>
+ <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
+ <item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item>
+ <item name="android:windowBackground">@android:color/transparent</item>
+ <item name="android:background">@android:color/transparent</item>
+ <item name="android:windowNoTitle">true</item>
+ <item name="android:windowCloseOnTouchOutside">false</item>
+ <item name="android:windowIsTranslucent">true</item>
+ </style>
+
+ <style name="CustomDialog" parent="@android:style/Theme.Dialog">
+ <item name="android:windowFrame">@null</item>
+ <item name="android:windowIsFloating">true</item>
+ <item name="android:windowContentOverlay">@null</item>
+ <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
+ <item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item>
+ <item name="android:windowBackground">@android:color/transparent</item>
+ <item name="android:windowNoTitle">true</item>
+ <item name="android:windowCloseOnTouchOutside">false</item>
+ <item name="android:windowIsTranslucent">true</item>
+ </style>
+
+ <style name="CustomProgressDialog" parent="@style/CustomDialog">
+ <item name="android:windowBackground">@android:color/transparent</item>
+ <item name="android:windowNoTitle">true</item>
+ </style>
+
+ <style name="myProgressBarStyleSmal">
+ <item name="android:indeterminateDrawable">@drawable/progress_bg</item>
+ <item name="android:minWidth">100dip</item>
+ <item name="android:maxWidth">100dip</item>
+ <item name="android:minHeight">100dip</item>
+ <item name="android:maxHeight">100dip</item>
+ </style>
+
+ <style name="myProgressBarStyleLarge">
+ <item name="android:indeterminateDrawable">@drawable/big_progress_bg</item>
+ <item name="android:width">200dp</item>
+ <item name="android:height">200dp</item>
+ </style>
+
+ <style name="PayDialog" parent="@android:style/Theme.Dialog">
+ <item name="android:windowFrame">@null</item>
+ <item name="android:windowIsFloating">true</item>
+ <item name="android:windowContentOverlay">@null</item>
+ <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
+ <item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item>
+ <item name="android:windowBackground">@android:color/transparent</item>
+ <item name="android:background">@android:color/transparent</item>
+ <item name="android:windowNoTitle">true</item>
+ <item name="android:windowCloseOnTouchOutside">false</item>
+ <item name="android:windowIsTranslucent">true</item>
+ <item name="android:windowNoDisplay">true</item>
+ </style>
+
+ <style name="OtherDialog" parent="@android:style/Theme.Dialog">
+ <item name="android:windowFrame">@null</item>
+ <item name="android:windowIsFloating">true</item>
+ <item name="android:windowContentOverlay">@null</item>
+ <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
+ <item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item>
+ <item name="android:windowBackground">@android:color/transparent</item>
+ <item name="android:background">@android:color/transparent</item>
+ <item name="android:windowNoTitle">true</item>
+ <item name="android:windowCloseOnTouchOutside">false</item>
+ <item name="android:windowIsTranslucent">false</item>
+ </style>
+ <!--activity_deposit-->
+ <style name="deposit_user_info_layout_style">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:orientation">horizontal</item>
+ <item name="android:padding">5dp</item>
+ </style>
+
+ <style name="deposit_user_info_name_style">
+ <item name="android:textSize">@dimen/deposit_text_size</item>
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:textColor">@color/black</item>
+ </style>
+
+ <style name="deposit_user_info_value_style">
+ <item name="android:textSize">@dimen/deposit_text_size</item>
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:textColor">@color/blue</item>
+ <item name="android:textStyle">bold</item>
+ <item name="android:maxLines">1</item>
+ </style>
+
+ <style name="deposit_result_layout_style">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:orientation">horizontal</item>
+ <item name="android:paddingLeft">10dp</item>
+ <item name="android:paddingTop">5dp</item>
+ </style>
+
+ <style name="deposit_result_name_style">
+ <item name="android:textSize">@dimen/deposit_text_size</item>
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">match_parent</item>
+ <item name="android:textColor">@color/black</item>
+ <item name="android:maxLines">1</item>
+ </style>
+
+ <style name="deposit_result_value_style">
+ <item name="android:textSize">@dimen/deposit_text_size</item>
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:textColor">@color/blue</item>
+ <item name="android:textStyle">bold</item>
+ <item name="android:maxLines">1</item>
+ </style>
+ <!--deposit revenue-->
+ <style name="deposit_revenue_statics_layout_style">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_marginTop">20dp</item>
+ <item name="android:orientation">horizontal</item>
+ <item name="android:weightSum">4</item>
+ </style>
+
+ <style name="deposit_revenue_statics_name_style">
+ <item name="android:layout_width">0dp</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_weight">1</item>
+ <item name="android:gravity">center</item>
+ <item name="android:textColor">@color/black</item>
+ <item name="android:textSize">20sp</item>
+ </style>
+
+ <style name="deposit_revenue_statics_value_style">
+ <item name="android:layout_width">0dp</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_weight">1</item>
+ <item name="android:gravity">center</item>
+ <item name="android:textColor">@color/black</item>
+ <item name="android:textSize">20sp</item>
+ </style>
+
+ <style name="deposit_revenue_detail_style">
+ <item name="android:textSize">25sp</item>
+ <item name="android:layout_width">0dp</item>
+ <item name="android:layout_weight">1</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:textColor">@color/black</item>
+ <item name="android:maxLines">1</item>
+ </style>
+
+ <style name="deposit_revenue_date_style">
+ <item name="android:textSize">@dimen/revenue_serch_text_size</item>
+ <item name="android:layout_width">0dp</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:gravity">center</item>
+ <item name="android:layout_weight">1</item>
+ <item name="android:textColor">@color/light_blue2</item>
+ <item name="android:textStyle">bold</item>
+ <item name="android:maxLines">1</item>
+ <item name="android:padding">5dp</item>
+ </style>
+
+ <style name="deposit_revenue_dtl_style">
+ <item name="android:layout_width">0dp</item>
+ <item name="android:layout_weight">1</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:maxLines">1</item>
+ <item name="android:textColor">@color/black</item>
+ <item name="android:textSize">20sp</item>
+ </style>
+
+ <style name="init_param_title_btn_name_style">
+ <item name="android:layout_width">0dp</item>
+ <item name="android:layout_weight">1</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_marginTop">10dp</item>
+ <item name="android:gravity">center</item>
+ <item name="android:textColor">@color/light_blue2</item>
+ <item name="android:textSize">28sp</item>
+ </style>
+
+ <style name="init_param_name_style">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_marginTop">10dp</item>
+ <item name="android:gravity">start|center</item>
+ <item name="android:textColor">@color/light_blue2</item>
+ <item name="android:textSize">28sp</item>
+ </style>
+
+ <style name="init_param_mode_style">
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">match_parent</item>
+ <item name="android:textColor">@color/light_blue2</item>
+ <item name="android:textSize">@dimen/enable_devphyid_font_size</item>
+ </style>
+
+ <style name="deposit_dialog_result_name_style">
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:textColor">@color/black</item>
+ <item name="android:textSize">40sp</item>
+ </style>
+
+ <style name="deposit_dialog_result_unit_style">
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:textColor">@color/black</item>
+ <item name="android:textSize">30sp</item>
+ <item name="android:text">" 元"</item>
+ </style>
+
+ <style name="deposit_menu_text_style">
+ <item name="android:textSize">30sp</item>
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:textColor">@color/light_blue2</item>
+ </style>
+
+ <style name="deposit_param_ll_style">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:weightSum">3</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_marginTop">10dp</item>
+ <item name="android:padding">10dp</item>
+ <item name="android:orientation">horizontal</item>
+ </style>
+
+ <style name="deposit_param_text_name_style">
+ <item name="android:layout_width">0dp</item>
+ <item name="android:layout_weight">1</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:textColor">@color/light_blue2</item>
+ <item name="android:textSize">30sp</item>
+ </style>
+
+ <style name="deposit_param_text_value_style">
+ <item name="android:layout_width">0dp</item>
+ <item name="android:layout_weight">1</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:textColor">@color/light_blue2</item>
+ <item name="android:textSize">30sp</item>
+ </style>
+
+ <style name="head_title_text_style">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:gravity">center</item>
+ <item name="android:padding">20dp</item>
+ <item name="android:textColor">@color/light_blue2</item>
+ <item name="android:textSize">50sp</item>
+ </style>
+
+ <style name="head_title_inner_style">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">match_parent</item>
+ <item name="android:layout_margin">20dp</item>
+ <item name="android:background">@drawable/corner_bg_white</item>
+ <item name="android:orientation">vertical</item>
+ </style>
+
+ <style name="head_title_out_style">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">match_parent</item>
+ <item name="android:background">@color/light_blue2</item>
+ <item name="android:orientation">vertical</item>
+ </style>
+ <!--菜单项-->
+ <style name="menu_item_text_style">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:textSize">30sp</item>
+ <item name="android:textColor">@color/light_blue2</item>
+ <item name="android:paddingLeft">5dp</item>
+ <item name="android:paddingTop">5dp</item>
+ </style>
+ <!--参数查询-->
+ <style name="syspara_item_text_ll_sytle">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:orientation">horizontal</item>
+ <item name="android:padding">10dp</item>
+ <item name="android:weightSum">2</item>
+ </style>
+
+ <style name="syspara_item_text_name_sytle">
+ <item name="android:layout_width">0dp</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_weight">1</item>
+ <item name="android:textColor">@color/light_blue2</item>
+ <item name="android:textSize">30sp</item>
+ </style>
+
+ <style name="param_set_item_radio_style">
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:textColor">@color/light_blue2</item>
+ <item name="android:textSize">30sp</item>
+ <item name="android:paddingTop">5dp</item>
+ <item name="android:paddingLeft">5dp</item>
+ </style>
+
+ <style name="param_item_text_btn_style">
+ <item name="android:layout_width">0dp</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_weight">1</item>
+ <item name="android:background">@drawable/select_bg_keyboard</item>
+ <item name="android:gravity">center</item>
+ <item name="android:padding">10dp</item>
+ <item name="android:textColor">@color/white</item>
+ <item name="android:textSize">@dimen/enable_devphyid_font_size</item>
+ </style>
+
+ <style name="load_info_text_style">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:gravity">start</item>
+ <item name="android:padding">10dp</item>
+ <item name="android:textColor">@color/light_blue2</item>
+ <item name="android:textSize">@dimen/enable_step_text_size</item>
+ </style>
+
+ <style name="control_item_ll_style">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_gravity">center_horizontal</item>
+ <item name="android:layout_marginLeft">10dp</item>
+ <item name="android:layout_marginTop">@dimen/control_para_gap</item>
+ <item name="android:orientation">vertical</item>
+ </style>
+
+ <style name="control_item_text_style">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:gravity">start|center</item>
+ <item name="android:textColor">@color/enable_text_font_color</item>
+ <item name="android:textSize">@dimen/control_para_text_size</item>
+ </style>
+
+ <style name="control_text_btn_style">
+ <item name="android:layout_width">0dp</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_weight">1</item>
+ <item name="android:layout_marginLeft">20dp</item>
+ <item name="android:layout_marginRight">20dp</item>
+ <item name="android:gravity">center</item>
+ <item name="android:padding">10dp</item>
+ <item name="android:background">@drawable/select_bg_keyboard</item>
+ <item name="android:textColor">@color/light_blue2</item>
+ <item name="android:textSize">35sp</item>
+ </style>
+
+ <style name="gate_content_text_style">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:gravity">center</item>
+ <item name="android:layout_height">0dp</item>
+ <item name="android:layout_weight">1</item>
+ <item name="android:padding">@dimen/consume_text_pad_size</item>
+ <item name="android:textSize">90sp</item>
+ <item name="android:textStyle">bold</item>
+ <item name="android:textColor">@color/orange1</item>
+ </style>
+
+ <style name="gate_dialog_result_text_style">
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_marginTop">10dp</item>
+ <item name="android:maxLines">1</item>
+ <item name="android:textSize">@dimen/ordinary_consume_text_size</item>
+ <item name="android:textStyle">bold</item>
+ <item name="android:textColor">@color/orange1</item>
+ </style>
+
+ <style name="consume_wait_account_ll_style">
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:orientation">horizontal</item>
+ <item name="android:padding">@dimen/consume_text_pad_size1</item>
+ </style>
+
+ <style name="consume_wait_account_paraname_style">
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:textColor">@color/black</item>
+ <item name="android:textSize">@dimen/consume_text_size2</item>
+ </style>
+
+ <style name="consume_wait_account_paraval_style">
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:textColor">@color/blue</item>
+ <item name="android:textSize">@dimen/consume_text_size2</item>
+ <item name="android:maxLines">1</item>
+ <item name="android:textStyle">bold</item>
+ </style>
+
+ <style name="consume_wait_account_spec_paraval_style">
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_width">0dp</item>
+ <item name="android:ellipsize">end</item>
+ <item name="android:layout_weight">1</item>
+ <item name="android:textColor">@color/blue</item>
+ <item name="android:textSize">@dimen/consume_text_size2</item>
+ <item name="android:maxLines">1</item>
+ <item name="android:textStyle">bold</item>
+ </style>
+
+ <style name="consume_pay_way_hint_style">
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_marginTop">50dp</item>
+ <item name="android:textSize">25sp</item>
+ <item name="android:textStyle">bold</item>
+ <item name="android:textColor">@color/black</item>
+ <item name="android:gravity">center</item>
+ </style>
+
+ <style name="consume_pay_way_text_style">
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_marginLeft">20dp</item>
+ <item name="android:layout_marginTop">60dp</item>
+ <item name="android:layout_marginRight">20dp</item>
+ <item name="android:background">@drawable/corner_bg_qrcode_hint</item>
+ <item name="android:gravity">center</item>
+ <item name="android:padding">5dp</item>
+ <item name="android:textColor">@color/white</item>
+ <item name="android:textSize">30sp</item>
+ <item name="android:textStyle">bold</item>
+ </style>
+
+ <style name="consume_pay_way_layout_style">
+ <item name="android:layout_height">380dp</item>
+ <item name="android:layout_marginLeft">20dp</item>
+ <item name="android:layout_marginRight">20dp</item>
+ <item name="android:layout_marginTop">20dp</item>
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:orientation">horizontal</item>
+ <item name="android:background">@drawable/corner_bg_white</item>
+ </style>
+
+ <style name="consume_pay_default_photo_style">
+ <item name="android:layout_width">300dp</item>
+ <item name="android:layout_height">300dp</item>
+ <item name="android:layout_gravity">center</item>
+ <item name="android:scaleType">fitXY</item>
+ </style>
+
+ <style name="activity_pay_out_ll_style">
+ <item name="android:layout_height">match_parent</item>
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:background">@color/light_blue2</item>
+ <item name="android:orientation">vertical</item>
+ </style>
+
+ <style name="upgrade_text_desc_style">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:padding">10dp</item>
+ <item name="android:textColor">@color/black</item>
+ <item name="android:textSize">30sp</item>
+ <item name="android:maxLines">1</item>
+ </style>
+
+ <style name="upgrade_text_value_style">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_marginLeft">10dp</item>
+ <item name="android:textColor">@color/light_blue2</item>
+ <item name="android:textSize">30sp</item>
+ <item name="android:maxLines">1</item>
+ </style>
+ <style name="comm_rb_para_style">
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">match_parent</item>
+ <item name="android:gravity">center|start</item>
+ <item name="android:textColor">@color/light_blue2</item>
+ <item name="android:textSize">28sp</item>
+ </style>
+ <style name="comm_ll_para_style">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:orientation">vertical</item>
+ <item name="android:layout_marginLeft">10dp</item>
+ <item name="android:padding">10dp</item>
+ </style>
+ <style name="purchase_ll_text_style">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_marginLeft">80dp</item>
+ <item name="android:layout_marginTop">10dp</item>
+ <item name="android:orientation">vertical</item>
+ </style>
+ <style name="purchase_tv_text_hint_style">
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:textSize">50sp</item>
+ <item name="android:textStyle">bold</item>
+ </style>
+</resources>
diff --git a/app/src/test/java/com/supwisdom/ExampleUnitTest.kt b/app/src/test/java/com/supwisdom/ExampleUnitTest.kt
new file mode 100644
index 0000000..f32e492
--- /dev/null
+++ b/app/src/test/java/com/supwisdom/ExampleUnitTest.kt
@@ -0,0 +1,17 @@
+package com.supwisdom
+
+import org.junit.Test
+
+import org.junit.Assert.*
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+class ExampleUnitTest {
+ @Test
+ fun addition_isCorrect() {
+ assertEquals(4, 2 + 2)
+ }
+}
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..3b61f16
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,28 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+ ext.kotlin_version = '1.3.31'
+ repositories {
+ google()
+ jcenter()
+
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:3.4.0'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ jcenter()
+
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..85be9ea
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,15 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx1536m
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# Kotlin code style for this project: "official" or "obsolete":
+kotlin.code.style=official
diff --git a/gradlew b/gradlew
new file mode 100644
index 0000000..cccdd3d
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..f955316
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/keys-app.jks b/keys-app.jks
new file mode 100644
index 0000000..3331a8b
--- /dev/null
+++ b/keys-app.jks
Binary files differ
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..e7b4def
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1 @@
+include ':app'
diff --git a/upgrade.py b/upgrade.py
new file mode 100644
index 0000000..8de756f
--- /dev/null
+++ b/upgrade.py
@@ -0,0 +1,48 @@
+#coding=utf-8
+#使用python做升级文件打包
+
+import hashlib
+import sys
+import zipfile
+from os import path
+import subprocess
+
+hashFileName = 'hash256.sign'
+
+
+def sha256_checknum(apk):
+ hash256 = hashlib.sha256()
+ srcFile = open(apk,'rb')
+ with srcFile as f:
+ for block in iter(lambda:f.read(4096),b''):
+ hash256.update(block);
+ srcFile.close()
+ hash256.update(b'nzoqPYMIu91VViA/mEIG5FtJXi8=')
+
+ hashFile = path.dirname(apk)+'/'+hashFileName
+ print('hashFile = '+hashFile)
+ destFile = open(hashFile,'w+')
+ destFile.write(hash256.hexdigest())
+ destFile.close()
+
+def zip_file(apk):
+ fileDir = path.dirname(apk)
+ version = subprocess.check_output(['git', 'describe', '--abbrev=4','--dirty','--always','--tags']).strip().decode('utf-8')
+ zipFile = fileDir+'/posa711'+'-'+version+'.zip'
+ print('zipFile = '+zipFile)
+
+ zf = zipfile.ZipFile(zipFile,'w',zipfile.ZIP_DEFLATED)
+ zf.write(fileDir+'/'+hashFileName,hashFileName)
+ zf.write(apk,'posa711.apk')
+ zf.close()
+
+if __name__ == '__main__':
+ appFile = './app/release/app-release.apk'
+ print('appFile = ' + appFile)
+
+ if not path.exists(appFile):
+ print(appFile +' is not exist')
+ exit()
+ sha256_checknum(appFile)
+ zip_file(appFile)
+ print('build upgrade zip success!')
\ No newline at end of file