Browse Source

集成家属探视机

weizhengliang 1 year ago
parent
commit
7023daaf6a
100 changed files with 7645 additions and 65 deletions
  1. 1 1
      android_mobile/build.gradle
  2. 0 64
      android_mobile/src/main/java/com/wdkl/ncs/android/component/home/util/HandleTcpConnect.kt.bak
  3. 1 0
      android_visiting/.gitignore
  4. 160 0
      android_visiting/build.gradle
  5. 25 0
      android_visiting/proguard-rules.pro
  6. 88 0
      android_visiting/src/main/AndroidManifest.xml
  7. BIN
      android_visiting/src/main/assets/wd_update_plugin.apk
  8. 246 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/activity/AppUpdateActivity.kt
  9. 263 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/activity/SystemActivity.kt
  10. 323 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/activity/TextActivity.kt
  11. 355 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/activity/VisitingActivationActivity.kt
  12. 618 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/activity/VisitingActivity.kt
  13. 56 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/adapter/NumAdapter.java
  14. 22 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/broadcast/WdBootReceiver.java
  15. 24 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/di/VisitingComponent.kt
  16. 138 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/fragment/BaseCallFragment.kt
  17. 512 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/fragment/SkyCallFragment.kt
  18. 62 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/hardware/HardTools.java
  19. 30 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/hardware/HardWareFactroy.java
  20. 140 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/hardware/imp/A133HardTools.java
  21. 79 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/hardware/imp/CommonHardTools.java
  22. 116 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/hardware/imp/Z3128HardTools.java
  23. 129 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/hardware/imp/ZKEHardTools.java
  24. 277 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/helper/AppUpdateHelper.java
  25. 161 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/helper/HttpHelper.java
  26. 92 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/helper/NetworkDialogHelper.java
  27. 61 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/helper/RebootDialogHelper.java
  28. 126 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/helper/RecordHelper.java
  29. 107 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/helper/ServicesDialogHelper.java
  30. 33 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/helper/StatusBarHelper.java
  31. 96 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/helper/SystemDialogHelper.java
  32. 70 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/helper/UpdataDialogHelper.java
  33. 101 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/helper/UpdateTipsDialogHelper.java
  34. 27 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/launch/VisitingLaunch.kt
  35. 100 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/service/TcpHandleService.kt
  36. 83 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/settingconfig/SettingConfig.java
  37. 236 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/util/AnrFcExceptionUtil.java.bak
  38. 147 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/util/AppUtils.java
  39. 90 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/util/CallDialogHelper.java
  40. 14 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/util/EthernetWifiCallBack.java
  41. 80 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/util/LocaleMangerUtils.java
  42. 283 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/util/MediaPlayHelper.java
  43. 115 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/util/MediaPlayer.kt
  44. 658 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/util/NetHelper.java
  45. 233 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/util/SPUtils.java
  46. 159 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/util/ServerConfigDialogHelper.java
  47. 84 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/util/SoundPoolManager.java
  48. 202 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/util/SpeechUtil.java
  49. 30 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/util/TimeTransition.kt
  50. 159 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/util/Util.kt
  51. 184 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/util/VoiceManagerUtil.java
  52. 238 0
      android_visiting/src/main/java/com/wdkl/ncs/android/component/home/util/XCrashUtils.java
  53. BIN
      android_visiting/src/main/res/drawable-hdpi/hu_jiao.png
  54. BIN
      android_visiting/src/main/res/drawable-hdpi/hu_jiao_bg.png
  55. BIN
      android_visiting/src/main/res/drawable-hdpi/wei_chu_li_bg.png
  56. BIN
      android_visiting/src/main/res/drawable-hdpi/yi_chu_li_bg.png
  57. BIN
      android_visiting/src/main/res/drawable-hdpi/yu_yin_wei_chu_li.png
  58. BIN
      android_visiting/src/main/res/drawable-mdpi/bao_ma_tou_xiang.png
  59. BIN
      android_visiting/src/main/res/drawable-mdpi/dian_liang.png
  60. BIN
      android_visiting/src/main/res/drawable-mdpi/geng_duo.png
  61. BIN
      android_visiting/src/main/res/drawable-mdpi/gu_ke_lie_biao.png
  62. BIN
      android_visiting/src/main/res/drawable-mdpi/hu_chu_wei_jie.png
  63. BIN
      android_visiting/src/main/res/drawable-mdpi/hu_chu_yi_jie.png
  64. BIN
      android_visiting/src/main/res/drawable-mdpi/hu_jiao.png
  65. BIN
      android_visiting/src/main/res/drawable-mdpi/hu_jiao_bg.png
  66. BIN
      android_visiting/src/main/res/drawable-mdpi/hu_ru_wei_jie.png
  67. BIN
      android_visiting/src/main/res/drawable-mdpi/hu_ru_yi_jie.png
  68. BIN
      android_visiting/src/main/res/drawable-mdpi/hu_shi_to_xiang.png
  69. BIN
      android_visiting/src/main/res/drawable-mdpi/ju_jie.png
  70. BIN
      android_visiting/src/main/res/drawable-mdpi/sip_lian_jie.png
  71. BIN
      android_visiting/src/main/res/drawable-mdpi/tong_hu_ji_lu.png
  72. BIN
      android_visiting/src/main/res/drawable-mdpi/wei_bo_fang.png
  73. BIN
      android_visiting/src/main/res/drawable-mdpi/wei_chu_li.png
  74. BIN
      android_visiting/src/main/res/drawable-mdpi/wei_chu_li_bg.png
  75. BIN
      android_visiting/src/main/res/drawable-mdpi/wifi_lian_jie.png
  76. BIN
      android_visiting/src/main/res/drawable-mdpi/yi_bo_fang.png
  77. BIN
      android_visiting/src/main/res/drawable-mdpi/yi_chu_li.png
  78. BIN
      android_visiting/src/main/res/drawable-mdpi/yi_chu_li_bg.png
  79. BIN
      android_visiting/src/main/res/drawable-mdpi/yu_yin_gua_duan.png
  80. BIN
      android_visiting/src/main/res/drawable-mdpi/yu_yin_jie_ting.png
  81. BIN
      android_visiting/src/main/res/drawable-mdpi/yu_yin_wei_chu_li.png
  82. BIN
      android_visiting/src/main/res/drawable-mdpi/zhe_die.png
  83. BIN
      android_visiting/src/main/res/drawable/av_handfree_hover.png
  84. BIN
      android_visiting/src/main/res/drawable/btn_back.png
  85. BIN
      android_visiting/src/main/res/drawable/ic_answer_normal.png
  86. BIN
      android_visiting/src/main/res/drawable/ic_answer_press.png
  87. BIN
      android_visiting/src/main/res/drawable/ic_hangup_normal.png
  88. BIN
      android_visiting/src/main/res/drawable/ic_hangup_press.png
  89. BIN
      android_visiting/src/main/res/drawable/ic_nurse.png
  90. BIN
      android_visiting/src/main/res/drawable/icon_hd_live.png
  91. BIN
      android_visiting/src/main/res/drawable/icon_hd_live_item.png
  92. BIN
      android_visiting/src/main/res/drawable/icon_switch_off.png
  93. BIN
      android_visiting/src/main/res/drawable/icon_switch_on.png
  94. 5 0
      android_visiting/src/main/res/drawable/item_selector.xml
  95. BIN
      android_visiting/src/main/res/drawable/main_bg.png
  96. BIN
      android_visiting/src/main/res/drawable/main_bg_1280x800.jpg
  97. BIN
      android_visiting/src/main/res/drawable/main_bg_1920x1080.jpg
  98. BIN
      android_visiting/src/main/res/drawable/main_bg_800x1280.png
  99. 6 0
      android_visiting/src/main/res/drawable/round_button_100dp.xml
  100. 0 0
      android_visiting/src/main/res/drawable/round_button_80dp.xml

+ 1 - 1
android_mobile/build.gradle

@@ -40,7 +40,7 @@ android {
     productFlavors {
         xiaomi {//自研
             dimension "app"
-            buildConfigField 'String', 'flag', '"8"'
+            buildConfigField 'String', 'flag', '"9"'
         }
     }
 

+ 0 - 64
android_mobile/src/main/java/com/wdkl/ncs/android/component/home/util/HandleTcpConnect.kt.bak

@@ -1,64 +0,0 @@
-package com.wdkl.ncs.android.component.home.util
-
-import android.annotation.SuppressLint
-import android.util.Log
-import com.wdkl.ncs.android.middleware.common.Constants
-import com.wdkl.ncs.android.lib.utils.showMessage
-import com.wdkl.ncs.android.lib.vo.MessageEvent
-import com.wdkl.ncs.android.middleware.tcp.NettyClient
-import org.greenrobot.eventbus.EventBus
-
-class HandleTcpConnect {
-    val TAG = HandleTcpConnect::class.simpleName
-
-    /*伴生对象*/
-    companion object {
-        var instance = HandleTcpConnect()
-    }
-
-    @SuppressLint("CheckResult")
-    fun tcpInitConnect(){
-        Log.d(TAG, "TCP.开始初始连接")
-        NettyClient.instance.connect(Constants.tcpServer, Constants.tcpPort, Constants.heartBeat.toLong()).subscribe {
-            if (it){
-                Log.d(TAG, "TCP.连接成功")
-                EventBus.getDefault().post(MessageEvent("tcp connected", Constants.EVENT_TCP_CONNECTED))
-            } else {
-                Log.e(TAG, "TCP.连接失败")
-                EventBus.getDefault().post(MessageEvent("tcp connected", Constants.EVENT_TCP_BREAK))
-            }
-        }
-    }
-
-    @SuppressLint("CheckResult")
-    fun tcpReConnect(){
-        Log.d(TAG, "TCP.开始重新连接")
-        NettyClient.instance.reConnect().doOnError {
-            it.message?.let { it1 -> Log.e(TAG, it1) }
-        }.subscribe {
-            if (it){
-                Log.d(TAG, "TCP.重连成功")
-            } else {
-                Log.e(TAG, "TCP.重连失败")
-            }
-        }
-    }
-
-    @SuppressLint("CheckResult")
-    fun tcpReConnectWithMsgShow(){
-        Log.d(TAG, "TCP.开始重新连接")
-        //showMessage("服务连接失败,正在重连")
-        NettyClient.instance.reConnect().doOnError {
-            it.message?.let { it1 -> Log.e(TAG, it1) }
-        }.subscribe{
-            if (it){
-                Log.d(TAG, "服务重连成功")
-                //EventBus.getDefault().post(MessageEvent("tcp connected", Constants.EVENT_TCP_CONNECTED))
-                //showMessage("重连成功")
-            } else {
-                Log.d(TAG, "服务重连失败")
-                //showMessage("重连失败,请尝试重启APP")
-            }
-        }
-    }
-}

+ 1 - 0
android_visiting/.gitignore

@@ -0,0 +1 @@
+/build

+ 160 - 0
android_visiting/build.gradle

@@ -0,0 +1,160 @@
+if (rootProject.ext.android_visiting.toBoolean()) {
+    apply plugin: 'com.android.library'
+} else {
+    return
+}
+
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-android-extensions'
+apply plugin: 'kotlin-kapt'
+
+
+kapt {
+    arguments {
+        arg("moduleName", project.getName())
+    }
+}
+
+android {
+    compileSdkVersion target_sdk_version
+    buildToolsVersion build_tools_version
+
+    defaultConfig {
+        minSdkVersion min_sdk_version
+        targetSdkVersion target_sdk_version
+        versionCode app_version_code
+        versionName app_version
+        multiDexEnabled true
+        flavorDimensions "app"
+        dataBinding {
+            enabled = true
+        }
+        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+        buildConfigField "String", "BUILD_TIME", getDate()
+        buildConfigField 'String', 'VERSION_NAME', "\"${project.rootProject.ext.app_version}\""
+        buildConfigField 'String', 'VERSION_CODE', "\"${project.rootProject.ext.app_version_code}\""
+        buildConfigField "String", "BUILD_TIME", getDate()
+    }
+
+    productFlavors {
+
+        xhg_rk3288 {//新豪格rk3288分机或门口机
+            dimension "app"
+            buildConfigField 'String', 'flag', '"2"'
+        }
+
+        //亿莱顿
+        yld {
+            dimension "app"
+            buildConfigField 'String', 'flag', '"5"'
+        }
+
+        //卡尔
+        kaer{
+            dimension "app"
+            buildConfigField 'String', 'flag', '"6"'
+        }
+
+        //中兴8寸
+        zx_8 {
+            dimension "app"
+            buildConfigField 'String', 'flag', '"8"'
+        }
+    }
+
+    lintOptions {
+        abortOnError false
+    }
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+        }
+    }
+    sourceSets {
+        main.java.srcDirs += 'src/main/main/java'
+        main.res.srcDirs += 'src/main/main/res'
+        main.manifest.srcFile 'src/main/AndroidManifest.xml'
+    }
+}
+
+//获取编译日期
+String getDate() {
+    Date date = new Date();
+    String dates = "\"" + date.format("yyyy-MM-dd", TimeZone.getTimeZone("UTC")) + "\"";
+    return dates;
+}
+
+
+dependencies {
+    compile fileTree(dir: 'libs', include: ['*.aar'])
+    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
+        exclude group: 'com.android.support', module: 'support-annotations'
+    })
+    /**
+     * 单元测试
+     */
+    testCompile 'junit:junit:4.12'
+
+    /**
+     *  Android基础依赖库
+     */
+    compile "com.android.support:design:$support_library_version"
+    compile "com.android.support:support-v4:$support_library_version"
+    compile "com.android.support:cardview-v7:$support_library_version"
+    compile "com.android.support:appcompat-v7:$support_library_version"
+
+    /**
+     * 公共库依赖
+     */
+    compile project(':middleware')
+
+    if (componentTag) {
+        debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.1'
+        releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.1'
+        testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.1'
+    }
+
+    /**
+     * Dagger编译依赖
+     */
+    kapt 'com.google.dagger:dagger-compiler:2.7'
+
+    /**
+     * Kotlin依赖
+     */
+    kapt 'com.android.databinding:compiler:2.3.3'
+
+    /**
+     * 路由注解处理器
+     */
+    kapt "com.enation.geamtear:jrouter-compiler:$router_version"
+
+    /**
+     *  constraint-layout布局依赖
+     */
+    implementation 'com.android.support.constraint:constraint-layout:1.1.0-beta5'
+    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+
+    //compile 'com.github.anrwatchdog:anrwatchdog:1.3.0'
+
+    implementation 'com.iqiyi.xcrash:xcrash-android-lib:3.0.0'
+
+    compile project(':janus')
+    compile project(':welcome')
+}
+
+/**
+ * kawo组件化框架配置
+ */
+if (componentTag) {
+    kawo {
+        /**
+         * Aop注解排除Jar
+         */
+        aspectExcludeJarFilter 'com.enation.geamtear.pay', 'AlipaySdk'
+    }
+}
+repositories {
+
+}

+ 25 - 0
android_visiting/proguard-rules.pro

@@ -0,0 +1,25 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /Users/Android/MAC_SDK/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile

+ 88 - 0
android_visiting/src/main/AndroidManifest.xml

@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    package="com.wdkl.ncs.android.component.home">
+
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+    <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
+    <uses-permission android:name="android.permission.SET_TIME" />
+    <uses-permission android:name="android.permission.SET_TIME_ZONE" />
+    <uses-permission android:name="android.permission.VIBRATE" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
+
+    <uses-permission android:name="android.permission.CAMERA" />
+    <uses-permission android:name="android.permission.RECORD_AUDIO" />
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <!-- 悬浮窗显示 -->
+    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
+    <uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW" />
+    <uses-permission android:name="android.permission.VIBRATE" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+    <uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT"/>
+
+    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
+
+    <application
+        android:allowBackup="true"
+        android:supportsRtl="true">
+
+        <activity android:name=".activity.VisitingActivity"
+            android:screenOrientation="nosensor"
+            android:launchMode="singleInstance">
+        </activity>
+
+        <activity android:name=".activity.SystemActivity"
+            android:screenOrientation="nosensor"
+            android:launchMode="singleTask"/>
+        <activity android:name=".activity.TextActivity"
+            android:screenOrientation="nosensor"
+            android:launchMode="singleTask"/>
+        <activity android:name=".activity.VisitingActivationActivity"
+            android:screenOrientation="nosensor"
+            android:launchMode="singleTask"/>
+        <activity android:name=".activity.AppUpdateActivity"
+            android:screenOrientation="nosensor"
+            android:launchMode="singleTask"/>
+
+        <service android:name=".service.TcpHandleService">
+            <intent-filter>
+                <action android:name="com.wdkl.ncs.android.component.home.service.TcpHandleService" />
+            </intent-filter>
+        </service>
+
+        <receiver
+            android:name=".broadcast.WdBootReceiver"
+            android:enabled="true"
+            android:exported="true">
+            <intent-filter android:priority="1000">
+                <action android:name="android.intent.action.BOOT_COMPLETED"/>
+            </intent-filter>
+        </receiver>
+
+        <!--<service android:name="com.wdkl.ncs.android.component.home.service.WdKeepAliveService">
+            <intent-filter>
+                <action android:name="com.wdkl.app.ncs.service.WdKeepAliveService"/>
+            </intent-filter>
+        </service>-->
+
+        <provider
+            android:name="androidx.core.content.FileProvider"
+            android:authorities="${applicationId}.provider"
+            tools:replace="android:authorities"
+            android:grantUriPermissions="true"
+            android:exported="false">
+            <meta-data
+                android:name="android.support.FILE_PROVIDER_PATHS"
+                android:resource="@xml/file_paths" />
+        </provider>
+
+    </application>
+
+</manifest>

BIN
android_visiting/src/main/assets/wd_update_plugin.apk


+ 246 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/activity/AppUpdateActivity.kt

@@ -0,0 +1,246 @@
+package com.wdkl.ncs.android.component.home.activity
+
+import android.content.Intent
+import android.os.Build
+import android.text.TextUtils
+import android.util.Log
+import android.view.View
+import com.enation.javashop.android.jrouter.external.annotation.Router
+import com.enation.javashop.net.engine.model.NetState
+import com.wdkl.ncs.android.component.home.BuildConfig
+import com.wdkl.ncs.android.component.home.R
+import com.wdkl.ncs.android.component.home.databinding.ActivityAppUpdateBinding
+import com.wdkl.ncs.android.component.home.helper.AppUpdateHelper
+import com.wdkl.ncs.android.component.home.helper.HttpHelper
+import com.wdkl.ncs.android.component.home.helper.StatusBarHelper
+import com.wdkl.ncs.android.component.home.launch.VisitingLaunch
+import com.wdkl.ncs.android.component.home.service.TcpHandleService
+import com.wdkl.ncs.android.lib.base.BaseActivity
+import com.wdkl.ncs.android.lib.utils.AppTool
+import com.wdkl.ncs.android.lib.utils.showMessage
+import com.wdkl.ncs.android.lib.vo.filter
+import com.wdkl.ncs.android.middleware.api.UrlManager
+import com.wdkl.ncs.android.middleware.common.Constant
+import com.wdkl.ncs.android.middleware.common.MessageEvent
+import com.wdkl.ncs.android.middleware.logic.contract.home.AppUpdateContract
+import com.wdkl.ncs.android.middleware.logic.presenter.home.HomeAppUpdatePresenter
+import com.wdkl.ncs.android.middleware.model.dos.AppVersionDO
+import com.wdkl.ncs.android.middleware.tcp.enums.DeviceTypeEnum
+import kotlinx.android.synthetic.main.activity_app_update.*
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+import java.io.File
+
+@Router(path = "/app/update")
+class AppUpdateActivity :BaseActivity<HomeAppUpdatePresenter, ActivityAppUpdateBinding>(), AppUpdateContract.View {
+    private val TAG = "AppUpdateActivity"
+
+    private val urlManager = UrlManager.build()
+
+    override fun getLayId(): Int {
+        return R.layout.activity_app_update
+    }
+
+    override fun bindDagger() {
+        VisitingLaunch.component.inject(this)
+    }
+
+    override fun init() {
+        checkAppVersion()
+    }
+
+    override fun handleAppVersion(appInfo: AppVersionDO) {
+        if ("YUNPAI_H6".equals(Build.MODEL)) {
+            try {
+                //启动云派app升级监听服务
+                val intent = Intent()
+                intent.setClassName("com.wd.app", "com.wd.app.MyService")
+                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+                    //android8.0以上通过startForegroundService启动service
+                    startForegroundService(intent)
+                } else {
+                    startService(intent)
+                }
+                Constant.yunpai_plugin = true
+            } catch (e: Exception) {
+                e.printStackTrace()
+            }
+        }
+
+        if (BuildConfig.VERSION_CODE.toInt() < appInfo.versionNo){
+            if (!TextUtils.isEmpty(appInfo.appPath)) {
+                downLoadAPK(urlManager.base + appInfo.appPath)
+            } else {
+                showMessage("下载路径异常")
+                finish()
+            }
+        } else {
+            showMessage("本机已经是最新版本")
+            activity_calling_bed_text_download.text = "本机已经是最新版本"
+            activity_appupdate_dialog_progressview.visibility = View.GONE
+            TcpHandleService.updateLastTime = System.currentTimeMillis() / 1000
+            AppTool.Time.delay(1000){
+                finish()
+            }
+        }
+    }
+
+    fun checkAppVersion() {
+        if (Constant.PART_ID != null) {
+            presenter.getAppVersion(Constant.PART_ID, DeviceTypeEnum.VISITATION.value())
+        }
+    }
+
+    /**
+     * 下载APK包
+     */
+    fun downLoadAPK(url: String) {
+        Log.d(TAG, "downLoadAPK  url==$url")
+        activity_appupdate_dialog_progressview.setCurProgress(0)
+        HttpHelper.download(url, object : HttpHelper.DownloadListener {
+            override fun onDownloadSuccess() {
+                Log.d("download", "onDownloadSuccess==" + "成功")
+                runOnUiThread {
+                    activity_calling_bed_text_download.text = "正在安装,请稍后..."
+                }
+
+                if (BuildConfig.FLAVOR.equals(Constant.DEV_W_XHG_RK3288)) {
+                    installApkForRk3288()
+                } else if ("YUNPAI_H6".equals(Build.MODEL)) {
+                    startInstallAppYunPai()
+                } else if (Build.BOARD.equals("k37tv1_64_bsp") || Build.BOARD.equals("k37mv1_64_bsp") || Build.MODEL.equals("KT10-3F")
+                        || "m3520b_bnkj_zx".equals(Build.MODEL, true)) {
+                    installAppKaer()
+                } else if (BuildConfig.FLAVOR.equals(Constant.DEV_W_YLD)) {
+                    //亿莱顿10寸
+                    installAppKaer()
+                } else {
+                    startInstallApk()
+                }
+            }
+
+            override fun onDownloading(progress: Int) {
+                runOnUiThread {
+                    activity_appupdate_dialog_progressview.setCurProgress(progress)
+                }
+            }
+
+            override fun onDownloadFailed() {
+                Log.d("download", "onDownloadFailed==" + "失败")
+                finish()
+            }
+        })
+    }
+
+    private fun installAppKaer() {
+        Thread{
+            AppUpdateHelper.updateApp2(this, object : AppUpdateHelper.UpdateCallBack {
+                override fun onFailed() {
+                    runOnUiThread {
+                        showMessage("升级失败")
+                        finish()
+                    }
+                }
+
+                override fun onSuccess() {
+                    runOnUiThread {
+                        finish()
+                    }
+                }
+            })
+        }.start()
+    }
+
+    fun startInstallApk() {
+        Thread{
+            AppUpdateHelper.updateApp(this, object : AppUpdateHelper.UpdateCallBack {
+                override fun onFailed() {
+                    runOnUiThread {
+                        showMessage("升级失败")
+                        finish()
+                    }
+                }
+
+                override fun onSuccess() {
+                    runOnUiThread {
+                        //showMessage("升级成功")
+                        finish()
+                        //有root权限用这个
+//                        android.os.Process.killProcess(android.os.Process.myPid())
+//                        System.exit(0)
+                    }
+                }
+            })
+        }.start()
+    }
+
+    //云派8寸机app静默升级
+    fun startInstallAppYunPai() {
+        val apkAbsolutePath = AppUpdateHelper.FILE_APK_PATH + "/" + AppUpdateHelper.FILE_APK_NAME
+        val action = "com.miki.slient.INSTALL_CUSTOMER_PACKAGES"
+        val intent = Intent(action)
+        intent.putExtra("apkPath", apkAbsolutePath)
+        intent.putExtra("packageName", "com.miki.sensortest")
+        sendBroadcast(intent)
+    }
+
+    fun installApkForRk3288() {
+        val path = AppUpdateHelper.FILE_APK_PATH + "/" + AppUpdateHelper.FILE_APK_NAME
+        if (File(path).exists()) {
+            val intent = Intent("com.android.yf_slient_install")
+            intent.putExtra("path", path)  //要静默安装的apk路径
+            intent.putExtra("isboot", true)  //安装完成后是否启动
+            sendBroadcast(intent)
+        } else {
+            showMessage("安装文件不存在,升级失败!")
+            finish()
+        }
+    }
+
+    override fun bindEvent() {
+        //
+    }
+
+    override fun destory() {
+        //
+    }
+
+    //数据加载错误
+    override fun onError(message: String, type: Int) {
+        showMessage("获取版本失败!")
+        finish()
+    }
+
+    override fun onNoneNet() {
+        showMessage("没有网络!")
+        finish()
+    }
+
+    //数据加载完成
+    override fun complete(message: String, type: Int) {
+        //
+    }
+
+    //开始获取数据
+    override fun start() {
+        //
+    }
+
+    //网络监听
+    override fun networkMonitor(state: NetState) {
+        state.filter(onMobile = {
+
+        },onWifi = {
+
+        },offline = {
+
+        })
+    }
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    fun onMoonEvent(messageEvent: MessageEvent) {
+
+    }
+
+
+}

+ 263 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/activity/SystemActivity.kt

@@ -0,0 +1,263 @@
+package com.wdkl.ncs.android.component.home.activity
+
+import android.content.Intent
+import android.content.res.Configuration
+import android.os.Build
+import android.view.View
+import com.enation.javashop.net.engine.model.NetState
+import com.wdkl.ncs.android.component.home.BuildConfig
+import com.wdkl.ncs.android.component.home.R
+import com.wdkl.ncs.android.component.home.databinding.VisitingSettingMainBinding
+import com.wdkl.ncs.android.component.home.helper.*
+import com.wdkl.ncs.android.component.home.launch.VisitingLaunch
+import com.wdkl.ncs.android.component.home.settingconfig.SettingConfig
+import com.wdkl.ncs.android.component.home.util.AppUtils
+import com.wdkl.ncs.android.component.home.util.NetHelper
+import com.wdkl.ncs.android.lib.base.BaseActivity
+import com.wdkl.ncs.android.lib.utils.EcodeHelper
+import com.wdkl.ncs.android.lib.utils.showMessage
+import com.wdkl.ncs.android.lib.vo.filter
+import com.wdkl.ncs.android.middleware.api.UrlManager
+import com.wdkl.ncs.android.middleware.common.Constant
+import com.wdkl.ncs.android.middleware.common.MessageEvent
+import com.wdkl.ncs.android.middleware.logic.contract.callingdoor.SystemActivityContract
+import com.wdkl.ncs.android.middleware.logic.presenter.callingdoor.SystemActivityPresenter
+import com.wdkl.ncs.android.middleware.model.dos.AppVersionDO
+import com.wdkl.ncs.android.middleware.tcp.enums.DeviceTypeEnum
+import com.wdkl.ncs.android.middleware.utils.CommonUtils
+import kotlinx.android.synthetic.main.view_title_layout.*
+import kotlinx.android.synthetic.main.visiting_setting_main.*
+import kotlinx.android.synthetic.main.visiting_setting_main.settings_main_5_ll
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+
+class SystemActivity : BaseActivity<SystemActivityPresenter, VisitingSettingMainBinding>(), SystemActivityContract.View {
+    private val TAG = "SystemActivity"
+    val QR_CODE_PATH = "http://m.wdklian.com/care/apk/care.user?type=NCS_DEVICE"
+
+    override fun getLayId(): Int {
+        return R.layout.visiting_setting_main
+    }
+
+    override fun bindDagger() {
+        VisitingLaunch.component.inject(this)
+    }
+
+    override fun init() {
+        showui()
+    }
+
+    override fun bindEvent() {
+        //服务器设置
+        settings_main_1_ll.setOnClickListener {
+            ServicesDialogHelper.showDialog(activity, object : ServicesDialogHelper.ClickListener {
+                override fun onClick(bedVO: String?) {
+                    setfuq()
+                }
+            })
+        }
+        //网络设置
+        settings_main_2_ll.setOnClickListener {
+            NetworkDialogHelper.showDialog(activity)
+        }
+
+        //进入调试
+        settings_main_3_ll.setOnClickListener {
+            if (AppUtils.openNetworkDebug()) {
+                showMessage("Debug enabled")
+            }
+
+            val intent = Intent()
+            intent.setClass(activity, TextActivity::class.java)
+            activity.startActivity(intent)
+        }
+
+        //版本更新
+        settings_main_4_ll.setOnClickListener {
+            UpdataDialogHelper.showDialog(activity, object : UpdataDialogHelper.ClickListener {
+                override fun onClick() {
+                    if (Constant.PART_ID != null) {
+                        presenter.getAppVersion(Constant.PART_ID, DeviceTypeEnum.VISITATION.value())
+                    } else {
+                        showMessage("null part id")
+                    }
+                }
+            })
+        }
+
+        //重启设备
+        settings_main_5_ll.setOnClickListener {
+            RebootDialogHelper.showDialog(activity)
+        }
+
+        //返回上一层
+        view_title_layout_return.setOnClickListener {
+            view_title_layout_img.visibility = View.GONE
+            view_title_layout_tv_no.visibility =View.GONE
+
+            finish()
+        }
+    }
+
+    override fun destory() {
+
+    }
+
+    fun setfuq(){
+        settings_main_10_tx.text= CommonUtils.getUrl(this)
+        showMessage("请重启设备,重新激活设备")
+    }
+
+    private fun showui(){
+        view_title_layout_tv_hospital_name.setText(R.string.str_back)
+        view_title_layout_img.visibility = View.VISIBLE
+        view_title_layout_tv_no.visibility =View.VISIBLE
+        view_title_layout_tv_no.text ="设备信息"
+        val orientation = resources.configuration.orientation
+        if (orientation == Configuration.ORIENTATION_PORTRAIT) {
+            // 竖屏模式
+            view_title_layout_tv_no.visibility = View.GONE
+        }
+        //网络图标
+        if ( Constant.network_state == 1){
+            view_title_layout_iv_wifi.visibility = View.VISIBLE
+            view_title_layout_iv_ethernet.visibility = View.GONE
+            view_title_layout_iv_wifi.setImageResource(R.mipmap.ic_wifi_success)
+        }else if ( Constant.network_state == 2){
+            view_title_layout_iv_wifi.visibility = View.GONE
+            view_title_layout_iv_ethernet.visibility = View.VISIBLE
+            view_title_layout_iv_ethernet.setImageResource(R.mipmap.ic_ethernet_success)
+        }else{
+            view_title_layout_iv_wifi.visibility = View.GONE
+            view_title_layout_iv_ethernet.visibility = View.VISIBLE
+            view_title_layout_iv_ethernet.setImageResource(R.mipmap.ic_ethernet_fail)
+        }
+        //蓝牙图标
+        if ( Constant.BT_state == 0){
+            view_title_layout_iv_bt.setImageResource(R.mipmap.ic_bt_success)
+        }
+        //白天/黑夜
+        if (Constant.day_state == 0){
+            view_title_layout_iv_day_night.setImageResource(R.mipmap.ic_daylight)
+        }else{
+            view_title_layout_iv_day_night.setImageResource(R.mipmap.ic_night)
+        }
+        view_title_layout_iv_tcp.setImageResource(R.mipmap.ic_tcp_success)
+        //设置二维码
+        setQrcode()
+        try {
+            //设备id
+            settings_main_6_tx.text =  ""+Constant.DEVICE_ID
+            //设备ip
+            settings_main_7_tx.text = NetHelper.getInstance().localIP
+            //设备网关
+            /*settings_main_8_tx.text = NetHelper.getInstance().gateway()
+            val netInfo = NetHelper.getNetInfo(activity)
+            if (netInfo.dns1!=null){
+                //设备dns
+                settings_main_9_tx.text=netInfo.dns1+ NetHelper.getInstance().getmask()
+            }else{
+                settings_main_9_tx.text="0:0:0:0   "+ NetHelper.getInstance().getmask()
+            }*/
+
+        } catch (e: Exception) {
+
+        }
+        //服务器地址
+        val buildUrl = UrlManager.build()
+        settings_main_10_tx.text=   buildUrl.buyer.substringAfterLast("//").substringBefore(":")
+        //语音id
+        settings_main_11_tx.text= Constant.SIP_ID
+        //语音类型 ??
+        /*if(SettingConfig.getSipEnabled(activity)){
+            settings_main_12_tx.text= "sip"+"类型"
+        }else{
+            settings_main_12_tx.text= "webrtc"+"类型"
+        }*/
+        //语音服务器
+        settings_main_13_tx.text= "${Constant.SIP_ID}@${Constant.sip_ip}:${Constant.sip_port}"
+        //app版本
+        settings_main_14_tx.text =  BuildConfig.VERSION_NAME + "_" + BuildConfig.VERSION_CODE + "_" + Build.MODEL
+        //发布日期
+        settings_main_15_tx.text =  BuildConfig.BUILD_TIME
+//        activation_zcm.text=  Constant.DEVICE_REGISTER_ID
+    }
+
+    //设置二维码
+    private fun setQrcode(){
+        Thread{
+            //val logoBitmap = BitmapFactory.decodeResource(resources, R.mipmap.erlogo)
+            var builder = StringBuilder()
+            builder.append(QR_CODE_PATH)
+            builder.append("&code=")
+            builder.append(Constant.DEVICE_CODE)
+            builder.append("&mac=")
+            builder.append(Constant.DEVICE_REGISTER_ID)
+            builder.append("&model=")
+            builder.append(Constant.DEVICE_MODEL)
+            builder.append("&hard_ver=")
+            builder.append(Constant.DEVICE_HARD_VER)
+            builder.append("&soft_ver=")
+            builder.append(Constant.DEVICE_SOFT_VER)
+            builder.append("&device_type=")
+            builder.append(DeviceTypeEnum.VISITATION.value())
+            builder.append("&device_name=")
+            builder.append(DeviceTypeEnum.VISITATION.typeName())
+            val code = EcodeHelper().createQRImage(builder.toString(), 200, null)
+            activity.runOnUiThread {
+                setting_qr_code?.setImageBitmap(code)
+            }
+        }.start()
+    }
+
+    override fun loadAppVersion(appInfo: AppVersionDO) {
+        var version = BuildConfig.VERSION_CODE.toInt()
+        if ( version< appInfo.versionNo) {
+            Constant.APP_UPDATING = true
+            Constant.APP_PATH = appInfo.appPath
+            //UpdateTipsDialogHelper.showDialog(activity)
+
+            val intent = Intent()
+            intent.setClass(this, AppUpdateActivity::class.java)
+            startActivity(intent)
+        } else {
+            showMessage(R.string.update_no_required)
+        }
+    }
+
+    override fun onNoNet() {
+
+    }
+
+    //数据加载错误
+    override fun onError(message: String, type: Int) {
+
+    }
+    //数据加载完成
+    override fun complete(message: String, type: Int) {
+
+    }
+
+    //开始获取数据
+    override fun start() {
+        //
+    }
+
+    //网络监听
+    override fun networkMonitor(state: NetState) {
+        state.filter(onMobile = {
+
+        }, onWifi = {
+
+        }, offline = {
+
+        })
+    }
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    fun onMoonEvent(messageEvent: MessageEvent) {
+        if (Constant.EVENT_FINISHh == messageEvent.type) {
+            finish()
+        }
+    }
+}

+ 323 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/activity/TextActivity.kt

@@ -0,0 +1,323 @@
+package com.wdkl.ncs.android.component.home.activity
+
+import android.hardware.Camera
+import android.os.Build
+import android.view.SurfaceHolder
+import android.view.View
+import android.widget.Toast
+import com.enation.javashop.net.engine.model.NetState
+import com.wdkl.ncs.android.component.home.R
+import com.wdkl.ncs.android.component.home.databinding.VisitingTestMainBinding
+import com.wdkl.ncs.android.component.home.helper.RecordHelper
+import com.wdkl.ncs.android.component.home.launch.VisitingLaunch
+import com.wdkl.ncs.android.component.home.util.MediaPlayHelper
+import com.wdkl.ncs.android.component.home.util.SoundPoolManager
+import com.wdkl.ncs.android.lib.base.BaseActivity
+import com.wdkl.ncs.android.lib.utils.showMessage
+import com.wdkl.ncs.android.lib.vo.filter
+import com.wdkl.ncs.android.middleware.common.Constant
+import com.wdkl.ncs.android.middleware.common.MessageEvent
+import com.wdkl.ncs.android.middleware.logic.contract.callingdoor.TextActivityContract
+import com.wdkl.ncs.android.middleware.logic.presenter.callingdoor.TextActivityPresenter
+import com.wdkl.ncs.android.middleware.utils.CommonUtils
+import kotlinx.android.synthetic.main.view_title_layout.*
+import kotlinx.android.synthetic.main.visiting_setting_main.*
+import kotlinx.android.synthetic.main.visiting_test_main.*
+import org.greenrobot.eventbus.EventBus
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+import org.linphone.core.Core
+
+class TextActivity : BaseActivity<TextActivityPresenter, VisitingTestMainBinding>(), TextActivityContract.View {
+    private val TAG = "TextActivity"
+
+    private var mCamera: Camera? = null
+    var core: Core? = null
+
+    override fun getLayId(): Int {
+        return R.layout.visiting_test_main
+    }
+
+    override fun bindDagger() {
+        VisitingLaunch.component.inject(this)
+    }
+
+    override fun init() {
+        Constant.isText=true
+        showui()
+
+        RecordHelper.getInstance().init()
+
+
+        /*WdklSipService.sipTesting = true
+        if (SettingConfig.getSipEnabled(this) && Constant.TCP_CONNECTED) {
+            core = WdklSipService.getCore()
+        }
+        if (core?.identity.equals("") || core?.identity==null ){
+            password_ed.hint = "无法获取本设备sip号"
+        }else{
+            password_ed.hint = core?.identity
+        }*/
+
+        //摄像头调用  暂无
+//        startCameraPreview()
+    }
+
+    override fun bindEvent() {
+        //  sip呼叫测试  门口机暂时没有
+        text_call_button.setOnClickListener {
+            val sipNo = password_ed.text
+            if (sipNo.equals("")){
+                Toast.makeText(this, "sip no must input", Toast.LENGTH_SHORT).show()
+                return@setOnClickListener
+            }
+            if (core!=null) {
+                val addressToCall = core?.interpretUrl(sipNo.toString())
+                val params = core?.createCallParams(null)
+                params?.isVideoEnabled  = false
+                if (addressToCall != null) {
+                    core?.inviteAddressWithParams(addressToCall, params!!)
+                }
+            }else{
+                showMessage("未启动sip服务,请启动服务后,在进行sip通话")
+            }
+        }
+
+        lycs_button.setOnClickListener {
+            startTest()
+        }
+
+        camera_button.setOnLongClickListener {
+            startCameraPreview()
+
+            return@setOnLongClickListener true
+        }
+
+        //返回上一层
+        view_title_layout_return.setOnClickListener {
+            Constant.isText=false
+            view_title_layout_img.visibility = View.GONE
+            view_title_layout_tv_no.visibility =View.GONE
+            //WdklSipService.sipTesting = false
+            finish()
+        }
+
+    }
+
+    override fun destory() {
+        Constant.isText=false
+        if (mCamera != null) {
+            mCamera!!.stopPreview()
+            mCamera!!.release()
+            mCamera = null
+        }
+    }
+
+    fun setfuq(){
+        settings_main_10_tx.text= CommonUtils.getUrl(this)
+        showMessage("请重启设备,重新激活设备")
+    }
+
+    private fun showui(){
+        view_title_layout_tv_hospital_name.setText(R.string.str_back)
+        view_title_layout_img.visibility = View.VISIBLE
+        view_title_layout_tv_no.visibility =View.VISIBLE
+        view_title_layout_tv_no.text ="设备调试"
+        //网络图标
+        if ( Constant.network_state == 1){
+            view_title_layout_iv_wifi.visibility = View.VISIBLE
+            view_title_layout_iv_ethernet.visibility = View.GONE
+            view_title_layout_iv_wifi.setImageResource(R.mipmap.ic_wifi_success)
+        }else if ( Constant.network_state == 2){
+            view_title_layout_iv_wifi.visibility = View.GONE
+            view_title_layout_iv_ethernet.visibility = View.VISIBLE
+            view_title_layout_iv_ethernet.setImageResource(R.mipmap.ic_ethernet_success)
+        }else{
+            view_title_layout_iv_wifi.visibility = View.GONE
+            view_title_layout_iv_ethernet.visibility = View.VISIBLE
+            view_title_layout_iv_ethernet.setImageResource(R.mipmap.ic_ethernet_fail)
+        }
+        //蓝牙图标
+        if ( Constant.BT_state == 0){
+            view_title_layout_iv_bt.setImageResource(R.mipmap.ic_bt_success)
+        }
+        //白天/黑夜
+        if (Constant.day_state == 0){
+            view_title_layout_iv_day_night.setImageResource(R.mipmap.ic_daylight)
+        }else{
+            view_title_layout_iv_day_night.setImageResource(R.mipmap.ic_night)
+        }
+        view_title_layout_iv_tcp.setImageResource(R.mipmap.ic_tcp_success)
+        text_sbaj_button.setBackgroundResource(R.drawable.shape_main_hos_txt_bg)
+        sbaj_img.visibility=View.INVISIBLE
+        mbhj_button.setBackgroundResource(R.drawable.shape_main_hos_txt_bg)
+        mbh_img.visibility=View.INVISIBLE
+        mbhjqx_button.setBackgroundResource(R.drawable.shape_main_hos_txt_bg)
+        mbhjjqx_img.visibility=View.INVISIBLE
+        lycs_button.setBackgroundResource(R.drawable.shape_main_hos_txt_bg)
+        lycs_img.visibility=View.INVISIBLE
+
+    }
+    //麦克风
+    private fun startTest() {
+        Thread {
+            SoundPoolManager.getInstance().playSound(3, 1.0f, 1.0f, 0)
+            Thread.sleep(2000)
+            EventBus.getDefault().post(MessageEvent("lu", Constant.EVENT_SERIAL_TEST))
+            RecordHelper.getInstance().recordTestStart()
+            Thread.sleep(2500)
+            RecordHelper.getInstance().recordTestStop()
+            Thread.sleep(500)
+            EventBus.getDefault().post(MessageEvent("bo", Constant.EVENT_SERIAL_TEST))
+            MediaPlayHelper.getInstance().playUrlMusic(RecordHelper.getInstance().audiofilePath, 1.0f, false)
+            Thread.sleep(3000)
+            RecordHelper.getInstance().deleteAudioFile()
+            EventBus.getDefault().post(MessageEvent("bo_w", Constant.EVENT_SERIAL_TEST))
+        }.start()
+    }
+
+    //摄像头
+    private fun startCameraPreview() {
+        val num = Camera.getNumberOfCameras()
+        if (num > 0) {
+            val info = Camera.CameraInfo()
+            for (i in 0 until num) {
+                Camera.getCameraInfo(i, info)
+                if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
+                    try {
+                        mCamera = Camera.open(i)
+                    } catch (e: Exception) {
+                        e.printStackTrace()
+                    }
+                    break
+                }
+            }
+
+            if (mCamera == null) {
+                try {
+                    mCamera = Camera.open()
+                } catch (e: Exception) {
+                    e.printStackTrace()
+                }
+            }
+
+            if (mCamera == null) {
+                showMessage(R.string.str_open_camera_failed)
+            } else {
+                frame_camera_view.visibility = View.VISIBLE
+            }
+
+            preview_surface.getHolder().addCallback(object : SurfaceHolder.Callback {
+                override fun surfaceCreated(holder: SurfaceHolder) {
+                    /**
+                     * The SurfaceHolder must already contain a surface when this method is called.
+                     * If you are using SurfaceView, you will need to register a SurfaceHolder.Callback
+                     * with SurfaceHolder#addCallback(SurfaceHolder.Callback) and wait for
+                     * SurfaceHolder.Callback#surfaceCreated(SurfaceHolder) before
+                     * calling setPreviewDisplay() or starting preview.
+                     * 相机的预览必须在surfaceCreated后调用,否则黑屏且没有任何提示哦
+                     */
+
+                    try {
+                        mCamera!!.setPreviewDisplay(preview_surface.getHolder())
+                        mCamera!!.startPreview()
+                    } catch (e: Exception) {
+                        e.printStackTrace()
+                    }
+                }
+
+                override fun surfaceChanged(
+                    holder: SurfaceHolder,
+                    format: Int,
+                    width: Int,
+                    height: Int
+                ) {
+                    //
+                }
+
+                override fun surfaceDestroyed(holder: SurfaceHolder) {
+                    //
+                }
+            })
+        } else {
+            showMessage(R.string.str_no_camera)
+        }
+    }
+
+    override fun onStart() {
+        EventBus.getDefault().register(this)
+        super.onStart()
+    }
+
+    override fun onStop() {
+        //WdklSipService.sipTesting = false
+        EventBus.getDefault().unregister(this)
+        super.onStop()
+    }
+
+    override fun onDestroy() {
+        super.onDestroy()
+
+        if (mCamera != null) {
+            mCamera?.stopPreview()
+            mCamera?.release()
+            mCamera = null
+        }
+    }
+
+    private fun showInfo(text: String) {
+        activity.runOnUiThread {
+
+        }
+    }
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    fun onMoonEvent(messageEvent: MessageEvent) {
+        if (Constant.EVENT_SERIAL_TEST == messageEvent.type) {
+                val message = messageEvent.message as String
+                if (message == "call") {
+                    mbhj_button.setBackgroundResource(R.drawable.shape_reinforcements_dialog_bt_bg)
+                    mbh_img.visibility=View.VISIBLE
+                }else if(message == "bo"){
+                    //手柄取消
+                    lycs_button.setCompoundDrawablesWithIntrinsicBounds(R.mipmap.bo, 0, 0, 0)
+                    lycs_button.text="播放中"
+                }else if(message == "bo_w"){
+                    //手柄取消
+                    lycs_button.setBackgroundResource(R.drawable.shape_reinforcements_dialog_bt_bg)
+                    lycs_button.text="播放完毕"
+                    lycs_img.visibility=View.VISIBLE
+                }else if(message == "lu"){
+                    lycs_button.text="录音中"
+
+                }
+        }else if (Constant.EVENT_FINISHh == messageEvent.type) {
+            finish()
+        }
+    }
+    //数据加载错误
+    override fun onError(message: String, type: Int) {
+
+    }
+    //数据加载完成
+    override fun complete(message: String, type: Int) {
+
+    }
+
+    //开始获取数据
+    override fun start() {
+        //
+    }
+
+    //网络监听
+    override fun networkMonitor(state: NetState) {
+        state.filter(onMobile = {
+
+        }, onWifi = {
+
+        }, offline = {
+
+        })
+    }
+
+}

+ 355 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/activity/VisitingActivationActivity.kt

@@ -0,0 +1,355 @@
+ package com.wdkl.ncs.android.component.home.activity
+
+import android.content.Context
+import android.content.Intent
+import android.content.res.Configuration
+import android.net.ConnectivityManager
+import android.net.Uri
+import android.os.Build
+import android.os.Handler
+import android.os.Looper
+import android.provider.Settings
+import android.text.TextUtils
+import android.util.Log
+import com.enation.javashop.android.jrouter.external.annotation.Router
+import com.enation.javashop.net.engine.config.NetEngineConfig
+import com.enation.javashop.net.engine.model.NetState
+import com.enation.javashop.net.engine.plugin.exception.RestfulExceptionInterceptor
+import com.enation.javashop.utils.base.config.BaseConfig
+import com.wdkl.ncs.android.component.home.BuildConfig
+import com.wdkl.ncs.android.component.home.R
+import com.wdkl.ncs.android.component.home.databinding.VisitingActivationBinding
+import com.wdkl.ncs.android.component.home.hardware.HardWareFactroy
+import com.wdkl.ncs.android.component.home.helper.ServicesDialogHelper
+import com.wdkl.ncs.android.component.home.helper.StatusBarHelper
+import com.wdkl.ncs.android.component.home.helper.SystemDialogHelper
+import com.wdkl.ncs.android.component.home.launch.VisitingLaunch
+import com.wdkl.ncs.android.component.home.settingconfig.SettingConfig
+import com.wdkl.ncs.android.component.home.util.*
+
+import com.wdkl.ncs.android.lib.base.BaseActivity
+import com.wdkl.ncs.android.lib.base.BaseApplication
+import com.wdkl.ncs.android.lib.utils.EcodeHelper
+import com.wdkl.ncs.android.lib.utils.showMessage
+import com.wdkl.ncs.android.lib.vo.filter
+import com.wdkl.ncs.android.middleware.common.Constant
+import com.wdkl.ncs.android.middleware.common.MessageEvent
+import com.wdkl.ncs.android.middleware.logic.contract.home.HomeActivityContract
+import com.wdkl.ncs.android.middleware.logic.presenter.home.HomeActivityPresenter
+import com.wdkl.ncs.android.middleware.model.ServerInfo
+import com.wdkl.ncs.android.middleware.model.ThirdServerInfo
+import com.wdkl.ncs.android.middleware.model.dos.PartSettingDO
+import com.wdkl.ncs.android.middleware.model.dto.TcpSeverDTO
+import com.wdkl.ncs.android.middleware.model.vo.DeviceWatchInfoVO
+import com.wdkl.ncs.android.middleware.tcp.enums.DeviceTypeEnum
+import com.wdkl.ncs.android.middleware.udp.ServerInfoUtil
+import com.wdkl.ncs.android.middleware.utils.CommonUtils
+import kotlinx.android.synthetic.main.visiting_activation.*
+import okhttp3.OkHttpClient
+import okhttp3.Request
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+import java.util.concurrent.TimeUnit
+
+/**
+  * 激活页面
+  * */
+ @Router(path = "/visiting/activation")
+class VisitingActivationActivity : BaseActivity<HomeActivityPresenter, VisitingActivationBinding>(), HomeActivityContract.View {
+
+    private val TAG = "VisitingActivationActivity"
+    val QR_CODE_PATH = "http://m.wdklian.com/care/apk/care.user?type=NCS_DEVICE"
+    private val uninstallApk = false
+    private val handler by lazy { Handler(Looper.getMainLooper()) }
+    //服务器是否请求成功
+    private var serverSuccess = false
+    //是否重启
+    private var cancelRestart = false
+
+    override fun getLayId(): Int {
+       return R.layout.visiting_activation
+    }
+
+    override fun bindDagger() {
+        VisitingLaunch.component.inject(this)
+    }
+
+    override fun init() {
+        BaseConfig.getInstance().addActivity("WelcomeActivity", "AppUpdateActivity", "VisitingActivity", "SystemActivity", "TextActivity", "VisitingActivationActivity")
+        NetEngineConfig.init(baseContext)
+                .openLogger()
+                .addNetInterceptor(RestfulExceptionInterceptor())
+
+        if (!Settings.canDrawOverlays(this)) {
+            val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
+                    Uri.parse("package:$packageName"))
+            startActivityForResult(intent, 10)
+        }
+        //init
+        NetHelper.getInstance().init()
+
+        if (Build.BOARD.equals("k37tv1_64_bsp") || Build.BOARD.equals("k37mv1_64_bsp") || Build.MODEL.equals("KT10-3F")) {
+            StatusBarHelper.toggleStatusBar(activity, true)
+        }
+
+        //anr catcher
+        //AnrFcExceptionUtil.getInstance(BaseApplication.appContext).initFCException()
+        //xCrash catcher
+        XCrashUtils().init(application)
+
+        showui()
+
+        checkServer()
+    }
+
+    override fun bindEvent() {
+        //设备重启
+        activation_settings_button.setOnClickListener {
+            AppUtils.restartApp()
+        }
+        //系统设置
+        activation_system_button.setOnClickListener {
+            SystemDialogHelper.showDialog(activity)
+        }
+        //服务器设置
+        activation_services_button.setOnClickListener {
+            ServicesDialogHelper.showDialog(activity, object : ServicesDialogHelper.ClickListener {
+                override fun onClick(bedVO: String?) {
+                    setfuq()
+                }
+            })
+        }
+    }
+
+    override fun destory() {
+
+    }
+
+    private fun showui(){
+        //注册方式
+        HardWareFactroy.getHardTools().Registration(this)
+
+        val isActivation = SPUtils.get(this, Constant.APP_ACTIVATION, "");
+        if (isActivation.equals("已激活")){
+            activation_title.setText("系统连接失败")
+            activation_title.setTextColor(resources.getColor(R.color.red_color))
+            activation_title_msg.setText("请检查网络与服务器地址")
+            activation_title.setTextColor(resources.getColor(R.color.red_color))
+        }else{
+            activation_title.setText("请先激活设备")
+            activation_title.setTextColor(resources.getColor(R.color.white))
+            activation_title_msg.setText("设置右侧参数后激活")
+            activation_title.setTextColor(resources.getColor(R.color.white))
+        }
+
+        //设置二维码
+        setQrcode()
+
+        activation_v.text =  BuildConfig.VERSION_NAME + "_" + BuildConfig.VERSION_CODE + "_" + Build.MODEL
+        activation_ip.text = NetHelper.getInstance().localIP
+        //activation_wg.text = NetHelper.getInstance().gateway()
+        //activation_ym.text= NetHelper.getInstance().getmask()
+        activation_zcm.text=  Constant.DEVICE_REGISTER_ID
+        activation_fuq.text = CommonUtils.getUrl(activity)
+
+        updateNetState()
+    }
+
+     fun setfuq(){
+         activation_fuq.text=CommonUtils.getUrl(this)
+         showMessage("请重启设备,重新激活设备")
+    }
+
+    //设置二维码
+    private fun setQrcode(){
+        Thread{
+            //val logoBitmap = BitmapFactory.decodeResource(resources, R.mipmap.erlogo)
+            var builder = StringBuilder()
+            builder.append(QR_CODE_PATH)
+            builder.append("&code=")
+            builder.append(Constant.DEVICE_CODE)
+            builder.append("&mac=")
+            builder.append(Constant.DEVICE_REGISTER_ID)
+            builder.append("&model=")
+            builder.append(Constant.DEVICE_MODEL)
+            builder.append("&hard_ver=")
+            builder.append(Constant.DEVICE_HARD_VER)
+            builder.append("&soft_ver=")
+            builder.append(Constant.DEVICE_SOFT_VER)
+            builder.append("&device_type=")
+            builder.append(DeviceTypeEnum.VISITATION.value())
+            builder.append("&device_name=")
+            builder.append(DeviceTypeEnum.VISITATION.typeName())
+            val code = EcodeHelper().createQRImage(builder.toString(), 160, null)
+            activity.runOnUiThread {
+                activation_qr_code?.setImageBitmap(code)
+            }
+        }.start()
+    }
+
+    private fun updateNetState() {
+        if (NetHelper.getInstance().networkType == ConnectivityManager.TYPE_WIFI) {
+            Constant.network_state = 1
+        } else if (NetHelper.getInstance().networkType == ConnectivityManager.TYPE_ETHERNET) {
+            Constant.network_state = 2
+        } else {
+            Constant.network_state = 3
+        }
+    }
+
+
+    private fun checkServer() {
+        Thread {
+            while (!serverSuccess) {
+                val okHttpClient = OkHttpClient().newBuilder()
+                        .connectTimeout(15 * 1000L, TimeUnit.MILLISECONDS)
+                        .readTimeout(15 * 1000L, TimeUnit.MILLISECONDS)
+                        .writeTimeout(15 * 1000L, TimeUnit.MILLISECONDS)
+                        .build()
+                val url: String = CommonUtils.getUrl(BaseApplication.appContext)
+                val port: String = CommonUtils.getUrlPort(BaseApplication.appContext)
+                val request = Request.Builder()
+                        .url("http://$url:$port/ncs_url/server_info")
+                        .get()
+                        .build()
+
+                try {
+                    val response = okHttpClient.newCall(request).execute()
+                    if (response != null && response.isSuccessful) {
+                        //接口数据获取成功,进入下一步获取设备信息
+                        //接口数据获取成功,检查设备是否已注册
+                        if (!TextUtils.isEmpty(Constant.DEVICE_REGISTER_ID)) {
+                            presenter.getDeviceVO(Constant.DEVICE_REGISTER_ID)
+                        }
+
+                    } else {
+
+                        //接口数据获取失败,可能服务器ip不对,尝试重新获取服务器ip
+                        val info = ServerInfoUtil.get(Constant.DEVICE_REGISTER_ID!!)
+                        checkServerInfo(info)
+                    }
+                } catch (e: Exception) {
+                    //接口数据获取失败,可能服务器ip不对,尝试重新获取服务器ip
+                    val info = ServerInfoUtil.get(Constant.DEVICE_REGISTER_ID!!)
+                    checkServerInfo(info)
+                    //e.printStackTrace()
+                }
+
+                try {
+                    Thread.sleep(30000)
+                } catch (ex: Exception) {
+                    ex.printStackTrace()
+                }
+            }
+        }.start()
+    }
+
+
+    private fun checkServerInfo(info: ThirdServerInfo?) {
+        //检查获取到的服务器ip是否可用,可用则重启app重新初始化,不可用则什么都不做,等待下次重新获取服务器ip
+        if (info != null) {
+            if (info.thirdServer == null || info.thirdServerPort == null) {
+                Log.d(TAG, "server info data null")
+                showMsgMain("get server data null")
+            } else {
+                val okHttpClient = OkHttpClient().newBuilder()
+                        .connectTimeout(15 * 1000L, TimeUnit.MILLISECONDS)
+                        .readTimeout(15 * 1000L, TimeUnit.MILLISECONDS)
+                        .writeTimeout(15 * 1000L, TimeUnit.MILLISECONDS)
+                        .build()
+                val request = Request.Builder()
+                        .url("http://${info.thirdServer}:${info.thirdServerPort}/ncs_url/server_info")
+                        .get()
+                        .build()
+
+                try {
+                    val response = okHttpClient.newCall(request).execute()
+                    if (response != null && response.isSuccessful) {
+                        //接口数据获取成功,稍后重启app
+                        serverSuccess = true
+                        CommonUtils.setUrl(activity, info.thirdServer)
+                        CommonUtils.setUrlPort(activity, info.thirdServerPort.toString())
+                        showMsgMain("restart...")
+                        handler.postDelayed({
+                            if (!cancelRestart) {
+                                AppUtils.restartApp()
+                            }
+                        }, 10000)
+                    }
+                } catch (e: Exception) {
+                    e.printStackTrace()
+                    showMsgMain("server error or net error")
+                }
+            }
+        } else {
+            Log.d(TAG, "server info null")
+            showMsgMain("get server null")
+        }
+    }
+
+    private fun showMsgMain(msg: String) {
+        runOnUiThread {
+            showMessage(msg)
+        }
+    }
+
+    override fun attachBaseContext(base: Context) {
+        val languageId: Int = SettingConfig.getLanguageId(base)
+        LocaleMangerUtils.setApplicationLanguageByIndex(base, languageId)
+        super.attachBaseContext(base)
+    }
+
+    override fun onConfigurationChanged(newConfig: Configuration) {
+        super.onConfigurationChanged(newConfig)
+        val languageId: Int = SettingConfig.getLanguageId(baseContext)
+        LocaleMangerUtils.setApplicationLanguageByIndex(baseContext, languageId)
+    }
+
+    override fun setDeviceDo(data: DeviceWatchInfoVO) {
+        serverSuccess = true
+        val intent = Intent()
+        intent.setClass(activity, VisitingActivity::class.java)
+        activity.startActivity(intent)
+        finish()
+    }
+
+    override fun setTcpServerHost(tcpSeverDTO: TcpSeverDTO) {
+
+    }
+
+    override fun setServerInfo(serverIpInfo: ServerInfo) {
+
+    }
+
+    override fun setDeviceSettingData(partSettingDO: PartSettingDO) {
+
+    }
+
+    //数据加载错误
+    override fun onError(message: String, type: Int) {
+
+    }
+    //数据加载完成
+    override fun complete(message: String, type: Int) {
+
+    }
+
+    //开始获取数据
+    override fun start() {
+        //
+    }
+
+    //网络监听
+    override fun networkMonitor(state: NetState) {
+        state.filter(onMobile = {
+
+        }, onWifi = {
+
+        }, offline = {
+
+        })
+    }
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    fun onMoonEvent(messageEvent: MessageEvent) {
+    }
+}

+ 618 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/activity/VisitingActivity.kt

@@ -0,0 +1,618 @@
+package com.wdkl.ncs.android.component.home.activity
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import android.content.pm.PackageManager
+import android.graphics.Color
+import android.media.AudioManager
+import android.net.Uri
+import android.os.Build
+import android.os.Bundle
+import android.os.Environment
+import android.provider.Settings
+import android.telephony.TelephonyManager
+import android.text.TextUtils
+import android.util.Log
+import android.view.KeyEvent
+import androidx.fragment.app.Fragment
+import com.alibaba.fastjson.JSON
+import com.enation.javashop.net.engine.model.NetState
+import com.wdkl.ncs.android.component.home.BuildConfig
+import com.wdkl.ncs.android.component.home.R
+import com.wdkl.ncs.android.component.home.databinding.ActivityHomeBinding
+import com.wdkl.ncs.android.component.home.fragment.SkyCallFragment
+import com.wdkl.ncs.android.component.home.helper.StatusBarHelper
+import com.wdkl.ncs.android.component.home.helper.SystemDialogHelper
+import com.wdkl.ncs.android.component.home.launch.VisitingLaunch
+import com.wdkl.ncs.android.component.home.service.TcpHandleService
+import com.wdkl.ncs.android.component.home.service.TcpHandleService.instance.updateLastTime
+import com.wdkl.ncs.android.component.home.settingconfig.SettingConfig
+import com.wdkl.ncs.android.component.home.util.*
+import com.wdkl.ncs.android.lib.base.BaseActivity
+import com.wdkl.ncs.android.lib.base.BaseApplication
+import com.wdkl.ncs.android.lib.utils.AppTool
+import com.wdkl.ncs.android.lib.utils.TimeHandle
+import com.wdkl.ncs.android.lib.utils.showMessage
+import com.wdkl.ncs.android.middleware.common.Constant
+import com.wdkl.ncs.android.middleware.common.MessageEvent
+import com.wdkl.ncs.android.middleware.logic.contract.home.HomeActivityContract
+import com.wdkl.ncs.android.middleware.logic.presenter.home.HomeActivityPresenter
+import com.wdkl.ncs.android.middleware.model.ServerInfo
+import com.wdkl.ncs.android.middleware.model.dos.PartSettingDO
+import com.wdkl.ncs.android.middleware.model.dto.TcpSeverDTO
+import com.wdkl.ncs.android.middleware.model.vo.DeviceWatchInfoVO
+import com.wdkl.ncs.android.middleware.tcp.TcpClient
+import com.wdkl.ncs.android.middleware.tcp.channel.DeviceChannel
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel
+import com.wdkl.ncs.android.middleware.tcp.enums.TcpAction
+import com.wdkl.ncs.janus.util.JanusConstant
+import kotlinx.android.synthetic.main.activity_home.*
+import org.greenrobot.eventbus.EventBus
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+import java.io.File
+import java.io.FileOutputStream
+import java.io.InputStream
+import java.math.BigInteger
+
+class VisitingActivity : BaseActivity<HomeActivityPresenter, ActivityHomeBinding>(), HomeActivityContract.View {
+
+    var TAG = VisitingActivity::class.java.getSimpleName()
+
+    //监听网络变化
+    lateinit var teleManager: TelephonyManager
+    private var netType: Int = -1
+
+    private var isRegister = true
+    private var inited = false
+
+    var currentFragment: Fragment? = null
+
+    private var clickTimes: Int = 1
+    private var clickTime: Long = 0
+    private var hookonTime: Long = 0
+
+    private lateinit var receiver: TimeReceiver
+
+    override fun getLayId(): Int {
+        return R.layout.activity_home
+    }
+
+    override fun bindDagger() {
+        VisitingLaunch.component.inject(this)
+    }
+
+    //初始化
+    override fun init() {
+
+        //if (Build.BOARD.equals("k37tv1_64_bsp") || Build.BOARD.equals("k37mv1_64_bsp") || Build.MODEL.equals("KT10-3F")) {
+        //    StatusBarHelper.toggleStatusBar(activity, true)
+        //}
+
+        if (!EventBus.getDefault().isRegistered(this)) {
+            EventBus.getDefault().register(this)
+        }
+
+        //APP版本
+        tv_version_name.setText("version: " + BuildConfig.VERSION_NAME)
+
+        //网络强度监听
+        teleManager = (applicationContext.getSystemService(Context.TELEPHONY_SERVICE)) as TelephonyManager
+        netType = NetHelper.getInstance().getNetworkState(applicationContext)
+        Log.i(TAG, "网络类型:" + netType)
+        /*if (netType == NetHelper.NETWORK_2G || netType == NetHelper.NETWORK_3G || netType == NetHelper.NETWORK_4G) {
+            if (teleManager != null) {
+                teleManager.listen(object : PhoneStateListener() {
+                    override fun onSignalStrengthsChanged(signalStrength: SignalStrength) {
+                        super.onSignalStrengthsChanged(signalStrength)
+                        val asu = signalStrength.gsmSignalStrength
+                        val lastSignal = -113 + 2 * asu
+                        if (lastSignal > 0) {
+                            var mobileNetworkSignal = lastSignal
+                        }
+                    }
+                }, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
+            }
+        }*/
+
+        if ("YUNPAI_H6".equals(Build.MODEL)) {
+            startYunpaiPlugin()
+        }
+
+        permissionGranted()
+    }
+
+    private fun startYunpaiPlugin() {
+        try {
+            val packageInfos = packageManager.getInstalledPackages(
+                PackageManager.GET_ACTIVITIES or
+                        PackageManager.GET_SERVICES
+            )
+            var needInstall = false
+            for (info in packageInfos) {
+                val pkg = info.packageName
+                if (pkg.equals("com.wd.app")) {
+                    //启动云派app升级监听服务
+                    val intent = Intent()
+                    intent.setClassName("com.wd.app", "com.wd.app.MyService")
+                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+                        //android8.0以上通过startForegroundService启动service
+                        startForegroundService(intent)
+                    } else {
+                        startService(intent)
+                    }
+                    Constant.yunpai_plugin = true
+                    needInstall = false
+                    break
+                } else {
+                    needInstall = true
+                }
+            }
+
+            if (needInstall) {
+                //拷贝并安装云派app升级服务apk
+                Log.d(TAG,"准备安装升级服务apk")
+                Thread{
+                    try {
+                        val fileName = "wd_update_plugin.apk"
+                        val dstPath = Environment.getExternalStorageDirectory().path + "/Download"
+                        val file = File(dstPath)
+                        if (!file.exists()) {
+                            file.mkdirs()
+                        }
+                        val outFile = File(dstPath + "/" + fileName)
+                        if (outFile.exists()) {
+                            outFile.delete()
+                        }
+                        val inputStream: InputStream = getAssets().open(fileName)
+                        val fos = FileOutputStream(outFile)
+                        val buffer = ByteArray(1024)
+                        var byteCount = 0
+                        while (inputStream.read(buffer).also { byteCount = it } != -1) {
+                            fos.write(buffer, 0, byteCount)
+                        }
+                        fos.flush()
+                        inputStream.close()
+                        fos.close()
+
+                        //apk拷贝完成,即将安装
+                        val action = "com.miki.slient.INSTALL_CUSTOMER_PACKAGES"
+                        val intent = Intent(action)
+                        intent.putExtra("apkPath", dstPath + "/" + fileName)
+                        intent.putExtra("packageName", "com.miki.sensortest")
+                        sendBroadcast(intent)
+
+                        runOnUiThread {
+                            showMessage("app升级服务正在安装,请稍后重启设备以完成升级服务启动")
+                        }
+                    } catch (e: java.lang.Exception) {
+                        e.printStackTrace()
+                    }
+                }.start()
+            }
+        } catch (t: Throwable) {
+            t.printStackTrace()
+            showMessage("启动升级插件服务失败: " + t.message)
+        }
+
+
+        if (Constant.yunpai_plugin) {
+            tv_version_name.setText("升级服务已启动 version: " + BuildConfig.VERSION_NAME)
+        } else {
+            tv_version_name.setText("升级服务未启动 version: " + BuildConfig.VERSION_NAME)
+        }
+    }
+
+    private fun permissionGranted() {
+        if (Build.VERSION.SDK_INT >= 23) {
+            if (!Settings.canDrawOverlays(this)) {
+                val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:$packageName"))
+                startActivityForResult(intent, 10)
+            }
+        }
+
+        Log.i(TAG, "IMEI " + Constant.imei)
+
+        //获取TCP服务器IP和端口
+        Thread{
+            while (isRegister) {
+                Log.i(TAG, "获取TCP服务器IP和端口")
+                presenter.getServerInfo()
+                try {
+                    Thread.sleep(30000)
+                } catch (e: Exception) {
+                    //
+                }
+            }
+        }.start()
+
+        regReceiver()
+    }
+
+    private fun regReceiver() {
+        receiver = TimeReceiver()
+        var intentFilter = IntentFilter()
+        intentFilter.addAction(Intent.ACTION_TIME_TICK)
+        registerReceiver(receiver, intentFilter)
+
+        //手柄状态监听
+        intentFilter.addAction(Constant.HOOK_OFF)
+        intentFilter.addAction(Constant.HOOK_ON)
+        registerReceiver(receiver, intentFilter)
+    }
+
+    private fun releaseReceiver(){
+        unregisterReceiver(receiver)
+    }
+
+    /**
+     * 返回的tcp信息
+     */
+    override fun setTcpServerHost(tcpSeverDTO: TcpSeverDTO) {
+
+    }
+
+    override fun setServerInfo(serverIpInfo: ServerInfo) {
+        isRegister = false
+        if(serverIpInfo.tcpLocalIp!= null && serverIpInfo.tcpPort != null && serverIpInfo.tcpIdleSeconds != null){
+            Constant.TCP_SERVER_URL = serverIpInfo.tcpLocalIp
+            Constant.TCP_PORT = serverIpInfo.tcpPort
+            Constant.TCP_HEART_BEAT = serverIpInfo.tcpIdleSeconds
+
+            JanusConstant.JANUS_URL = "ws://" + serverIpInfo.rtcLocalIp + ":" + serverIpInfo.rtcPort
+            JanusConstant.STUN_SERVER = arrayOf<String>(serverIpInfo.stunServer)
+            //JanusConstant.TURN_SERVER = data.turnServer
+
+            Thread {
+                //启动tcp连接
+                TcpClient.getInstance().init(Constant.TCP_SERVER_URL, Constant.TCP_PORT, Constant.TCP_HEART_BEAT)
+
+                //获取设备数据
+                while (!inited) {
+                    Log.i(TAG, "获取设备数据")
+                    if (!TextUtils.isEmpty(Constant.DEVICE_REGISTER_ID)) {
+                        presenter.getDeviceVO(Constant.DEVICE_REGISTER_ID)
+                    }
+
+                    try {
+                        Thread.sleep(30000)
+                    } catch (e: Exception) {
+                        //
+                    }
+                }
+            }.start()
+        }
+    }
+
+    /**
+     * 返回的设备信息
+     */
+    override fun setDeviceDo(data: DeviceWatchInfoVO) {
+        Log.i(TAG, "收到返回的设备信息 ")
+        try {
+            Constant.PART_ID = data.partId
+            Constant.DEVICE_ID = data.id
+            Constant.SIP_ID = data.sipId
+            //Constant.ethIp = data.ethIp
+            //Constant.sipIp = data.sipIp
+            Constant.sipPassword = data.sipPassword
+            Constant.userName = data.memberName
+
+            if (Constant.DEVICE_ID == -1 || TextUtils.isEmpty(Constant.SIP_ID)) {
+                showMessage("初始化数据不全,请联系管理员")
+                return
+            } else if (data.status != null && data.status == 0) {
+                showMessage("设备未启用")
+                return
+            }
+
+            inited = true
+            btn_callout.isEnabled = true
+            //watch_activity_home_linyout.visibility = View.VISIBLE
+
+            /*if ("YUNPAI_H6".equals(Build.MODEL) || "KT10-3F".equals(Build.MODEL, true)
+                || "KT10-2F".equals(Build.MODEL, true) || "KT8001-2F".equals(Build.MODEL, true)) {
+                //中兴8寸机,卡尔10寸
+                watch_activity_home_linyout.setBackgroundResource(R.drawable.main_bg_1280x800)
+                btn_callout.setBackgroundResource(R.drawable.round_button_100dp)
+                btn_callout.textSize = 36f
+            } else if ("KT8001_2C".equals(Build.MODEL, true)) {
+                //卡尔8寸竖屏
+                watch_activity_home_linyout.setBackgroundResource(R.drawable.main_bg_800x1280)
+                btn_callout.setBackgroundResource(R.drawable.round_button_80dp)
+                btn_callout.textSize = 24f
+            } else if ("rk3288".equals(Build.MODEL, true) || "m3520b_bnkj_zx".equals(Build.MODEL, true)) {
+                //亿莱顿,新豪格都是rk3288,亿莱顿在另一个分支上
+                watch_activity_home_linyout.setBackgroundResource(R.drawable.main_bg_1920x1080)
+                btn_callout.setBackgroundResource(R.drawable.round_button_100dp)
+                btn_callout.textSize = 36f
+            } else {
+                watch_activity_home_linyout.setBackgroundResource(R.drawable.main_bg)
+                btn_callout.setBackgroundResource(R.drawable.round_button_80dp)
+                btn_callout.textSize = 28f
+            }*/
+
+
+            initSDK()
+            presenter.getDeviceSettingData(Constant.PART_ID)
+
+            //tv_part_name.setText(data.hospitalName + data.partName)
+            tv_part_name.text = data.partDisplay
+
+            showMessage("初始化完成")
+
+            AppTool.Time.delay(5000) {
+                startCheckUpdate()
+            }
+        } catch (e: java.lang.Exception) {
+            showMessage("设备数据异常:" + e.message)
+        }
+    }
+
+    private fun initSDK() {
+        val intent = Intent(this, TcpHandleService::class.java)
+        startService(intent)
+    }
+
+    //开始呼叫
+    private fun startVideoCall() {
+        currentFragment = SkyCallFragment()
+        var bundle = Bundle()
+        bundle.putInt("call_state", 0)
+        bundle.putBoolean("audio_only", false)
+        currentFragment?.arguments = bundle
+        supportFragmentManager.beginTransaction()
+            .add(R.id.frame_visit, currentFragment!!)
+            .commitAllowingStateLoss()
+        //watch_activity_home_linyout.visibility = View.GONE
+    }
+
+    override fun onResume() {
+        super.onResume()
+
+        if (inited) {
+            if (Build.BOARD.equals("k37tv1_64_bsp") || Build.BOARD.equals("k37mv1_64_bsp") || Build.MODEL.equals("KT10-3F")) {
+                StatusBarHelper.toggleStatusBar(activity, false)
+            }
+        }
+    }
+
+    override fun onStop() {
+        super.onStop()
+
+        if (Build.BOARD.equals("k37tv1_64_bsp") || Build.BOARD.equals("k37mv1_64_bsp") || Build.MODEL.equals("KT10-3F")) {
+            StatusBarHelper.toggleStatusBar(activity, true)
+        }
+    }
+
+    /**
+     * 设置设备数据
+     */
+    override fun setDeviceSettingData(partSettingDO: PartSettingDO) {
+        try {
+            //分机通话音量  没做白昼区分
+            SettingConfig.setExtensionCallVolume(this, partSettingDO.dayBedVol)
+
+            VoiceManagerUtil.setCallVoice(activity, partSettingDO.dayBedVol)
+
+            VoiceManagerUtil.setSystemVoice(activity, partSettingDO.dayBedVol)
+            VoiceManagerUtil.setMusicVoice(activity, partSettingDO.dayBedVol)
+
+        } catch (ex: Exception) {
+            ex.printStackTrace()
+        }
+    }
+
+    override fun onError(message: String, type: Int) {
+    }
+
+    override fun complete(message: String, type: Int) {
+    }
+
+    override fun start() {
+    }
+
+    override fun networkMonitor(state: NetState) {
+    }
+
+    override fun destory() {
+        releaseReceiver()
+
+        if (EventBus.getDefault().isRegistered(this)) {
+            EventBus.getDefault().unregister(this)
+        }
+
+        if (Build.BOARD.equals("k37tv1_64_bsp") || Build.BOARD.equals("k37mv1_64_bsp") || Build.MODEL.equals("KT10-3F")) {
+            StatusBarHelper.toggleStatusBar(activity, true)
+        }
+    }
+
+    override fun onBackPressed() {
+        //禁用返回
+    }
+
+    override fun bindEvent() {
+        //长按检测升级
+        tv_version_name.setOnLongClickListener {
+            if (inited) {
+                if (System.currentTimeMillis() / 1000 - updateLastTime > 10) {
+                    showMessage("检查新版本")
+                    updateLastTime = System.currentTimeMillis() / 1000
+                    startCheckUpdate()
+                } else {
+                    showMessage("请10秒后再尝试")
+                }
+            } else {
+                showMessage("设备未注册")
+            }
+            return@setOnLongClickListener true
+        }
+
+        tv_version_name.setOnClickListener {
+            val time = System.currentTimeMillis()
+            if (time - clickTime < 1500) {
+                clickTimes++
+            } else {
+                clickTimes = 1
+            }
+
+            if (clickTimes > 9) {
+                val intent = Intent(activity, SystemActivity::class.java)
+                startActivity(intent)
+                clickTimes = 1
+            }
+            clickTime = time
+        }
+
+        btn_callout.setOnClickListener {
+            if (System.currentTimeMillis() - clickTime > 3000) {
+                if (Constant.TCP_CONNECTED) {
+                    startVideoCall()
+                } else {
+                    showMessage("通话服务或网络未连接,请检查网络稍后再试")
+                }
+            } else {
+                showMessage("点击太频繁")
+            }
+            clickTime = System.currentTimeMillis()
+        }
+    }
+
+    private fun startCheckUpdate() {
+        val intent = Intent()
+        intent.setClass(this, AppUpdateActivity::class.java)
+        startActivity(intent)
+    }
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    fun onMoonEvent(messageEvent: MessageEvent) {
+        if (messageEvent.type == Constant.EVENT_REMOVE_CALL_FRAGMENT) {
+            if (currentFragment != null) {
+                supportFragmentManager.beginTransaction()
+                    .remove(currentFragment!!)
+                    .commitAllowingStateLoss()
+                currentFragment = null
+            }
+            //watch_activity_home_linyout.visibility = View.VISIBLE
+            AppUtils.setAudioMode(BaseApplication.appContext, AudioManager.MODE_NORMAL)
+        } else if (messageEvent.type == Constant.EVENT_TCP_MSG) {
+            val tcp = messageEvent.getMessage() as TcpModel
+            Log.d("TCP", "received tcp action: " + tcp.action + ", type: " + tcp.type)
+            if (tcp.action == TcpAction.DataAction.REFRESH) {
+                if (!TextUtils.isEmpty(Constant.DEVICE_REGISTER_ID)) {
+                    presenter.getDeviceVO(Constant.DEVICE_REGISTER_ID)
+                }
+            } else if (tcp.action == TcpAction.TimeAction.SYNC) {
+                var time = 0L
+                var timeZone="Asia/Shanghai"
+                if (canParseJson(tcp.data.toString())) {
+                    val json = JSON.parseObject(tcp.data.toString())
+                    time = json.getLong("time")*1000
+                    timeZone = json.getString("time_zone")
+                } else {
+                    time = tcp.data.toString().toLong() * 1000
+                }
+
+                try {
+                    AppUtils.setSystemTime(BaseApplication.appContext, time, timeZone)
+                    Log.d("setTime", "set sys time1: $time, $timeZone")
+                } catch (e: Exception) {
+                    //"20211213:092314"
+                    val timeStr = TimeHandle.getDateTime(time, "yyyyMMdd.HHmmss")
+                    AppUtils.setSysTime(timeStr, timeZone)
+                    Log.d("setTime", "set sys time2: $timeStr, $timeZone")
+                }
+            } else if (tcp.action == TcpAction.DeviceAction.SERVER_CHANGE) {
+                EventBus.getDefault().post(MessageEvent(tcp, Constant.EVENT_SERVER_CHANGE))
+            } else if (tcp.action == TcpAction.DeviceAction.APP_UPDATE) {
+                EventBus.getDefault().post(MessageEvent(tcp, Constant.EVENT_APP_UPDATE))
+            }
+        } else if (messageEvent.type == Constant.EVENT_TCP_STATE) {
+            if (Constant.TCP_CONNECTED) {
+                tv_rtc_status.setBackgroundColor(Color.GREEN)
+            } else {
+                tv_rtc_status.setBackgroundColor(Color.RED)
+            }
+        }
+    }
+
+    private fun canParseJson(str:String) : Boolean {
+        var result = false
+        try {
+            JSON.parseObject(str)
+            result=true
+        }catch (e:java.lang.Exception){
+            result=false
+        }
+        return result
+    }
+
+    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
+        Log.d(TAG, "keyDown ====> keyCode: $keyCode, action: ${event?.action}")
+        if (keyCode == 135) {
+            //手柄拿起
+            Log.e(TAG,"手柄拿起 ")
+            Constant.hookOn = false
+            AppUtils.switchAudioMode(activity, false)
+        } else if (keyCode == 134) {
+            //手柄放下
+            Log.e(TAG,"手柄放下 ")
+            Constant.hookOn = true
+            AppUtils.switchAudioMode(activity, true)
+            if (System.currentTimeMillis() - hookonTime > 2000) {
+                if (Constant.CALL_STATE == Constant.CALL_OUTGOING) {
+                    //呼出取消
+                    Constant.CALL_STATE = Constant.CALL_STANDBY
+                    DeviceChannel.calling = false
+                    EventBus.getDefault().post(MessageEvent("cancel", Constant.EVENT_END_CALL))
+                } else if (Constant.CALL_STATE == Constant.CALL_CALLING) {
+                    Constant.CALL_STATE = Constant.CALL_STANDBY
+                    DeviceChannel.calling = false
+                    EventBus.getDefault().post(MessageEvent("handoff", Constant.EVENT_END_CALL))
+                }
+
+                hookonTime = System.currentTimeMillis()
+            }
+        }
+        return super.onKeyDown(keyCode, event)
+    }
+
+
+    inner class TimeReceiver: BroadcastReceiver() {
+        override fun onReceive(context: Context, intent: Intent) {
+            if (intent.action == Intent.ACTION_TIME_TICK) {
+                if (inited) {
+                    if (Constant.TCP_CONNECTED) {
+                        tv_rtc_status.setBackgroundColor(Color.GREEN)
+                    } else {
+                        tv_rtc_status.setBackgroundColor(Color.RED)
+                    }
+                }
+            } else if (intent.action == Constant.HOOK_ON) {
+                Log.e(TAG,"手柄放下 ")
+                Constant.hookOn = true
+                AppUtils.switchAudioMode(activity, true)
+                if (System.currentTimeMillis() - hookonTime > 2000) {
+                    if (Constant.CALL_STATE == Constant.CALL_OUTGOING) {
+                        //呼出取消
+                        Constant.CALL_STATE = Constant.CALL_STANDBY
+                        DeviceChannel.calling = false
+                        EventBus.getDefault().post(MessageEvent("cancel", Constant.EVENT_END_CALL))
+                    } else if (Constant.CALL_STATE == Constant.CALL_CALLING) {
+                        Constant.CALL_STATE = Constant.CALL_STANDBY
+                        DeviceChannel.calling = false
+                        EventBus.getDefault().post(MessageEvent("handoff", Constant.EVENT_END_CALL))
+                    }
+
+                    hookonTime = System.currentTimeMillis()
+                }
+            } else if (intent.action == Constant.HOOK_OFF) {
+                Log.e(TAG,"手柄拿起 ")
+                Constant.hookOn = false
+                AppUtils.switchAudioMode(activity, false)
+            }
+        }
+    }
+}

+ 56 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/adapter/NumAdapter.java

@@ -0,0 +1,56 @@
+package com.wdkl.ncs.android.component.home.adapter;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.TextView;
+
+import com.wdkl.ncs.android.component.home.R;
+
+public class NumAdapter extends BaseAdapter {
+    private String[] num;
+    private Context context;
+
+    public NumAdapter(String[] numbers, Context context) {
+        this.num = numbers;
+        this.context = context;
+    }
+
+
+    @Override
+    public int getCount() {
+        return num.length;
+    }
+
+    @Override
+    public Object getItem(int position) {
+        return num[position];
+    }
+
+    @Override
+    public long getItemId(int position) {
+        return position;
+    }
+
+    @Override
+    public View getView(int position, View convertView, ViewGroup parent) {
+        ViewHolder viewHolder;
+        if (convertView == null) {
+            convertView = LayoutInflater.from(context).inflate(R.layout.digital_item, null);
+            viewHolder = new ViewHolder();
+            viewHolder.numTv = convertView.findViewById(R.id.tv_number);
+            convertView.setTag(viewHolder);
+        } else {
+            viewHolder = (ViewHolder) convertView.getTag();
+        }
+        viewHolder.numTv.setText(num[position]);
+
+        return convertView;
+    }
+
+    static class ViewHolder {
+        TextView numTv;
+    }
+}

+ 22 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/broadcast/WdBootReceiver.java

@@ -0,0 +1,22 @@
+package com.wdkl.ncs.android.component.home.broadcast;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+import com.wdkl.ncs.android.component.home.activity.VisitingActivity;
+import com.wdkl.ncs.android.component.welcome.activity.WelcomeActivity;
+
+public class WdBootReceiver extends BroadcastReceiver {
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
+            Log.d("wdBoot", "收到开机广播,启动app");
+            Intent startIntent= new Intent(context, WelcomeActivity.class);
+            startIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            context.startActivity(startIntent);
+        }
+    }
+}

+ 24 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/di/VisitingComponent.kt

@@ -0,0 +1,24 @@
+package com.wdkl.ncs.android.component.home.di
+
+import com.wdkl.ncs.android.component.home.activity.*
+import com.wdkl.ncs.android.middleware.di.ApplicationComponent
+import dagger.Component
+
+/**
+ * @author LDD
+ * @Date   2018/1/22 下午2:43
+ * @From   com.wdkl.ncs.android.component.home.di
+ * @Note   依赖注入入口
+ */
+@Component(dependencies = arrayOf(ApplicationComponent::class))
+interface VisitingComponent {
+    fun inject(activity: VisitingActivationActivity)
+
+    fun inject(activity: VisitingActivity)
+
+    fun inject(activity: AppUpdateActivity)
+
+    fun inject(activity: SystemActivity)
+
+    fun inject(activity: TextActivity)
+}

+ 138 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/fragment/BaseCallFragment.kt

@@ -0,0 +1,138 @@
+package com.wdkl.ncs.android.component.home.fragment
+
+import android.os.Bundle
+import android.os.CountDownTimer
+import android.view.LayoutInflater
+import android.view.MotionEvent
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import androidx.fragment.app.Fragment
+import com.enation.javashop.utils.base.tool.BaseToolActivity
+import com.wdkl.ncs.android.lib.utils.showMessage
+import com.wdkl.ncs.android.middleware.common.Constant
+import com.wdkl.ncs.android.middleware.common.MessageEvent
+import com.wdkl.ncs.android.middleware.tcp.channel.DeviceChannel
+import com.wdkl.ncs.android.middleware.utils.RingPlayHelper
+import org.greenrobot.eventbus.EventBus
+
+abstract class BaseCallFragment: Fragment(), View.OnTouchListener {
+
+    private var layout: View? = null
+
+    protected lateinit var baseActivity: BaseToolActivity
+
+    //通话状态:0-去电, 1-来电
+    protected var callState : Int = 0
+    protected var onlyAudio: Boolean = false
+    //来电设备id
+    protected var fromId: Int = -1
+    protected var interactionId: Int? = -1
+    protected var targetId: String? = null
+
+    //计时器
+    lateinit var countDownTimer: CountDownTimer
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        retainInstance = true
+        callState = requireArguments().getInt("call_state")
+        onlyAudio = requireArguments().getBoolean("audio_only")
+        fromId = requireArguments().getInt("fromId")
+        interactionId = requireArguments().getInt("interactionId")
+        targetId = requireArguments().getString("targetId")
+    }
+
+    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+        if (layout == null) {
+            layout = inflater.inflate(getLayId(), null)
+        }
+
+        /**初始化宿主Activity*/
+        baseActivity = getActivity() as BaseToolActivity
+
+        return layout
+    }
+
+    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+        super.onViewCreated(view, savedInstanceState)
+
+        init()
+        bindEvent()
+
+        view.setOnTouchListener(this)
+    }
+
+    override fun onDestroyView() {
+        super.onDestroyView()
+        destroy()
+    }
+
+    override fun onStart() {
+        EventBus.getDefault().register(this)
+        super.onStart()
+    }
+
+    override fun onStop() {
+        EventBus.getDefault().unregister(this)
+        super.onStop()
+    }
+
+    override fun onTouch(v: View?, event: MotionEvent?): Boolean {
+        return true
+    }
+
+    protected abstract fun getLayId(): Int
+
+    protected abstract fun init()
+
+    protected abstract fun bindEvent()
+
+    protected abstract fun destroy()
+
+    protected abstract fun callEnd(handoff: Boolean)
+
+    protected abstract fun cancelVideoCall()
+
+    //初始化计时器
+    protected fun initCountDownTimer(view: TextView) {
+        countDownTimer = object: CountDownTimer(60000, 1000) {
+            override fun onTick(millisUntilFinished: Long) {
+                if (view != null) {
+                    val time = millisUntilFinished/1000
+                    view.setText("倒计时: " + time + "秒")
+                }
+            }
+
+            override fun onFinish() {
+                //呼叫超时,返回到主界面
+                RingPlayHelper.stopRingTone()
+                showMessage("无人应答...")
+                DeviceChannel.calling = false
+                Constant.CALL_STATE = Constant.CALL_STANDBY
+                cancelVideoCall()
+                callEnd(false)
+            }
+        }
+    }
+
+    //开始计时
+    protected fun startTimer() {
+        if (countDownTimer != null) {
+            countDownTimer.start()
+        }
+    }
+
+    //取消计时器
+    protected fun cancelTimer() {
+        if (countDownTimer != null) {
+            countDownTimer.cancel()
+        }
+    }
+
+    //返回主界面
+    protected fun backToMain() {
+        EventBus.getDefault().post(MessageEvent("back_to_main", Constant.EVENT_REMOVE_CALL_FRAGMENT))
+    }
+
+}

+ 512 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/fragment/SkyCallFragment.kt

@@ -0,0 +1,512 @@
+package com.wdkl.ncs.android.component.home.fragment
+
+import android.media.AudioManager
+import android.os.Build
+import android.os.Handler
+import android.os.Looper
+import android.os.SystemClock
+import android.util.Log
+import android.view.View
+import android.view.ViewGroup
+import android.widget.SeekBar
+import com.google.gson.Gson
+import com.wdkl.ncs.android.component.home.R
+import com.wdkl.ncs.android.component.home.settingconfig.SettingConfig
+import com.wdkl.ncs.android.component.home.util.AppUtils
+import com.wdkl.ncs.android.component.home.util.Util
+import com.wdkl.ncs.android.component.home.util.VoiceManagerUtil
+import com.wdkl.ncs.android.lib.base.BaseApplication
+import com.wdkl.ncs.android.lib.utils.AppTool
+import com.wdkl.ncs.android.lib.utils.showMessage
+import com.wdkl.ncs.android.middleware.common.Constant
+import com.wdkl.ncs.android.middleware.common.MessageEvent
+import com.wdkl.ncs.android.middleware.model.vo.InteractionVO
+import com.wdkl.ncs.android.middleware.tcp.TcpClient
+import com.wdkl.ncs.android.middleware.tcp.channel.DeviceChannel
+import com.wdkl.ncs.android.middleware.tcp.channel.VideoUtil
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel
+import com.wdkl.ncs.android.middleware.tcp.enums.RoleTypeEnum
+import com.wdkl.ncs.android.middleware.tcp.enums.TcpAction
+import com.wdkl.ncs.android.middleware.utils.RingPlayHelper
+import com.wdkl.ncs.janus.client.CallSessionCallback
+import com.wdkl.ncs.janus.client.JanusClient
+import com.wdkl.ncs.janus.client.VideoRoomCallback
+import com.wdkl.ncs.janus.entity.Room
+import com.wdkl.ncs.janus.rtc.WebRTCEngine
+import com.wdkl.ncs.janus.util.EnumType
+import com.wdkl.ncs.janus.util.JanusConstant
+import kotlinx.android.synthetic.main.sky_voice_call_layout.*
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+import org.webrtc.SurfaceViewRenderer
+import java.math.BigInteger
+
+class SkyCallFragment: BaseCallFragment(), CallSessionCallback {
+    private val TAG = "SkyCallFragment"
+
+    private var localSurfaceView: SurfaceViewRenderer? = null
+    private var remoteSurfaceView: SurfaceViewRenderer? = null
+
+    private val handler = Handler(Looper.getMainLooper())
+
+    private var callEnded: Boolean = false
+    private var outGoing: Boolean = false
+    private var tid: String? = ""
+
+    private var janusClient: JanusClient? = null
+    private var room: Room?=null
+    private var videoRoomCallback: VideoRoomCallback? = null
+
+    private var callSuccess: Boolean = false
+    private var micMute: Boolean = false // 是否关闭麦克风
+
+    private var volume = 60
+
+    override fun getLayId(): Int {
+        /*if ("YUNPAI_H6".equals(Build.MODEL, true) || "rk3288".equals(Build.MODEL, true)
+            || "KT10-3F".equals(Build.MODEL, true) || "KT10-2F".equals(Build.MODEL, true)
+            || "KT8001-2F".equals(Build.MODEL, true)) {
+            return R.layout.sky_voice_call_layout_land
+        } else if ("m3520b_bnkj_zx".equals(Build.MODEL, true)) {
+            return R.layout.sky_voice_call_layout_land_1920
+        } else {
+            return R.layout.sky_voice_call_layout
+        }*/
+
+        return R.layout.sky_voice_call_layout
+    }
+
+    override fun init() {
+        //初始化计时器
+        initCountDownTimer(sky_voice_call_timeout)
+
+        //初始化 engine
+        WebRTCEngine.getInstance().init(false, this.context)
+
+        volume = SettingConfig.getExtensionCallVolume(activity)
+        if (volume < 0 || volume > 100) {
+            volume = 60
+        }
+        call_volume_bar.progress = volume/10
+        tv_volume.text = "" + volume/10
+
+        VoiceManagerUtil.setCallVoice(activity, volume)
+
+        if (Constant.hookOn) {
+            //手柄放下,免提模式
+            AppUtils.switchAudioMode(activity, true)
+        } else {
+            //手柄拿起,听筒模式
+            AppUtils.switchAudioMode(activity, false)
+        }
+
+        //初始化 janusClient
+        janusClient = JanusClient(JanusConstant.JANUS_URL, Constant.SIP_ID!!.toBigInteger())
+
+        when (callState) {
+            0 -> {
+                //发起通话
+                outGoing = true
+                startOutgoing()
+                RingPlayHelper.playRingTone(baseActivity, R.raw.ring_back2, true, 60000)
+
+                janusClient!!.callState = EnumType.CallState.Outgoing
+                room = Room(Constant.SIP_ID!!.toBigInteger())
+            }
+
+            1 -> {
+                //接受通话
+            }
+        }
+
+
+        videoRoomCallback = VideoRoomCallback(janusClient, room, Constant.SIP_ID!!.toBigInteger())
+        videoRoomCallback!!.callSessionCallback = this
+        janusClient!!.setJanusCallback(videoRoomCallback)
+    }
+
+    override fun bindEvent() {
+        //通话挂断
+        sky_voice_call_hangup.setOnClickListener {
+            RingPlayHelper.stopRingTone()
+            if (Constant.CALL_STATE == Constant.CALL_CALLING) {
+                //结束sip通话
+                Constant.CALL_STATE = Constant.CALL_STANDBY
+                if (sky_voice_call_timer != null) {
+                    sky_voice_call_timer.stop()
+                }
+
+                callEnd(true)
+            } else {
+                Constant.CALL_STATE = Constant.CALL_STANDBY
+                DeviceChannel.calling = false
+                cancelVideoCall()
+                cancelCall()
+            }
+        }
+
+        sky_voice_call_mute.setOnClickListener {
+            micMute = !micMute
+            Log.d(TAG,"静音切换$micMute")
+
+            WebRTCEngine.getInstance().muteAudio(micMute)
+            sky_voice_call_mute.isSelected = micMute
+        }
+
+        call_volume_bar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener{
+            override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
+                tv_volume.text = "" + progress
+                if (seekBar!!.progress <= 1) {
+                    tv_volume.text = "1"
+                } else {
+                    tv_volume.text = "" + progress
+                }
+            }
+
+            override fun onStartTrackingTouch(seekBar: SeekBar?) {
+                //
+            }
+
+            override fun onStopTrackingTouch(seekBar: SeekBar?) {
+                if (seekBar!!.progress <= 2) {
+                    VoiceManagerUtil.setCallVoice(activity, 20)
+                } else {
+                    VoiceManagerUtil.setCallVoice(activity, seekBar.progress*10)
+                }
+            }
+        })
+    }
+
+    override fun destroy() {
+        DeviceChannel.calling = false
+        cancelTimer()
+        Constant.CALL_STATE = Constant.CALL_STANDBY
+        if (sky_voice_call_timer != null) {
+            sky_voice_call_timer.stop()
+        }
+        RingPlayHelper.stopRingTone()
+        AppUtils.setAudioMode(BaseApplication.appContext, AudioManager.MODE_NORMAL)
+    }
+
+    private fun startOutgoing() {
+        callSuccess = false
+        sky_voice_call_hangup.isEnabled = false
+        val callTcp = VideoUtil.videoOutCall(Constant.DEVICE_ID, RoleTypeEnum.NURSE.name)
+        TcpClient.getInstance().sendMsg(callTcp.toJson())
+
+        DeviceChannel.calling = true
+        Constant.CALL_STATE = Constant.CALL_OUTGOING
+        sky_voice_call_timeout.visibility = View.VISIBLE
+        sky_voice_call_timer.visibility = View.GONE
+        startTimer()
+
+        AppTool.Time.delay(5000) {
+            Log.d("tcp", "call success: $callSuccess")
+            if (!callSuccess && !callEnded) {
+                //呼叫失败
+                showMessage("呼叫失败,服务器无响应或网络故障!")
+                RingPlayHelper.stopRingTone()
+                cancelCall()
+            }
+        }
+    }
+
+    override fun cancelVideoCall() {
+        val cancelTcp = VideoUtil.videoCancelCall(tid, Constant.DEVICE_ID, Constant.interactionId)
+        TcpClient.getInstance().sendMsg(cancelTcp.toJson())
+    }
+
+    //去电界面
+    private fun showOutgoingCall() {
+        Constant.CALL_STATE = Constant.CALL_OUTGOING
+        sky_voice_call_calling_text.text = "正在呼叫,等待接听..."
+        sky_voice_call_outgoing.visibility = View.VISIBLE
+        sky_voice_call_incoming.visibility = View.GONE
+
+        fullscreen_video_frame.visibility = View.VISIBLE
+        pip_video_frame.visibility = View.VISIBLE
+    }
+
+    //呼叫取消
+    private fun cancelCall() {
+        cancelTimer()
+        DeviceChannel.calling = false
+        Constant.CALL_STATE = Constant.CALL_STANDBY
+        callEnd(false)
+    }
+
+    private fun showCalling(audioOnly: Boolean) {
+        if (audioOnly) {
+            ll_voice_call.visibility = View.VISIBLE
+        } else {
+            //显示视频画面
+            fullscreen_video_frame.visibility = View.VISIBLE
+            pip_video_frame.visibility = View.VISIBLE
+            ll_voice_call.visibility = View.GONE
+        }
+
+        cancelTimer()
+        sky_voice_call_calling_text.text = "通话中..."
+        sky_voice_call_timer.visibility = View.VISIBLE
+        sky_voice_call_timer.base = SystemClock.elapsedRealtime()
+        sky_voice_call_timer.start()
+        sky_voice_call_mute.visibility = View.VISIBLE
+        ll_voice_volume_bar.visibility = View.VISIBLE
+    }
+
+    //通话结束
+    override fun callEnd(handoff: Boolean) {
+        synchronized(this) {
+            if (callEnded) {
+                return
+            }
+            callEnded = true
+            DeviceChannel.calling = false
+            Constant.CALL_STATE = Constant.CALL_STANDBY
+            if (sky_voice_call_timer != null) {
+                sky_voice_call_timer.stop()
+            }
+
+            Log.e(TAG, "call end !!!!!!!!!!!!!!!!!!")
+            if (handoff) {
+                val handoffTcp = VideoUtil.videoHandoff(tid, Constant.DEVICE_ID, Constant.visitHostId, Constant.interactionId)
+                TcpClient.getInstance().sendMsg(handoffTcp.toJson())
+            }
+
+            if (janusClient != null && janusClient!!.webSocketChannel != null) {
+                janusClient!!.callState = EnumType.CallState.Idle
+                if (outGoing) {
+                    janusClient!!.destroyRoom(janusClient!!.currentHandleId, null)
+                } else {
+                    janusClient!!.leaveRoom()
+                }
+
+                janusClient!!.setJanusCallback(null)
+                janusClient!!.disConnect()
+            }
+
+            Constant.interactionId = null
+
+            backToMain()
+        }
+    }
+
+
+    /********************************************************
+     ********************* webrtc通话回调 ********************
+     * 注意: 如涉及到UI更新的需要在主线程处理,务必注意
+     *******************************************************/
+    override fun didChangeState(var1: EnumType.CallState?) {
+        Log.e(TAG, "didChangeState: $var1")
+        if (var1 == EnumType.CallState.Connected) {
+            handler.post {
+                RingPlayHelper.stopRingTone()
+                //更新界面显示
+                showCalling(false)
+            }
+        }
+    }
+
+    override fun didDisconnected(userId: String?) {
+        Log.w(TAG, "didDisconnected: $userId")
+        handler.post {
+            showMessage("$userId 失去连接")
+            callEnd(true)
+        }
+    }
+
+    override fun didError(error: String?) {
+        Log.e(TAG, "didError: $error")
+        handler.post {
+            showMessage("通话错误")
+            callEnd(true)
+        }
+    }
+
+    override fun didHangUp(handlerId: BigInteger?) {
+        Log.e("hangup", "socket hangup")
+        handler.post {
+            callEnd(true)
+        }
+    }
+
+    override fun didRoomCreated() {
+        //
+    }
+
+    //处理本地视频画面
+    override fun didCreateLocalVideoTrack() {
+        Log.e(TAG, "didCreateLocalVideoTrack")
+        handler.post {
+            if (!callEnded) {
+                if (localSurfaceView == null) {
+                    val surfaceView = WebRTCEngine.getInstance().startPreview(true)
+                    Log.e(TAG, "didCreateLocalVideoTrack surfaceView: $surfaceView")
+                    if (surfaceView != null) {
+                        localSurfaceView = surfaceView as SurfaceViewRenderer
+                    } else {
+                        callEnd(true)
+                    }
+                } else {
+                    localSurfaceView!!.setZOrderMediaOverlay(true)
+                }
+
+                if (localSurfaceView!!.parent != null) {
+                    (localSurfaceView!!.parent as ViewGroup).removeView(localSurfaceView)
+                }
+
+                if (fullscreen_video_frame != null) {
+                    if (fullscreen_video_frame.getChildCount() != 0) {
+                        fullscreen_video_frame.removeAllViews()
+                    }
+                    fullscreen_video_frame.addView(localSurfaceView)
+                }
+            }
+        }
+    }
+
+    override fun didReceiveRemoteVideoTrack(userId: BigInteger?) {
+        Log.e(TAG, "didReceiveRemoteVideoTrack==  userId: $userId, hostSip: ${Constant.hostSipId}")
+        handler.post {
+            if (!callEnded) {
+                if (Constant.hostSipId!!.toBigInteger() != userId) {
+                    //本地画面
+                    Log.e(TAG, "didReceiveRemoteVideoTrack, local surfaceView = $localSurfaceView")
+                    if (localSurfaceView != null) {
+                        localSurfaceView!!.setZOrderMediaOverlay(true)
+                        if (outGoing) {
+                            if (localSurfaceView!!.parent != null) {
+                                (localSurfaceView!!.parent as ViewGroup).removeView(localSurfaceView)
+                            }
+                            if (pip_video_frame != null) {
+                                pip_video_frame.addView(localSurfaceView)
+                            }
+                        }
+                    }
+
+                    //远端画面
+                    val surfaceView = WebRTCEngine.getInstance().setupRemoteVideo(userId, false)
+                    Log.e(TAG, "didReceiveRemoteVideoTrack, remote surfaceView = $surfaceView")
+                    if (surfaceView != null && fullscreen_video_frame != null) {
+                        remoteSurfaceView = surfaceView as SurfaceViewRenderer
+                        fullscreen_video_frame.removeAllViews()
+                        if (remoteSurfaceView!!.parent != null) {
+                            (remoteSurfaceView!!.parent as ViewGroup).removeView(remoteSurfaceView)
+                        }
+                        fullscreen_video_frame.addView(remoteSurfaceView)
+                    }
+                } else {
+                    showMessage("主机已接听")
+                }
+            }
+        }
+    }
+
+    override fun didCallEndWithReason(callEndReason: EnumType.CallEndReason?) {
+        handler.post {
+            callEnd(true)
+        }
+    }
+
+    override fun didChangeMode(isAudioOnly: Boolean) {
+        handler.post {
+            //
+        }
+    }
+
+    override fun didUserLeave(userId: BigInteger?) {
+        Log.w(TAG, "didUserLeave: $userId")
+        handler.post {
+            callEnd(true)
+        }
+    }
+
+
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    fun onMoonEvent(messageEvent: MessageEvent) {
+        if (messageEvent.type == Constant.EVENT_TCP_MSG){
+            val tcpModel = messageEvent.getMessage() as TcpModel
+            var interactionVO: InteractionVO? = null
+            if (tcpModel.data != null) {
+                interactionVO = Gson().fromJson(tcpModel.data.toString(), InteractionVO::class.java)
+            }
+            Log.e(TAG, "收到tcp消息: " + tcpModel.getType() + " " + tcpModel.getAction())
+            when (tcpModel.action){
+                TcpAction.VideoAction.CALLING->{
+                    //我方呼出,对方通话中
+                    AppTool.Time.delay(3000) {
+                        RingPlayHelper.stopRingTone()
+                        cancelCall()
+                        showMessage("对方忙线中!")
+                    }
+                }
+
+                TcpAction.VideoAction.FAILED->{
+                    //我方呼出,对方不在线,设备离线或其它错误
+                    callSuccess = true
+                    AppTool.Time.delay(3000) {
+                        RingPlayHelper.stopRingTone()
+                        cancelCall()
+                        showMessage("呼叫失败,找不到设备或对方不在线!")
+                    }
+                }
+
+                TcpAction.VideoAction.SUCCESS->{
+                    tid = tcpModel.tid
+                    callSuccess = true
+                    DeviceChannel.calling = true
+                    if (interactionVO != null) {
+                        Constant.interactionId = interactionVO.id
+                    }
+                    Constant.visitHostId = tcpModel.fromId
+                    Util.wakeUpAndUnlock(BaseApplication.appContext)
+                    sky_voice_call_hangup.isEnabled = true
+                    showOutgoingCall()
+                    janusClient!!.connect(-1, false)
+                }
+
+                TcpAction.VideoAction.ACCEPT-> {
+                   //
+                }
+
+                //主机接听
+                TcpAction.VideoAction.VIDEO_IN_CALL-> {
+                    if (interactionVO != null) {
+                        Constant.hostSipId = interactionVO.toSipId
+                    }
+                }
+
+                TcpAction.VideoAction.VIDEO_ON -> {
+                    //
+                }
+
+                TcpAction.VideoAction.REJECT->{
+                    //我方呼出,对方拒绝
+                    AppTool.Time.delay(1000) {
+                        RingPlayHelper.stopRingTone()
+                        cancelCall()
+                        showMessage("对方拒绝!")
+                    }
+                }
+
+                TcpAction.VideoAction.HANDOFF -> {
+                    if (interactionVO != null && Constant.interactionId == interactionVO.id) {
+                        callEnd(false)
+                    }
+                }
+            }
+        } else if (messageEvent.type == Constant.EVENT_END_CALL) {
+            if (messageEvent.getMessage() is String) {
+                val str = messageEvent.getMessage() as String
+                if (str.equals("cancel")) {
+                    cancelVideoCall()
+                    callEnd(false)
+                } else {
+                    callEnd(true)
+                }
+            }
+        }
+    }
+
+}

+ 62 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/hardware/HardTools.java

@@ -0,0 +1,62 @@
+package com.wdkl.ncs.android.component.home.hardware;
+
+import android.app.Activity;
+import android.app.Application;
+import android.content.Context;
+
+public  class HardTools {
+
+    public HardTools() {
+
+    }
+    //初始化
+    public void init(){}
+    //退出
+    public void unInit(){}
+    //led初始化
+    public void LEDinit(){}
+    //是否卸载旧版本
+    public void uninstallApp(Context context , boolean isuninstall, String name){}
+    //串口设置
+    public void setSerial(Activity activity){}
+    //导航栏隐藏或者显示
+    public void toggleStatusBar(Context context,boolean is){}
+
+    public void setAudioMute(Context context,boolean mute){}
+
+    public void setAudioMode(Context context,int mode){}
+
+    //检查launch版本
+    public void checkLaunch(){}
+    //紧急按钮Start
+    public void setSOSStart(){}
+    //紧急按钮Stop
+    public void setSOSStop(){}
+    //门灯颜色
+    public void setDoorLight(int type){}
+    //重置设备
+    public void resetDevice(){}
+    //重置设备 XCrashUtils
+    public void resetDevicex(Application application){}
+    //注册方式
+    public void Registration(Context context){}
+    //安装方式1
+    public void installApk(Activity activity){}
+    //安装方式2
+    public void startInstallApk(Activity activity){}
+
+
+    //提供卡号
+    public  void offerCardData(String data){}
+    //提供按键数据
+    public void offerKeyBoardData(String data){}
+    //是否开启灯光
+    public  void enableLed(boolean isEnable){}
+    public  void enableIRLed(boolean isEnable){}
+    public  void enableControlLed(boolean isEnable,int id){}
+    //麦克风
+    public void enalbeNet(boolean isEnable){}
+    //设置voip 初始化配置
+    public void setVoipConfig(){}
+
+}

+ 30 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/hardware/HardWareFactroy.java

@@ -0,0 +1,30 @@
+package com.wdkl.ncs.android.component.home.hardware;
+
+import com.wdkl.ncs.android.component.home.BuildConfig;
+import com.wdkl.ncs.android.component.home.hardware.imp.CommonHardTools;
+import com.wdkl.ncs.android.component.home.hardware.imp.Z3128HardTools;
+import com.wdkl.ncs.android.component.home.hardware.imp.ZKEHardTools;
+import com.wdkl.ncs.android.middleware.common.Constant;
+
+/**
+ * 硬件设备控制适配类
+ *
+ * **/
+public  class HardWareFactroy {
+    //不同硬件设备控制类替换即可
+    private static HardTools hardTools;
+    public static HardTools getHardTools() {
+        if(null == hardTools) {
+            if( BuildConfig.flag.equals(Constant.DEV_Z_RK3128)) {
+                hardTools = Z3128HardTools.getInstance();
+            } else if(BuildConfig.flag.equals(Constant.DEV_W_KAER)){
+                hardTools = ZKEHardTools.getInstance();
+            } else {
+                hardTools = CommonHardTools.getInstance();
+            }
+        }
+        return hardTools ;
+    }
+
+
+}

+ 140 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/hardware/imp/A133HardTools.java

@@ -0,0 +1,140 @@
+package com.wdkl.ncs.android.component.home.hardware.imp;
+
+import android.app.Application;
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.util.Log;
+
+import com.wdkl.ncs.android.component.home.hardware.HardTools;
+import com.wdkl.ncs.android.component.home.helper.AppUpdateHelper;
+import com.wdkl.ncs.android.component.home.util.VoiceManagerUtil;
+import com.wdkl.ncs.android.lib.base.BaseApplication;
+import com.wdkl.ncs.android.lib.utils.AppTool;
+import com.wdkl.ncs.android.middleware.common.Constant;
+import com.wdkl.ncs.android.middleware.utils.AppUtil;
+
+import java.util.List;
+
+import kotlin.Unit;
+import kotlin.jvm.functions.Function0;
+
+/**
+ * W——KR主机硬件控制类
+ *
+ * */
+public class A133HardTools extends HardTools {
+
+    public static final String HARDWDT_SERVICE = "A133HardTools";
+    private Application app;
+
+    //private ZhylManager zhylManager;
+
+    private static class A133HardToolsHolder{
+        private final  static A133HardTools a133HardTools = new A133HardTools();
+    }
+
+    public static A133HardTools getInstance(){
+        return A133HardToolsHolder.a133HardTools;
+    }
+
+    @Override
+    public void init() {
+
+    }
+
+    @Override
+    public void unInit() {
+
+    }
+
+    @Override
+    public void resetDevice() {
+//        SerialPortHelper.resetDevice();
+    }
+
+    @Override
+    public void setAudioMode(Context context, int mode) {
+
+    }
+
+    @Override
+    public void setAudioMute(Context context, boolean mute) {
+        //VoiceManagerUtil.setAudioMute(BaseApplication.appContext, mute);
+    }
+
+    @Override
+    public void resetDevicex(Application application) {
+        AppUpdateHelper.reboot(application);
+    }
+    @Override
+    public void Registration(Context context) {
+        /*try {
+            ZhylManager zhylManager = ZhylManager.getInstance(BaseApplication.appContext);
+            //设置开机自启动
+            zhylManager.sys_setSystemBootApp("com.wdkl.app.ncs.callingdoor/com.wdkl.ncs.android.component.welcome.activity.WelcomeActivity");
+            //隐藏虚拟导航栏
+            zhylManager.disp_setNavigationBar(false);
+
+            //切换mic
+            if (!zhylManager.sys_getMICEnable()) {
+                zhylManager.sys_setMICEnable(true);
+                AppTool.Time.delay(10000, new Function0<Unit>() {
+                    @Override
+                    public Unit invoke() {
+                        zhylManager.sys_setReboot();
+                        return null;
+                    }
+                });
+            }
+            Constant.LOCAL_MAC = zhylManager.net_getMacAddress("eth0");
+            Constant.DEVICE_REGISTER_ID = Constant.LOCAL_MAC;
+        } catch (Exception e) {
+            //异常处理
+        }*/
+    }
+
+    @Override
+    public void uninstallApp(Context context, boolean isuninstall, String name) {
+        //卸载原来二代系统apk
+        if (isuninstall) {
+            Thread thread = new Thread(new Runnable() {
+                @Override
+                public void run() {
+                    // 在子线程中执行的代码
+                    if (checkAppExist(context,name)) {
+                        AppUtil.uninstallApp(name);
+                    }
+                }
+            });
+        }
+    }
+
+    @Override
+    public void setSOSStart() {
+//        SOSHelper.sosStart();
+    }
+
+    @Override
+    public void setSOSStop() {
+//        SOSHelper.sosStop();
+    }
+    @Override
+    public void setDoorLight(int type) {
+
+    }
+
+    private boolean checkAppExist(Context context, String name) {
+        PackageManager packageManager = context.getPackageManager();
+        List<PackageInfo> packageInfoList = packageManager.getInstalledPackages(0);
+        boolean appExist = false;
+        for (PackageInfo pInfo : packageInfoList) {
+            if (name.equals(pInfo.packageName)) {
+                appExist = true;
+                break;
+            }
+        }
+        Log.e("wdkl_app", "callingdoor app exist: " + appExist);
+        return appExist;
+    }
+}

+ 79 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/hardware/imp/CommonHardTools.java

@@ -0,0 +1,79 @@
+package com.wdkl.ncs.android.component.home.hardware.imp;
+
+import android.app.Application;
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.util.Log;
+
+import com.wdkl.ncs.android.component.home.hardware.HardTools;
+import com.wdkl.ncs.android.component.home.helper.AppUpdateHelper;
+import com.wdkl.ncs.android.component.home.helper.StatusBarHelper;
+import com.wdkl.ncs.android.component.home.util.NetHelper;
+import com.wdkl.ncs.android.middleware.common.Constant;
+import com.wdkl.ncs.android.middleware.utils.AppUtil;
+
+import java.util.List;
+
+public class CommonHardTools extends HardTools {
+
+    private static class CommonHardToolsHolder{
+        private final  static CommonHardTools hardTools = new CommonHardTools();
+    }
+
+    public static CommonHardTools getInstance(){
+        return CommonHardToolsHolder.hardTools;
+    }
+
+    @Override
+    public void init() {
+
+    }
+
+    @Override
+    public void unInit() {
+
+    }
+
+    @Override
+    public void resetDevicex(Application application) {
+        AppUpdateHelper.reboot(application);
+    }
+
+    @Override
+    public void Registration(Context context) {
+        Constant.imei = NetHelper.getInstance().getMacAddress();
+        Constant.DEVICE_REGISTER_ID = Constant.imei;
+    }
+
+    @Override
+    public void uninstallApp(Context context, boolean isuninstall, String name) {
+        //卸载原来二代系统apk
+        if (isuninstall) {
+            Thread thread = new Thread(new Runnable() {
+                @Override
+                public void run() {
+                    // 在子线程中执行的代码
+                    if (checkAppExist(context,name)) {
+                        AppUtil.uninstallApp(name);
+                    }
+                }
+            });
+        }
+    }
+
+    private boolean checkAppExist(Context context, String name) {
+        PackageManager packageManager = context.getPackageManager();
+        List<PackageInfo> packageInfoList = packageManager.getInstalledPackages(0);
+        boolean appExist = false;
+        for (PackageInfo pInfo : packageInfoList) {
+            if (name.equals(pInfo.packageName)) {
+                appExist = true;
+                break;
+            }
+        }
+        Log.e("wdkl_app", "callingdoor app exist: " + appExist);
+        return appExist;
+    }
+}

+ 116 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/hardware/imp/Z3128HardTools.java

@@ -0,0 +1,116 @@
+package com.wdkl.ncs.android.component.home.hardware.imp;
+
+import android.app.Application;
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.provider.Settings;
+import android.util.Log;
+
+import com.wdkl.ncs.android.component.home.hardware.HardTools;
+import com.wdkl.ncs.android.component.home.helper.AppUpdateHelper;
+import com.wdkl.ncs.android.component.home.util.NetHelper;
+import com.wdkl.ncs.android.middleware.common.Constant;
+import com.wdkl.ncs.android.middleware.utils.AppUtil;
+
+import java.util.List;
+
+/**
+ * Z-3128硬件控制类
+ *
+ * */
+public class Z3128HardTools extends HardTools {
+
+    public static final String HARDWDT_SERVICE = "Z3128HardTools";
+    private Application app;
+
+
+    private static class Z3128HardToolsHolder{
+        private final  static Z3128HardTools z3128HardTools = new Z3128HardTools();
+    }
+
+    public static Z3128HardTools getInstance(){
+        return Z3128HardToolsHolder.z3128HardTools;
+    }
+
+    @Override
+    public void init() {
+
+    }
+
+    @Override
+    public void unInit() {
+
+    }
+
+    @Override
+    public void setAudioMode(Context context, int mode) {
+        super.setAudioMode(context, mode);
+    }
+
+    @Override
+    public void setAudioMute(Context context, boolean mute) {
+        super.setAudioMute(context, mute);
+    }
+
+
+    @Override
+    public void resetDevice() {
+//        SerialPortHelper.resetDevice();
+    }
+    @Override
+    public void resetDevicex(Application application) {
+        AppUpdateHelper.reboot(application);
+    }
+    @Override
+    public void Registration(Context context) {
+        //获取mac地址
+        Constant.LOCAL_MAC = NetHelper.getInstance().getMacAddress();
+        Constant.DEVICE_REGISTER_ID = Constant.LOCAL_MAC;
+    }
+
+    @Override
+    public void uninstallApp(Context context, boolean isuninstall, String name) {
+        //卸载原来二代系统apk
+        if (isuninstall) {
+            Thread thread = new Thread(new Runnable() {
+                @Override
+                public void run() {
+                    // 在子线程中执行的代码
+                    if (checkAppExist(context,name)) {
+                        AppUtil.uninstallApp(name);
+                    }
+                }
+            });
+        }
+    }
+
+    @Override
+    public void setSOSStart() {
+//        SOSHelper.sosStart();
+    }
+
+    @Override
+    public void setSOSStop() {
+//        SOSHelper.sosStop();
+    }
+    @Override
+    public void setDoorLight(int type) {
+
+    }
+
+    private boolean checkAppExist(Context context, String name) {
+        PackageManager packageManager = context.getPackageManager();
+        List<PackageInfo> packageInfoList = packageManager.getInstalledPackages(0);
+        boolean appExist = false;
+        for (PackageInfo pInfo : packageInfoList) {
+            if (name.equals(pInfo.packageName)) {
+                appExist = true;
+                break;
+            }
+        }
+        Log.e("wdkl_app", "callingdoor app exist: " + appExist);
+        return appExist;
+    }
+}

+ 129 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/hardware/imp/ZKEHardTools.java

@@ -0,0 +1,129 @@
+package com.wdkl.ncs.android.component.home.hardware.imp;
+
+import android.app.Application;
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.util.Log;
+
+import com.wdkl.ncs.android.component.home.hardware.HardTools;
+import com.wdkl.ncs.android.component.home.helper.AppUpdateHelper;
+import com.wdkl.ncs.android.component.home.helper.StatusBarHelper;
+import com.wdkl.ncs.android.component.home.util.NetHelper;
+import com.wdkl.ncs.android.middleware.common.Constant;
+import com.wdkl.ncs.android.middleware.utils.AppUtil;
+
+import java.util.List;
+
+
+/**
+ * W——KR主机硬件控制类
+ *
+ * */
+public class ZKEHardTools extends HardTools {
+
+    public static final String HARDWDT_SERVICE = "ZKEHardTools";
+    private Application app;
+
+
+    private static class Z3128HardToolsHolder{
+        private final  static ZKEHardTools z3128HardTools = new ZKEHardTools();
+    }
+
+    public static ZKEHardTools getInstance(){
+        return Z3128HardToolsHolder.z3128HardTools;
+    }
+
+    @Override
+    public void init() {
+
+    }
+
+    @Override
+    public void unInit() {
+
+    }
+    @Override
+    public void toggleStatusBar(Context context,boolean is) {
+        if (Build.BOARD.equals("k37tv1_64_bsp") || Build.BOARD.equals("k37mv1_64_bsp") || Build.MODEL.equals("KT10-3F") || "m3520b_bnkj_zx".equals(Build.MODEL)) {
+            StatusBarHelper.toggleStatusBar(context, is);
+        }
+
+    }
+    @Override
+    public void resetDevice() {
+//        SerialPortHelper.resetDevice();
+    }
+
+    @Override
+    public void setAudioMode(Context context, int mode) {
+
+    }
+
+    @Override
+    public void setAudioMute(Context context, boolean mute) {
+        //VoiceManagerUtil.setAudioMute(BaseApplication.appContext, mute);
+    }
+
+    @Override
+    public void resetDevicex(Application application) {
+        AppUpdateHelper.reboot(application);
+    }
+    @Override
+    public void Registration(Context context) {
+        if ("KT10-3F".equalsIgnoreCase(Build.MODEL) || "KT10-2F".equalsIgnoreCase(Build.MODEL) || "KT8001-2F".equalsIgnoreCase(Build.MODEL)) {
+            Constant.imei = NetHelper.getInstance().getMacAddress();
+        } else if ("KT8001_2C".equalsIgnoreCase(Build.MODEL)) {
+            Constant.imei = NetHelper.getInstance().getIMEI2();
+        } else {
+            Constant.imei = NetHelper.getInstance().getIMEI();
+        }
+
+        Constant.DEVICE_REGISTER_ID = Constant.imei;
+    }
+
+    @Override
+    public void uninstallApp(Context context, boolean isuninstall, String name) {
+        //卸载原来二代系统apk
+        if (isuninstall) {
+            Thread thread = new Thread(new Runnable() {
+                @Override
+                public void run() {
+                    // 在子线程中执行的代码
+                    if (checkAppExist(context,name)) {
+                        AppUtil.uninstallApp(name);
+                    }
+                }
+            });
+        }
+    }
+
+    @Override
+    public void setSOSStart() {
+//        SOSHelper.sosStart();
+    }
+
+    @Override
+    public void setSOSStop() {
+//        SOSHelper.sosStop();
+    }
+    @Override
+    public void setDoorLight(int type) {
+
+    }
+
+    private boolean checkAppExist(Context context, String name) {
+        PackageManager packageManager = context.getPackageManager();
+        List<PackageInfo> packageInfoList = packageManager.getInstalledPackages(0);
+        boolean appExist = false;
+        for (PackageInfo pInfo : packageInfoList) {
+            if (name.equals(pInfo.packageName)) {
+                appExist = true;
+                break;
+            }
+        }
+        Log.e("wdkl_app", "callingdoor app exist: " + appExist);
+        return appExist;
+    }
+}

+ 277 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/helper/AppUpdateHelper.java

@@ -0,0 +1,277 @@
+package com.wdkl.ncs.android.component.home.helper;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Environment;
+import android.util.Log;
+
+import androidx.core.content.FileProvider;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+public class AppUpdateHelper {
+    private final static String TAG = "AppUpdate";
+
+    /**
+     * 下载的APK文件绝对路径
+     */
+    public static final String FILE_APK_PATH = Environment.getExternalStorageDirectory() + "/IcuVisit";
+    /**
+     * 下载的APK文件的文件名
+     */
+    public static final String FILE_APK_NAME = "IcuVisitApp.apk";
+
+    public static Context mContext;
+
+    public static void updateApp(Context context, UpdateCallBack callBack) {
+        mContext = context;
+        if (checkApkExit(context)) {
+            Log.d(TAG, "文件存在");
+        } else {
+            Log.d(TAG, "文件不存在");
+            if (callBack != null) {
+                callBack.onFailed();
+            }
+            return;
+        }
+
+        String path = FILE_APK_PATH + "/" + FILE_APK_NAME;
+
+        if (installAPP(path)) {
+            Log.d(TAG, "安装成功");
+            if (callBack != null) {
+                callBack.onSuccess();
+            }
+        }
+    }
+
+    public static void updateApp2(Context context, UpdateCallBack callBack) {
+        if (checkApkExit(context)) {
+            Log.d(TAG, "文件存在");
+        } else {
+            Log.d(TAG, "文件不存在");
+            if (callBack != null) {
+                callBack.onFailed();
+            }
+            return;
+        }
+
+        String path = FILE_APK_PATH + "/" + FILE_APK_NAME;
+        if (rootInstall(context, context.getPackageName(), path)) {
+            Log.d(TAG, "安装成功");
+            if (callBack != null) {
+                callBack.onSuccess();
+            }
+        } else {
+            Log.d(TAG, "安装失败");
+            if (callBack != null) {
+                callBack.onFailed();
+            }
+        }
+    }
+
+
+    public static boolean installAPP(String path) {
+
+        Intent intent = new Intent(Intent.ACTION_VIEW);
+        File apkFile = new File(path);
+        // 由于没有在Activity环境下启动Activity,设置下面的标签
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        //Android 7.0以上要使用FileProvider
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+            intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+            //参数1 上下文, 参数2 Provider主机地址 和配置文件中保持一致   参数3  共享的文件
+            Uri uri = FileProvider.getUriForFile(mContext, mContext.getPackageName()+".provider", apkFile);
+            //添加这一句表示对目标应用临时授权该Uri所代表的文件
+//                    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+            intent.setDataAndType(uri, "application/vnd.android.package-archive");
+        } else {
+            intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
+        }
+        mContext.startActivity(intent);
+        return true;
+    }
+
+
+    private static boolean checkApkExit(Context context) {
+        File file = new File(FILE_APK_PATH + "/" + FILE_APK_NAME);
+        return file.exists();
+    }
+
+    private static boolean checkApkAvailable(Context context, String path) {
+        try {
+            PackageManager pm = context.getPackageManager();
+            PackageInfo info = pm.getPackageArchiveInfo(path, 0);
+            ApplicationInfo applicationInfo = info.applicationInfo;
+            String newPkg = applicationInfo.packageName;
+            String curPkg = context.getPackageName();
+            Log.d(TAG, "new package: " + newPkg + ", cur package: " + curPkg);
+            if (curPkg.equals(newPkg)) {
+                return true;
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return false;
+    }
+
+    public static boolean silentInstall(Context context, String apkPath) {
+        PackageManager packageManager = context.getPackageManager();
+        Class pmClz = packageManager.getClass();
+        try {
+            if (Build.VERSION.SDK_INT >= 21) {
+                Log.d(TAG, "apk path: " + apkPath);
+                Class aClass = Class.forName("android.app.PackageInstallObserver");
+                Constructor constructor = aClass.getDeclaredConstructor();
+                constructor.setAccessible(true);
+                Object installObserver = constructor.newInstance();
+                Method method = pmClz.getDeclaredMethod("installPackage", Uri.class, aClass, int.class, String.class);
+                method.setAccessible(true);
+                method.invoke(packageManager, Uri.fromFile(new File(apkPath)), installObserver, 2, null);
+            } else {
+                Method method = pmClz.getDeclaredMethod("installPackage", Uri.class, Class.forName("android.content.pm.IPackageInstallObserver"), int.class, String.class);
+                method.setAccessible(true);
+                method.invoke(packageManager, Uri.fromFile(new File(apkPath)), null, 2, null);
+            }
+            return true;
+        } catch (Exception e) {
+            Log.e(TAG, e.toString());
+        }
+        return false;
+    }
+
+    public static boolean installApp(String packageName, String apkPath) {
+        Process process = null;
+        BufferedReader successResult = null;
+        BufferedReader errorResult = null;
+        StringBuilder successMsg = new StringBuilder();
+        StringBuilder errorMsg = new StringBuilder();
+        Log.e(TAG, "install package: " + packageName + ", apkPath: " + apkPath);
+        try {
+            process = new ProcessBuilder("pm", "install", "-i", packageName, "-r", apkPath).start();
+            successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));
+            errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));
+            String s;
+            while ((s = successResult.readLine()) != null) {
+                successMsg.append(s);
+            }
+            while ((s = errorResult.readLine()) != null) {
+                errorMsg.append(s);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            try {
+                if (successResult != null) {
+                    successResult.close();
+                }
+                if (errorResult != null) {
+                    errorResult.close();
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+            if (process != null) {
+                process.destroy();
+            }
+        }
+        Log.e(TAG, "" + errorMsg.toString());
+        //如果含有“success”认为安装成功
+        return successMsg.toString().equalsIgnoreCase("success");
+    }
+
+    public static boolean rootSilenceInstall(String path) {
+        Process process;
+        PrintWriter printWriter;
+        try {
+            process = Runtime.getRuntime().exec("su");
+            printWriter = new PrintWriter(process.getOutputStream());
+            printWriter.println("pm install -r " + path);
+            printWriter.flush();
+            printWriter.close();
+            int res = process.waitFor();
+            Log.e(TAG, "silent install res: " + res);
+            if (res == 0) {
+                return true;
+            } else {
+                return false;
+            }
+        } catch (Exception e) {
+            Log.e(TAG, "rootSilenceInstall e:" + e.getMessage());
+            return false;
+        }
+    }
+
+    public static boolean rootInstall(Context context, String packageName, String path) {
+        Process process;
+        PrintWriter printWriter;
+        BufferedReader errorStream = null;
+        BufferedReader successStream = null;
+        Boolean result;
+        try {
+            process = Runtime.getRuntime().exec("su");
+            printWriter = new PrintWriter(process.getOutputStream());
+            printWriter.println("pm install -i "+packageName+" -r " + path);//-i "+packageName+"
+            printWriter.flush();
+            printWriter.close();
+            Intent intent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
+            PendingIntent restartIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_ONE_SHOT);
+            AlarmManager mgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {// 6.0及以上
+                mgr.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 45000, restartIntent);
+            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {// 4.4及以上
+                mgr.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 45000, restartIntent);
+            }
+            int value = process.waitFor();
+            result = (value == 0);
+        } catch (Exception e) {
+            if(errorStream!=null){
+                try {
+                    errorStream.close();
+                } catch (IOException ioException) {
+                    ioException.printStackTrace();
+                }
+            }
+            if(successStream!=null){
+                try {
+                    successStream.close();
+                } catch (IOException ioException) {
+                    ioException.printStackTrace();
+                }
+            }
+            Log.e(TAG, "rootSilenceInstall e:" + e.getMessage());
+            result = false;
+        }
+
+        return result;
+    }
+
+    public static void reboot(Context context) {
+        Intent intent = new Intent(Intent.ACTION_REBOOT);
+        intent.putExtra("nowait", 1);
+        intent.putExtra("interval", 1);
+        intent.putExtra("window", 0);
+        context.sendBroadcast(intent);
+    }
+
+    public interface UpdateCallBack {
+        void onFailed();
+
+        void onSuccess();
+    }
+}

+ 161 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/helper/HttpHelper.java

@@ -0,0 +1,161 @@
+package com.wdkl.ncs.android.component.home.helper;
+
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import okhttp3.Call;
+import okhttp3.Callback;
+import okhttp3.MediaType;
+import okhttp3.MultipartBody;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+import okhttp3.Response;
+
+import static com.wdkl.ncs.android.component.home.helper.AppUpdateHelper.FILE_APK_NAME;
+import static com.wdkl.ncs.android.component.home.helper.AppUpdateHelper.FILE_APK_PATH;
+
+
+public class HttpHelper {
+
+    /**
+     * @param url   服务器地址
+     * @param file  所要上传的文件
+     */
+    public static void upload(String url, File file, final UploadCallback callback) {
+        OkHttpClient client = new OkHttpClient();
+        RequestBody requestBody = new MultipartBody.Builder()
+                .setType(MultipartBody.FORM)
+                .addFormDataPart("file", file.getName(), RequestBody.create(MediaType.parse("multipart/form-data"), file))
+                .build();
+        Request request = new Request.Builder()
+                .url(url)
+                .post(requestBody)
+                .build();
+
+        client.newCall(request).enqueue(new Callback() {
+            @Override
+            public void onFailure(Call call, IOException e) {
+                if (callback != null) {
+                    callback.onFail();
+                }
+            }
+
+            @Override
+            public void onResponse(Call call, Response response) throws IOException {
+                Log.d("wzlll", "voice msg response: " + response.toString());
+               if( response.code()==200 && response.body() != null) {
+                   String data = response.body().string();
+                   //voice msg response: upload/file/202104102037715.mp3
+                   if (callback != null) {
+                       callback.onSuccess(data);
+                   }
+               } else {
+                   if (callback != null) {
+                       callback.onFail();
+                   }
+               }
+            }
+        });
+    }
+
+    public static void download(String url, final DownloadListener listener) {
+        Request request = new Request.Builder().url(url).build();
+        OkHttpClient okHttpClient = new OkHttpClient();
+        okHttpClient.newCall(request).enqueue(new Callback() {
+            @Override
+            public void onFailure(Call call, IOException e) {
+                Log.d("download", "onFailure==" + e.toString());
+                if (listener != null) {
+                    listener.onDownloadFailed(); // 下载失败
+                }
+            }
+
+            @Override
+            public void onResponse(Call call, Response response) {
+                Log.d("download", "response==" + response.body().contentLength());
+                InputStream is = null;
+                byte[] buf = new byte[2048];
+                int len;
+                FileOutputStream fos = null;
+                try {
+                    is = response.body().byteStream();
+                    long total = response.body().contentLength();
+                    File file = new File(isHaveExistDir(new File(FILE_APK_PATH), new File(FILE_APK_PATH + "/" + FILE_APK_NAME)), FILE_APK_NAME);
+                    fos = new FileOutputStream(file);
+                    long sum = 0;
+                    while ((len = is.read(buf)) != -1) {
+                        fos.write(buf, 0, len);
+                        sum = sum + (long) len;
+                        //int progress = (int) (sum * 1.0f / total * 100);
+                        float sp = (float) sum / (float) total;
+                        int progress = (int) (sp * 100);
+                        Log.d("download", "progress==" + progress);
+                        if (listener != null) {
+                            listener.onDownloading(progress);// 下载中
+                        }
+                    }
+                    fos.flush();
+                    if (listener != null) {
+                        listener.onDownloadSuccess(); // 下载完成
+                    }
+                } catch (Exception e) {
+                    Log.d("download", "Exception==");
+                    if (listener != null) {
+                        listener.onDownloadFailed();
+                    }
+                } finally {
+                    try {
+                        if (is != null)
+                            is.close();
+                        if (fos != null)
+                            fos.close();
+                    } catch (IOException e) {
+                        Log.d("download", "IOException==");
+                    }
+                }
+            }
+        });
+    }
+
+    private static String isHaveExistDir(File downloadFile, File sonFile) throws IOException {
+        Log.d("download", "downloadFile.mkdirs()==" + downloadFile.mkdirs());
+        Log.d("download", "sonFile.mkdir()==" + sonFile.mkdir());
+        if (!downloadFile.mkdirs()) {
+            downloadFile.createNewFile();
+        }
+        deleteAPKFile(sonFile);//只要文件名相同就可以自动替换(按道理此处不需要了,但为了保险起见还是先执行删除操作)。
+        return downloadFile.getAbsolutePath();
+    }
+
+    public static boolean deleteAPKFile(File downloadFile) {
+        return downloadFile.delete();
+    }
+
+
+    public interface UploadCallback{
+        void onFail();
+        void onSuccess(String data);
+    }
+
+    public interface DownloadListener {
+        /**
+         * 下载成功
+         */
+        void onDownloadSuccess();
+
+        /**
+         * @param progress 下载进度
+         */
+        void onDownloading(int progress);
+
+        /**
+         * 下载失败
+         */
+        void onDownloadFailed();
+    }
+}

+ 92 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/helper/NetworkDialogHelper.java

@@ -0,0 +1,92 @@
+package com.wdkl.ncs.android.component.home.helper;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.os.Build;
+import android.provider.Settings;
+import android.util.DisplayMetrics;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.Button;
+import android.widget.TextView;
+
+import com.wdkl.ncs.android.component.home.R;
+import com.wdkl.ncs.android.lib.utils.EthernetUtils;
+
+import static com.wdkl.ncs.android.lib.utils.ExtendMethodsKt.showMessage;
+
+public class NetworkDialogHelper {
+
+    private static AlertDialog alertDialog;
+    private static String network="";
+
+    public static void showDialog(Activity activity) {
+
+        View contentView = LayoutInflater.from(activity).inflate(R.layout.main_network_dialog, null);
+        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+        builder.setView(contentView);
+        TextView network_one_tx = contentView.findViewById(R.id.network_one_tx);
+        TextView network_two_tx = contentView.findViewById(R.id.network_two_tx);
+        Button network_button = contentView.findViewById(R.id.network_button);
+        network_one_tx.setOnClickListener(v -> {
+            network="DHCP";
+            network_one_tx.setBackgroundResource(R.drawable.shape_main_hos_txt_bg);
+            network_two_tx.setBackgroundResource(R.drawable.selector_nuser_msg_tx_d);
+        });
+        network_two_tx.setOnClickListener(v -> {
+            network="静态";
+            network_one_tx.setBackgroundResource(R.drawable.selector_nuser_msg_tx_d);
+            network_two_tx.setBackgroundResource(R.drawable.shape_main_hos_txt_bg);
+        });
+        network_button.setOnClickListener(v -> {
+            if (alertDialog != null && alertDialog.isShowing()) {
+                alertDialog.dismiss();
+                Intent intent = new Intent(Settings.ACTION_SETTINGS);
+                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                activity.startActivity(intent);
+
+                //显示虚拟导航栏
+                if (Build.BOARD.equals("k37tv1_64_bsp") || Build.BOARD.equals("k37mv1_64_bsp") || Build.MODEL.equals("KT10-3F")) {
+                    StatusBarHelper.toggleStatusBar(activity, true);
+                }
+
+                /*if (network.equals("静态")){
+                    Network2DialogHelper.showDialog(activity);
+                }else {
+                    //设置成动态获取网络
+                    if (EthernetUtils.setDynamicIp(activity)) {
+                        showMessage("动态获取网络设置成功");
+                    } else {
+                        showMessage("动态获取网络设置失败");
+                    }
+                }*/
+
+            }
+        });
+        alertDialog = builder.create();
+        alertDialog.setCanceledOnTouchOutside(true);
+        alertDialog.setCancelable(true);
+        alertDialog.show();
+        DisplayMetrics metrics = new DisplayMetrics();
+        activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
+        int screenWidth = metrics.widthPixels;
+        int orientation = activity.getResources().getConfiguration().orientation;
+        if (orientation == Configuration.ORIENTATION_PORTRAIT && screenWidth>600) {
+            try {
+                Window window = alertDialog.getWindow();
+                WindowManager.LayoutParams lp = window.getAttributes();
+                lp.width = 800;
+                lp.height = 800;
+                lp.gravity = Gravity.CENTER;
+                window.setAttributes(lp);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
+}

+ 61 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/helper/RebootDialogHelper.java

@@ -0,0 +1,61 @@
+package com.wdkl.ncs.android.component.home.helper;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.res.Configuration;
+import android.util.DisplayMetrics;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.Button;
+
+import com.wdkl.ncs.android.component.home.R;
+
+public class RebootDialogHelper {
+
+    private static AlertDialog alertDialog;
+
+    public static void showDialog(Activity activity) {
+
+        View contentView = LayoutInflater.from(activity).inflate(R.layout.main_restart_dialog, null);
+        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+        builder.setView(contentView);
+
+        Button btn_cancel = contentView.findViewById(R.id.server_cancel_button);
+        Button server_determine_button = contentView.findViewById(R.id.server_determine_button);
+        btn_cancel.setOnClickListener(v -> {
+            if (alertDialog != null && alertDialog.isShowing()) {
+                alertDialog.dismiss();
+            }
+        });
+        server_determine_button.setOnClickListener(v -> {
+            if (alertDialog != null && alertDialog.isShowing()) {
+                alertDialog.dismiss();
+                AppUpdateHelper.reboot(activity);
+            }
+        });
+        alertDialog = builder.create();
+        alertDialog.setCanceledOnTouchOutside(true);
+        alertDialog.setCancelable(true);
+        alertDialog.show();
+
+        DisplayMetrics metrics = new DisplayMetrics();
+        activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
+        int screenWidth = metrics.widthPixels;
+        int orientation = activity.getResources().getConfiguration().orientation;
+        if (orientation == Configuration.ORIENTATION_PORTRAIT && screenWidth>600) {
+            try {
+                Window window = alertDialog.getWindow();
+                WindowManager.LayoutParams lp = window.getAttributes();
+                lp.width = 800;
+                lp.height = 450;
+                lp.gravity = Gravity.CENTER;
+                window.setAttributes(lp);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
+}

+ 126 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/helper/RecordHelper.java

@@ -0,0 +1,126 @@
+package com.wdkl.ncs.android.component.home.helper;
+
+import android.media.MediaRecorder;
+import android.os.Environment;
+import android.util.Log;
+
+import java.io.File;
+import java.io.IOException;
+
+public class RecordHelper {
+    private static final String VOICE_MSG_FILE_PATH = Environment.getExternalStorageDirectory().getPath() + "/VoiceMsg";
+    private String audiofilePath;
+    private MediaRecorder mediaRecorder;
+    private static RecordHelper sInstance = null;
+    private boolean recording = false;
+
+    private final static Object lock = new Object();
+
+    public RecordHelper() {
+    }
+
+    public static RecordHelper getInstance() {
+        if (sInstance == null) {
+            synchronized (RecordHelper.class) {
+                if (sInstance == null) {
+                    sInstance = new RecordHelper();
+                }
+            }
+        }
+        return sInstance;
+    }
+
+    public void init() {
+        //创建音频文件路径
+        File file = new File(VOICE_MSG_FILE_PATH);
+        if (!file.exists()) {
+            file.mkdir();
+        }
+    }
+
+    public void startRecord() {
+        audiofilePath = VOICE_MSG_FILE_PATH + "/" + System.currentTimeMillis() + "_voice.mp3";
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                synchronized (lock) {
+                    try {
+                        mediaRecorder = new MediaRecorder();
+                        mediaRecorder.setOutputFile(audiofilePath);
+                        mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 设置MediaRecorder的音频源为麦克风
+                        mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);// 设置MediaRecorder录制的音频格式
+                        mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);// 设置MediaRecorder录制音频的编码为amr
+                        mediaRecorder.prepare();
+                        mediaRecorder.start();
+                        recording = true;
+                    } catch (IOException e) {
+                        Log.i("error", "call startAmr(File mRecAudioFile) failed!" + e.getMessage());
+                    }
+                }
+            }
+        }).start();
+    }
+
+    public void stopRecord() {
+        synchronized (lock) {
+            try {
+                mediaRecorder.stop();
+                mediaRecorder.release();
+                mediaRecorder = null;
+            } catch (Exception e) {
+                e.printStackTrace();
+            } finally {
+                recording = false;
+            }
+        }
+    }
+
+    public void recordTestStart() {
+        audiofilePath = VOICE_MSG_FILE_PATH + "/" + System.currentTimeMillis() + "_voice.mp3";
+        synchronized (lock) {
+            try {
+                mediaRecorder = new MediaRecorder();
+                mediaRecorder.setOutputFile(audiofilePath);
+                mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 设置MediaRecorder的音频源为麦克风
+                mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);// 设置MediaRecorder录制的音频格式
+                mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);// 设置MediaRecorder录制音频的编码为amr
+                mediaRecorder.prepare();
+                mediaRecorder.start();
+                recording = true;
+            } catch (IOException e) {
+                Log.i("error", "call startAmr(File mRecAudioFile) failed!" + e.getMessage());
+            }
+        }
+    }
+
+    public void recordTestStop() {
+        synchronized (lock) {
+            try {
+                mediaRecorder.stop();
+                mediaRecorder.release();
+                mediaRecorder = null;
+            } catch (Exception e) {
+                e.printStackTrace();
+            } finally {
+                recording = false;
+            }
+        }
+    }
+
+    public void deleteAudioFile(String path) {
+        synchronized (lock) {
+            File file = new File(path);
+            if (file.exists()) {
+                file.delete();
+            }
+        }
+    }
+
+    public void deleteAudioFile() {
+        deleteAudioFile(audiofilePath);
+    }
+
+    public String getAudiofilePath() {
+        return audiofilePath;
+    }
+}

+ 107 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/helper/ServicesDialogHelper.java

@@ -0,0 +1,107 @@
+package com.wdkl.ncs.android.component.home.helper;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.util.DisplayMetrics;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+
+import com.wdkl.ncs.android.component.home.R;
+import com.wdkl.ncs.android.component.home.util.AppUtils;
+import com.wdkl.ncs.android.lib.base.BaseApplication;
+import com.wdkl.ncs.android.middleware.utils.CommonUtils;
+
+import static com.wdkl.ncs.android.lib.utils.ExtendMethodsKt.showMessage;
+
+public class ServicesDialogHelper {
+
+    private static AlertDialog alertDialog;
+
+    public static void showDialog(Activity activity, ClickListener clickListener) {
+
+        View contentView = LayoutInflater.from(activity).inflate(R.layout.main_server_dialog, null);
+        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+        builder.setView(contentView);
+
+        Button server_determine_button = contentView.findViewById(R.id.server_determine_button);
+        Button server_cancel_button = contentView.findViewById(R.id.server_cancel_button);
+        LinearLayout layout = contentView.findViewById(R.id.ll_server_config_view);
+        EditText server_ed = contentView.findViewById(R.id.server_ed);
+        String URL = CommonUtils.getUrl(BaseApplication.appContext);
+        server_ed.setText(URL);
+        server_determine_button.setOnClickListener(v -> {
+            if (alertDialog != null && alertDialog.isShowing()) {
+                if(server_ed.getText().toString().equals("")){
+                    showMessage("服务器地址不能为空");
+                    return;
+                }
+                CommonUtils.setUrl(BaseApplication.appContext, server_ed.getText().toString());
+                if (clickListener != null) {
+                    String IP = server_ed.getText().toString();
+                    clickListener.onClick(IP);
+                }
+                alertDialog.dismiss();
+            }
+        });
+        server_cancel_button.setOnClickListener(v -> {
+            if (alertDialog != null && alertDialog.isShowing()) {
+                server_ed.setText("");
+            }
+        });
+        layout.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                try {
+                    AppUtils.hideInputKeyboard(alertDialog.getWindow().getDecorView().getWindowToken());
+                } catch (Exception e) {
+                    //
+                }
+            }
+        });
+
+        alertDialog = builder.create();
+        alertDialog.setCanceledOnTouchOutside(true);
+        alertDialog.setCancelable(true);
+        alertDialog.show();
+
+        DisplayMetrics metrics = new DisplayMetrics();
+        activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
+        int screenWidth = metrics.widthPixels;
+        int orientation = activity.getResources().getConfiguration().orientation;
+        if (orientation == Configuration.ORIENTATION_PORTRAIT && screenWidth>600) {
+            try {
+                Window window = alertDialog.getWindow();
+                WindowManager.LayoutParams lp = window.getAttributes();
+                lp.width = 800;
+                lp.height = 800;
+                lp.gravity = Gravity.CENTER;
+                window.setAttributes(lp);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+//        //设置dialog宽高及位置
+//        try {
+//            Window window = alertDialog.getWindow();
+//            WindowManager.LayoutParams lp = window.getAttributes();
+//            lp.width = 680;
+//            lp.height = 440;
+//            lp.gravity = Gravity.CENTER;
+//            window.setAttributes(lp);
+//        } catch (Exception e) {
+//            e.printStackTrace();
+//        }
+    }
+
+    public interface ClickListener{
+        void onClick(String bedVO);
+    }
+}

+ 33 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/helper/StatusBarHelper.java

@@ -0,0 +1,33 @@
+package com.wdkl.ncs.android.component.home.helper;
+
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+public class StatusBarHelper {
+    public static void toggleStatusBar(Context context, Boolean show) {
+        Intent intent = new Intent();
+        intent.setAction("com.kaer.action.WHETHER_SHOW_NAVIGATION");
+        intent.putExtra("show_navigation_bar", show);
+        context.sendBroadcast(intent);
+
+        Log.d("StatusBar", "toggleStatusBar: show ===== " + show);
+        Intent intent2 = new Intent();
+        if (show) {
+            intent2.setAction("com.android.show.statusbar.show.navbar");
+        } else {
+            intent2.setAction("com.android.hide.statusbar.hide.navbar");
+        }
+        context.sendBroadcast(intent2);
+
+        /*Intent intent2 = new Intent();
+        intent2.setAction("com.kaer.action.OPEN_PANEL_ENABLED");
+        intent2.putExtra("open_panel_enabled", show);
+        context.sendBroadcast(intent2);
+
+        Intent intent3 = new Intent();
+        intent3.setAction("com.kaer.action.WHETHER_SHOW_STATUSBAR");
+        intent3.putExtra("show_status_bar", show);
+        context.sendBroadcast(intent3);*/
+    }
+}

+ 96 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/helper/SystemDialogHelper.java

@@ -0,0 +1,96 @@
+package com.wdkl.ncs.android.component.home.helper;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.util.DisplayMetrics;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+
+import com.wdkl.ncs.android.component.home.R;
+import com.wdkl.ncs.android.component.home.activity.SystemActivity;
+import com.wdkl.ncs.android.component.home.util.AppUtils;
+
+public class SystemDialogHelper {
+
+    private static AlertDialog alertDialog;
+
+    public static void showDialog(Activity activity) {
+
+        View contentView = LayoutInflater.from(activity).inflate(R.layout.main_password_dialog, null);
+        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+        builder.setView(contentView);
+
+        LinearLayout layout = contentView.findViewById(R.id.ll_password_view);
+        Button password_cancel_button = contentView.findViewById(R.id.password_cancel_button);
+        Button password_determine_button = contentView.findViewById(R.id.password_determine_button);
+        EditText password_ed = contentView.findViewById(R.id.password_ed);
+
+        layout.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                try {
+                    AppUtils.hideInputKeyboard(alertDialog.getWindow().getDecorView().getWindowToken());
+                } catch (Exception e) {
+                    //
+                }
+            }
+        });
+
+        password_cancel_button.setOnClickListener(v -> {
+            if (alertDialog != null && alertDialog.isShowing()) {
+                alertDialog.dismiss();
+            }
+        });
+        password_determine_button.setOnClickListener(v -> {
+            if (alertDialog != null && alertDialog.isShowing()) {
+                String passwprd =password_ed.getText().toString();
+                if (passwprd.equals("888")){
+                    Intent intent = new Intent();
+                    intent.setClass(activity, SystemActivity.class);
+                    activity.startActivity(intent);
+                }
+                alertDialog.dismiss();
+            }
+        });
+        alertDialog = builder.create();
+        alertDialog.setCanceledOnTouchOutside(true);
+        alertDialog.setCancelable(true);
+        alertDialog.show();
+
+        DisplayMetrics metrics = new DisplayMetrics();
+        activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
+        int screenWidth = metrics.widthPixels;
+        int orientation = activity.getResources().getConfiguration().orientation;
+        if (orientation == Configuration.ORIENTATION_PORTRAIT && screenWidth>600) {
+            try {
+                Window window = alertDialog.getWindow();
+                WindowManager.LayoutParams lp = window.getAttributes();
+                lp.width = 800;
+                lp.height = 650;
+                lp.gravity = Gravity.CENTER;
+                window.setAttributes(lp);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+//        //设置dialog宽高及位置
+//        try {
+//            Window window = alertDialog.getWindow();
+//            WindowManager.LayoutParams lp = window.getAttributes();
+//            lp.width = 680;
+//            lp.height = 440;
+//            lp.gravity = Gravity.CENTER;
+//            window.setAttributes(lp);
+//        } catch (Exception e) {
+//            e.printStackTrace();
+//        }
+    }
+}

+ 70 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/helper/UpdataDialogHelper.java

@@ -0,0 +1,70 @@
+package com.wdkl.ncs.android.component.home.helper;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.os.Build;
+import android.util.DisplayMetrics;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.Button;
+import android.widget.TextView;
+
+import com.wdkl.ncs.android.component.home.BuildConfig;
+import com.wdkl.ncs.android.component.home.R;
+import com.wdkl.ncs.android.component.home.activity.AppUpdateActivity;
+
+public class UpdataDialogHelper {
+
+    private static AlertDialog alertDialog;
+
+    public static void showDialog(Activity activity, ClickListener clickListener) {
+
+        View contentView = LayoutInflater.from(activity).inflate(R.layout.main_version_dialog, null);
+        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+        builder.setView(contentView);
+
+        TextView version_number_tx = contentView.findViewById(R.id.version_number_tx);
+        TextView version_time_tx = contentView.findViewById(R.id.version_time_tx);
+        Button version_button = contentView.findViewById(R.id.version_button);
+        version_number_tx.setText( BuildConfig.VERSION_NAME + "_" + BuildConfig.VERSION_CODE + "_" + Build.MODEL);
+        version_time_tx.setText(BuildConfig.BUILD_TIME);
+
+        version_button.setOnClickListener(v -> {
+            if (alertDialog != null && alertDialog.isShowing()) {
+                clickListener.onClick();
+
+                alertDialog.dismiss();
+            }
+        });
+        alertDialog = builder.create();
+        alertDialog.setCanceledOnTouchOutside(true);
+        alertDialog.setCancelable(true);
+        alertDialog.show();
+
+        DisplayMetrics metrics = new DisplayMetrics();
+        activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
+        int screenWidth = metrics.widthPixels;
+        int orientation = activity.getResources().getConfiguration().orientation;
+        if (orientation == Configuration.ORIENTATION_PORTRAIT && screenWidth>600) {
+            try {
+                Window window = alertDialog.getWindow();
+                WindowManager.LayoutParams lp = window.getAttributes();
+                lp.width = 800;
+                lp.height = 650;
+                lp.gravity = Gravity.CENTER;
+                window.setAttributes(lp);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    public interface ClickListener{
+        void onClick();
+    }
+}

+ 101 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/helper/UpdateTipsDialogHelper.java

@@ -0,0 +1,101 @@
+package com.wdkl.ncs.android.component.home.helper;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Intent;
+import android.os.CountDownTimer;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.Button;
+
+import com.wdkl.ncs.android.component.home.R;
+import com.wdkl.ncs.android.component.home.activity.AppUpdateActivity;
+import com.wdkl.ncs.android.lib.base.BaseApplication;
+import com.wdkl.ncs.android.middleware.common.Constant;
+
+public class UpdateTipsDialogHelper {
+
+    private static AlertDialog dialog;
+
+    public static void showDialog(Activity activity) {
+        if (dialog != null && dialog.isShowing()) {
+            return;
+        }
+
+        View contentView = LayoutInflater.from(activity).inflate(R.layout.update_tips_dialog, null);
+        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+        builder.setView(contentView);
+        Button buttonCancel = contentView.findViewById(R.id.cancel_button);
+        Button buttonConfirm = contentView.findViewById(R.id.confirm_button);
+        final CountDownTimer timer = new CountDownTimer(15000, 1000) {
+
+            @Override
+            public void onTick(long millisUntilFinished) {
+                String text = BaseApplication.appContext.getString(R.string.confirm_down_time, millisUntilFinished/1000);
+                buttonConfirm.setText(text);
+            }
+
+            @Override
+            public void onFinish() {
+                Intent intent = new Intent();
+                intent.setClass(activity, AppUpdateActivity.class);
+                activity.startActivity(intent);
+
+                if (dialog != null) {
+                    dialog.dismiss();
+                }
+            }
+        };
+        timer.start();
+
+        buttonCancel.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                Constant.APP_UPDATING = false;
+                if (timer != null) {
+                    timer.cancel();
+                }
+                if (dialog != null) {
+                    dialog.dismiss();
+                }
+            }
+        });
+
+        buttonConfirm.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if (timer != null) {
+                    timer.cancel();
+                }
+
+                Intent intent = new Intent();
+                intent.setClass(activity, AppUpdateActivity.class);
+                activity.startActivity(intent);
+
+                if (dialog != null) {
+                    dialog.dismiss();
+                }
+            }
+        });
+
+        dialog = builder.create();
+        dialog.setCanceledOnTouchOutside(false);
+        dialog.setCancelable(false);
+        dialog.show();
+
+        //设置dialog宽高及位置
+        try {
+            Window window = dialog.getWindow();
+            WindowManager.LayoutParams lp = window.getAttributes();
+            lp.width = 600;
+            lp.height = 320;
+            lp.gravity = Gravity.CENTER;
+            window.setAttributes(lp);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+}

+ 27 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/launch/VisitingLaunch.kt

@@ -0,0 +1,27 @@
+package com.wdkl.ncs.android.component.home.launch
+
+import com.wdkl.ncs.android.component.home.di.DaggerVisitingComponent
+import com.wdkl.ncs.android.component.home.di.VisitingComponent
+import com.enation.javashop.android.jrouter.external.annotation.Router
+import com.wdkl.ncs.android.lib.base.BaseLaunch
+import com.wdkl.ncs.android.middleware.di.DaggerManager
+
+/**
+ * @author LDD
+ * @Date   2018/1/22 下午2:44
+ * @From   com.wdkl.ncs.android.component.home.launch
+ * @Note   home模块启动类 代替Application 在壳工程Application中反射调用
+ */
+@Router(path = "/visiting/launch")
+class VisitingLaunch : BaseLaunch() {
+    companion object {
+        lateinit var component:VisitingComponent
+    }
+
+    override fun moduleInit() {
+        component = DaggerVisitingComponent.builder()
+                .applicationComponent(DaggerManager.APPLICATION_COMPONENT)
+                .build()
+    }
+
+}

+ 100 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/service/TcpHandleService.kt

@@ -0,0 +1,100 @@
+package com.wdkl.ncs.android.component.home.service
+
+import android.app.Service
+import android.content.Intent
+import android.os.Binder
+import android.os.IBinder
+import android.util.Log
+import com.alibaba.fastjson.JSONObject
+import com.wdkl.ncs.android.component.home.activity.*
+import com.wdkl.ncs.android.component.home.util.AppUtils
+import com.wdkl.ncs.android.component.home.util.Util
+import com.wdkl.ncs.android.lib.base.BaseApplication
+import com.wdkl.ncs.android.lib.utils.AppTool
+import com.wdkl.ncs.android.middleware.common.Constant
+import com.wdkl.ncs.android.middleware.common.MessageEvent
+import com.wdkl.ncs.android.middleware.tcp.channel.DeviceChannel
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel
+import com.wdkl.ncs.android.middleware.tcp.enums.TcpAction
+import com.wdkl.ncs.android.middleware.utils.CommonUtils
+import org.greenrobot.eventbus.EventBus
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+
+
+class TcpHandleService : Service(){
+    val TAG = TcpHandleService.javaClass.canonicalName
+    companion object instance {
+        var updateLastTime : Long = System.currentTimeMillis() / 1000
+    }
+
+    override fun onBind(intent: Intent?): IBinder? {
+        return ServiceBinder()
+    }
+
+    inner class ServiceBinder : Binder() {
+        fun doThings() {
+        }
+    }
+
+    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
+        Log.i("TcpHandleService", "已经启动")
+
+        return super.onStartCommand(intent, flags, startId)
+    }
+
+    override fun onCreate() {
+        super.onCreate()
+        EventBus.getDefault().register(this)
+    }
+
+    override fun onDestroy() {
+        EventBus.getDefault().unregister(this)
+        super.onDestroy()
+    }
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    fun onMoonEvent(messageEvent: MessageEvent) {
+        when(messageEvent.type){
+            //APP升级
+            Constant.EVENT_APP_UPDATE->{
+                while (DeviceChannel.calling) {    //通话中不处理,一直等待至结束
+                    Thread.sleep(3000)
+                }
+
+                DeviceChannel.calling = true    //置于通话状态中,不可呼叫
+                Util.wakeUpAndUnlock(this)
+                var tcpModel = messageEvent.getMessage() as TcpModel
+                if (tcpModel.action == TcpAction.DeviceAction.APP_UPDATE) {
+                    if ((System.currentTimeMillis() / 1000) - updateLastTime > 10){   //大于10秒可继续升级
+                        updateLastTime = System.currentTimeMillis() / 1000
+                        var intent = Intent()
+                        intent.setClass(this, AppUpdateActivity::class.java)
+                        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+                        startActivity(intent)
+                    }
+                }
+            }
+
+            Constant.EVENT_RESTART_APP -> {
+                AppUtils.restartApp()
+            }
+
+            //服务器IP地址切换
+            Constant.EVENT_SERVER_CHANGE -> {
+                val tcpModel = messageEvent.getMessage() as TcpModel
+                if (tcpModel.data != null) {
+                    val json = JSONObject.parseObject(tcpModel.data.toString())
+                    val serverIp = json.getString("server_ip")
+                    val serverPort = json.getString("server_port")
+                    //Log.e(TAG, "change server ip:$serverIp, server port:$serverPort")
+                    CommonUtils.setUrl(BaseApplication.appContext, serverIp)
+                    CommonUtils.setUrlPort(BaseApplication.appContext, serverPort)
+                    AppTool.Time.delay(2000) {
+                        AppUtils.restartApp()
+                    }
+                }
+            }
+        }
+    }
+}

+ 83 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/settingconfig/SettingConfig.java

@@ -0,0 +1,83 @@
+package com.wdkl.ncs.android.component.home.settingconfig;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+
+public class SettingConfig {
+
+    private static final String SP_NAME = "SP_FUNCTION";
+
+    //呼叫转接时间设置
+    private static final String KEY_SP_COUNTDOWN_TIME = "KEY_SP_COUNTDOWN_TIME";
+    private static final int CountdownTime = 15;
+
+    //分机通话音量
+    private static final String KEY_SP_EXTENSION_CALL_VOLUME = "KEY_SP_EXTENSION_CALL_VOLUME";
+    private static final int extension_call_volume = 80;
+
+    //默认语言
+    private static final String KEY_LANGUAGE_ID = "KEY_LANGUAGE_ID";
+    private static final String KEY_LANGUAGE_MODE = "KEY_LANGUAGE_MODE";
+
+    public static int getLanguageId(Context context) {
+        //0--auto, 1--English, 2--中文, 3--西班牙语, 4--俄语
+        return getSP(context).getInt(KEY_LANGUAGE_ID, 2);
+    }
+
+    public static void setLanguageId(Context context, int id) {
+        getEditor(context).putInt(KEY_LANGUAGE_ID, id).apply();
+    }
+
+    //0:同步服务器设置, 1:手动设置
+    public static int getLanguageMode(Context context) {
+        return getSP(context).getInt(KEY_LANGUAGE_MODE, 0);
+    }
+
+    public static void setLanguageMode(Context context, int mode) {
+        getEditor(context).putInt(KEY_LANGUAGE_MODE, mode).apply();
+    }
+
+    /**
+     * 获取转发时间
+     *
+     * @return
+     */
+    public static int getCountdownTime(Context context) {
+        return getSP(context).getInt(KEY_SP_COUNTDOWN_TIME, CountdownTime);
+    }
+
+    /**
+     * 设置转发时间
+     *
+     * @param value
+     */
+    public static void setCountdownTime(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_COUNTDOWN_TIME, value).apply();
+    }
+
+    /**
+     * 获取分机通话音量
+     *
+     * @return
+     */
+    public static int getExtensionCallVolume(Context context) {
+        return getSP(context).getInt(KEY_SP_EXTENSION_CALL_VOLUME, extension_call_volume);
+    }
+
+    /**
+     * 设置分机通话音量
+     *
+     * @param value
+     */
+    public static void setExtensionCallVolume(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_EXTENSION_CALL_VOLUME, value).apply();
+    }
+
+    private static SharedPreferences getSP(Context context) {
+        return context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
+    }
+
+    private static SharedPreferences.Editor getEditor(Context context) {
+        return getSP(context).edit();
+    }
+}

+ 236 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/util/AnrFcExceptionUtil.java.bak

@@ -0,0 +1,236 @@
+package com.wdkl.ncs.android.component.home.util;
+
+import android.app.AlarmManager;
+import android.app.Application;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Environment;
+import android.util.Log;
+
+import com.github.anrwatchdog.ANRError;
+import com.github.anrwatchdog.ANRWatchDog;
+import com.wdkl.ncs.android.component.home.activity.VisitingActivity;
+import com.wdkl.ncs.android.component.welcome.activity.WelcomeActivity;
+import com.wdkl.ncs.android.middleware.api.UrlManager;
+import com.wdkl.ncs.android.middleware.tcp.channel.DeviceChannel;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import okhttp3.Call;
+import okhttp3.Callback;
+import okhttp3.FormBody;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+
+/**
+ * Created by dengzhe on 2018/4/2.
+ * //=========================FC&ANR异常处理类=========================//
+ */
+
+public class AnrFcExceptionUtil implements Thread.UncaughtExceptionHandler {
+
+    private static ANRWatchDog mANRWatchDog;
+    private Thread.UncaughtExceptionHandler mDefaultHandler;
+    public static final String TAG = "AnrFcExceptionUtil";
+    private static Application application;
+
+    private static AnrFcExceptionUtil mAnrFcExceptionUtil;
+
+    private OkHttpClient okHttpClient;
+    private UrlManager urlManager = UrlManager.Companion.build();
+
+    /**
+     * 存储异常和参数信息
+     */
+    private Map<String, String> paramsMap = new HashMap<>();
+    /**
+     * 格式化时间
+     */
+    private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
+
+
+    public static AnrFcExceptionUtil getInstance(Application application) {
+        if (mAnrFcExceptionUtil == null) {
+            mAnrFcExceptionUtil = new AnrFcExceptionUtil(application);
+        }
+        return mAnrFcExceptionUtil;
+    }
+
+    private AnrFcExceptionUtil(Application application) {
+        //获取系统默认的UncaughtException处理器
+        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
+        this.application = application;
+    }
+
+    @Override
+    public void uncaughtException(Thread thread, Throwable ex) {
+        if (!handleException(ex) && mDefaultHandler != null) {
+            //如果用户没有处理则让系统默认的异常处理器来处理
+            mDefaultHandler.uncaughtException(thread, ex);
+        } else {
+            try {
+                Thread.sleep(3000);
+            } catch (InterruptedException e) {
+                Log.e(TAG, "error : ", e);
+            }
+
+            restartApp();
+        }
+    }
+
+    private void restartApp() {
+        DeviceChannel.calling = false;
+
+        //重新启动app
+        Intent mStartActivity = new Intent(application.getApplicationContext(), WelcomeActivity.class);
+        mStartActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+        int mPendingIntentId = 123456;
+        PendingIntent mPendingIntent = PendingIntent.getActivity(application.getApplicationContext(), mPendingIntentId, mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT);
+        AlarmManager mgr = (AlarmManager) application.getApplicationContext().getSystemService(Context.ALARM_SERVICE);
+        mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1500, mPendingIntent);
+
+        android.os.Process.killProcess(android.os.Process.myPid());
+        System.exit(0);
+    }
+
+    /**
+     * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
+     *
+     * @param ex
+     * @return true:如果处理了该异常信息;否则返回false.
+     */
+    private boolean handleException(Throwable ex) {
+        if (ex == null) {
+            return false;
+        }
+
+        saveCrashInfo2File(ex);
+        return true;
+    }
+
+    private void uploadingErrorLog(String class_name, String err_msg, String exception_name, String method_name, String stack_trace) {
+        if(okHttpClient == null){
+            okHttpClient = new OkHttpClient();
+        }
+
+        FormBody.Builder formBody = new FormBody.Builder();
+        formBody.add("class_name",class_name);
+        formBody.add("method_name",method_name);
+        formBody.add("exception_name",exception_name);
+        formBody.add("err_msg",err_msg);
+        formBody.add("stack_trace",stack_trace);
+
+        Request request  = new Request.Builder()
+                .url(urlManager.getBase() + "device/error_log")
+                .post(formBody.build())
+                .build();
+
+        okHttpClient.newCall(request).enqueue(new Callback() {
+            @Override
+            public void onFailure(Call call, IOException e) {
+                Log.e(TAG,"错误日志上传失败"+e.getMessage());
+            }
+
+            @Override
+            public void onResponse(Call call, Response response) throws IOException {
+                Log.d(TAG,"错误日志上传成功");
+                String data = response.body().string();
+                Log.d(TAG,"错误日志数据 data "+data);
+            }
+        });
+    }
+
+    /**
+     * 保存错误信息到文件中
+     *
+     * @param ex
+     * @return 返回文件名称
+     */
+    private String saveCrashInfo2File(Throwable ex) {
+        StringBuffer sb = new StringBuffer();
+        for (Map.Entry<String, String> entry : paramsMap.entrySet()) {
+            String key = entry.getKey();
+            String value = entry.getValue();
+            sb.append(key + "=" + value + "\n");
+        }
+
+        Writer writer = new StringWriter();
+        PrintWriter printWriter = new PrintWriter(writer);
+        ex.printStackTrace(printWriter);
+        Throwable cause = ex.getCause();
+        while (cause != null) {
+            cause.printStackTrace(printWriter);
+            cause = cause.getCause();
+        }
+        printWriter.close();
+        String result = writer.toString();
+        sb.append(result);
+
+
+        try {
+            long timestamp = System.currentTimeMillis();
+            String time = format.format(new Date());
+            String fileName = "crash-" + time + "-" + timestamp + ".txt";
+            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+                String path = Environment.getExternalStorageDirectory() + "/crash/";
+                File dir = new File(path);
+                if (!dir.exists()) {
+                    dir.mkdirs();
+                }
+                FileOutputStream fos = new FileOutputStream(path + fileName);
+                fos.write(sb.toString().getBytes());
+                Log.i(TAG, "saveCrashInfo2File: "+sb.toString());
+                fos.close();
+            }
+
+            //上传错误日志
+            uploadingErrorLog(application.getPackageName(), "crash", "crash", "", sb.toString());
+
+            return fileName;
+        } catch (Exception e) {
+            Log.e(TAG, "an error occured while writing file...", e);
+        }
+
+        return null;
+    }
+
+    /**
+     * ===================================================崩溃异常处理===================================================
+     */
+    public void initFCException() {
+        //设置该CrashHandler为程序的默认处理器
+        AnrFcExceptionUtil catchExcep = AnrFcExceptionUtil.getInstance(application);
+        Thread.setDefaultUncaughtExceptionHandler(catchExcep);
+        mANRWatchDog = new ANRWatchDog(10000);
+        mANRWatchDog.setInterruptionListener(new ANRWatchDog.InterruptionListener() {
+            @Override
+            public void onInterrupted(InterruptedException exception) {
+            }
+        }).setIgnoreDebugger(true).setANRListener(new ANRWatchDog.ANRListener() {
+            @Override
+            public void onAppNotResponding(ANRError error) {
+                /*Intent mStartActivity = new Intent(application.getApplicationContext(), Constants.ANR_FC);
+                int mPendingIntentId = 123456;
+                PendingIntent mPendingIntent = PendingIntent.getActivity(application.getApplicationContext(), mPendingIntentId, mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT);
+                AlarmManager mgr = (AlarmManager) application.getApplicationContext().getSystemService(Context.ALARM_SERVICE);
+                mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1500, mPendingIntent);
+                android.os.Process.killProcess(android.os.Process.myPid());*/
+
+                Log.d("anr", "Anr restart app...");
+                restartApp();
+            }
+        }).start();
+
+    }
+}

+ 147 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/util/AppUtils.java

@@ -0,0 +1,147 @@
+package com.wdkl.ncs.android.component.home.util;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.media.AudioManager;
+import android.os.IBinder;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.inputmethod.InputMethodManager;
+
+import com.wdkl.ncs.android.component.welcome.activity.WelcomeActivity;
+import com.wdkl.ncs.android.lib.base.BaseApplication;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class AppUtils {
+
+    public static void restartApp() {
+        try {
+            Log.i("AppUtil", "restartApp ======================");
+            //重新启动app
+            Intent mStartActivity = new Intent(BaseApplication.appContext, WelcomeActivity.class);
+            mStartActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
+            int mPendingIntentId = 123456;
+            PendingIntent mPendingIntent = PendingIntent.getActivity(BaseApplication.appContext, mPendingIntentId, mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT);
+            AlarmManager mgr = (AlarmManager) BaseApplication.appContext.getSystemService(Context.ALARM_SERVICE);
+            mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1500, mPendingIntent);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        android.os.Process.killProcess(android.os.Process.myPid());
+        System.exit(0);
+    }
+
+    public static void setSystemTime(Context context, long timeMills, String timeZone) {
+        AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+        //alarmManager.setTimeZone("Asia/Shanghai");
+        alarmManager.setTimeZone(timeZone);
+        alarmManager.setTime(timeMills);
+    }
+
+    /**
+     * 设置系统时间
+     *
+     * @param time
+     */
+    public static void setSysTime(String time, String timeZone) {
+        try {
+            Process process = Runtime.getRuntime().exec("su");
+            if (null == process) return;
+            DataOutputStream os = new DataOutputStream(process.getOutputStream());
+            //os.writeBytes("setprop persist.sys.timezone Asia/Shanghai\n");
+            os.writeBytes("setprop persist.sys.timezone " + timeZone + "\n");
+            if (android.os.Build.VERSION.SDK_INT >= 24) {//7.1以上的系统
+                String datetime = changeTimeForm(time); //20211213:092314  ------  051315372019.00
+                os.writeBytes("/system/bin/date " + datetime + " set\n");
+            } else {
+                os.writeBytes("/system/bin/date -s " + time + "\n");//【时间格式 yyyyMMdd.HHmmss】"20131023.112800"
+            }
+            os.writeBytes("clock -w\n");
+            os.writeBytes("exit\n");
+            os.flush();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public static String changeTimeForm(String t) {
+        if (!TextUtils.isEmpty(t) && t.length() >= 15) {
+            String yyyy = substringByLengh(t, 0, 4);
+            String MMdd = substringByLengh(t, 4, 8);
+            String HHmm = substringByLengh(t, 9, 13);
+            String ss = substringByLengh(t, 13, 15);
+
+            return MMdd + HHmm + yyyy + "." + ss;
+        } else {
+            return "051315372019.00";
+        }
+    }
+
+    public static String substringByLengh(String str, int start, int end) {
+        if (str == null) {
+            return "";
+        }
+        if (start > end) {
+            return "";
+        }
+        if (str.length() - 1 < start || str.length() < end) {
+            return "";
+        }
+
+        return str.substring(start, end);
+    }
+
+
+    public static void switchAudioMode(Context context, boolean speakerOn) {
+        AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        audioManager.setSpeakerphoneOn(speakerOn);
+        /*if (speakerOn) {
+            audioManager.setMode(AudioManager.MODE_NORMAL);
+        } else {
+            audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
+        }*/
+    }
+
+    public static void setAudioMode(Context context, int mode) {
+        AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        audioManager.setMode(mode);
+    }
+
+    //隐藏软键盘
+    public static void hideInputKeyboard(IBinder token) {
+        try {
+            Log.d("keyboard", "hide input keyboard ===== ");
+            InputMethodManager mInputKeyBoard = (InputMethodManager) BaseApplication.appContext.getSystemService(Context.INPUT_METHOD_SERVICE);
+            mInputKeyBoard.hideSoftInputFromWindow(token, 0);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    //开启网络调试
+    public static boolean openNetworkDebug() {
+        try {
+            Process process = Runtime.getRuntime().exec("su");
+            if (null == process) {
+                return false;
+            }
+            DataOutputStream os = new DataOutputStream(process.getOutputStream());
+            os.writeBytes("setprop service.adb.tcp.port 5555\n");
+            os.writeBytes("stop adbd\n");
+            os.writeBytes("start adbd\n");
+            os.writeBytes("exit\n");
+            os.flush();
+
+            return true;
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        return false;
+    }
+}

+ 90 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/util/CallDialogHelper.java

@@ -0,0 +1,90 @@
+package com.wdkl.ncs.android.component.home.util;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import com.wdkl.ncs.android.component.home.R;
+import com.wdkl.ncs.android.middleware.utils.RingPlayHelper;
+
+
+public class CallDialogHelper {
+
+    private static AlertDialog callDialog;
+
+    public static void showCallDialog(Activity activity, int callType, String callText, View.OnClickListener hangupCall, View.OnClickListener acceptCall, View.OnClickListener rejectCall) {
+        View contentView = LayoutInflater.from(activity).inflate(R.layout.call_dialog_lay, null);
+        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+        builder.setView(contentView);
+
+        LinearLayout outCall = contentView.findViewById(R.id.ll_call_outgoing);
+        ImageView hangup = contentView.findViewById(R.id.iv_hangup_call);
+
+        RelativeLayout inCall = contentView.findViewById(R.id.rl_call_incoming);
+        ImageView accept = contentView.findViewById(R.id.iv_accept_call);
+        ImageView reject = contentView.findViewById(R.id.iv_reject_call);
+        TextView inText = contentView.findViewById(R.id.tv_incoming_call_text);
+        TextView outText = contentView.findViewById(R.id.tv_out_call_text);
+
+        if (callType == 0) {
+            //去电
+            outCall.setVisibility(View.VISIBLE);
+            inCall.setVisibility(View.GONE);
+            outText.setText(callText);
+            RingPlayHelper.playRingTone(activity, R.raw.ring_back2, true, 60000);
+        } else {
+            //来电
+            outCall.setVisibility(View.GONE);
+            inCall.setVisibility(View.VISIBLE);
+            inText.setText(callText);
+            RingPlayHelper.playRingTone(activity, R.raw.incoming_call, false, 60000);
+
+        }
+
+        hangup.setOnClickListener(hangupCall);
+        accept.setOnClickListener(acceptCall);
+        reject.setOnClickListener(rejectCall);
+
+        callDialog = builder.create();
+        callDialog.setCanceledOnTouchOutside(false);
+        callDialog.setCancelable(false);
+
+        //设置dialog宽高及位置
+        try {
+            Window window = callDialog.getWindow();
+            window.setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
+            callDialog.show();
+            WindowManager.LayoutParams lp = window.getAttributes();
+            lp.width = 800;
+            lp.height = 600;
+            lp.gravity = Gravity.CENTER;
+            //lp.alpha = 0.8f;//设置透明度
+            window.setAttributes(lp);
+
+            window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
+                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
+                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+                    | View.SYSTEM_UI_FLAG_FULLSCREEN);
+            window.clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public static void dismissCallDialog() {
+        if (callDialog != null && callDialog.isShowing()) {
+            callDialog.dismiss();
+            RingPlayHelper.stopRingTone();
+        }
+    }
+}

+ 14 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/util/EthernetWifiCallBack.java

@@ -0,0 +1,14 @@
+package com.wdkl.ncs.android.component.home.util;
+
+/**
+ * ======================以太网和wifi状态接口=====================
+ * Created by dengzhe on 2018/2/7.
+ */
+
+public interface EthernetWifiCallBack {
+
+    boolean ethernetStatus(boolean status);//以太网状态
+
+    boolean wifiStatus(boolean status);//wifi状态
+
+}

+ 80 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/util/LocaleMangerUtils.java

@@ -0,0 +1,80 @@
+package com.wdkl.ncs.android.component.home.util;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.os.Build;
+import android.util.DisplayMetrics;
+import android.util.Log;
+
+import com.wdkl.ncs.android.component.home.R;
+import com.wdkl.ncs.android.component.home.settingconfig.SettingConfig;
+import com.wdkl.ncs.android.lib.base.BaseApplication;
+
+import java.util.Locale;
+
+public class LocaleMangerUtils {
+
+    public static Locale getSystemLocale() {
+        return Locale.getDefault();
+    }
+
+    //获取当前语言id: 0--auto, 1--English, 2--中文, 3--西班牙语, 4--俄语
+    public static int getCurrentLocaleIndex() {
+        int languageSize = BaseApplication.appContext.getResources().getStringArray(R.array.language_list).length;
+        int index = SettingConfig.getLanguageId(BaseApplication.appContext);
+        //Log.d("wzl", "current language index: " + index);
+        if (index >= 0 && index <languageSize) {
+            return index;
+        } else {
+            return 0;
+        }
+    }
+
+    public static void setApplicationLanguageByIndex(Context context, int index) {
+        Locale locale = Locale.getDefault();
+        switch (index) {
+            case 0:
+                //
+                break;
+            case 1:
+                locale = Locale.ENGLISH;
+                break;
+            case 2:
+                locale = Locale.CHINESE;
+                break;
+            case 3:
+                locale = new Locale("es");
+                break;
+            case 4:
+                locale = new Locale("ru");
+                break;
+        }
+
+        setApplicationLanguage(context, locale);
+    }
+
+    public static void setApplicationLanguage(Context context, Locale locale) {
+        Log.d("locale", "set locale language: " + locale.getLanguage());
+        Configuration configuration = context.getResources().getConfiguration();
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+            configuration.setLocale(locale);
+        } else {
+            configuration.locale = locale;
+        }
+        // 更新context中的语言设置
+        Resources resources = context.getResources();
+        DisplayMetrics dm = resources.getDisplayMetrics();
+        resources.updateConfiguration(configuration, dm);
+    }
+
+    public static Locale getApplicationLocale() {
+        Configuration config = BaseApplication.appContext.getResources().getConfiguration();
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+            return config.locale;
+        } else {
+            return config.getLocales().get(0);
+        }
+    }
+
+}

+ 283 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/util/MediaPlayHelper.java

@@ -0,0 +1,283 @@
+package com.wdkl.ncs.android.component.home.util;
+
+import android.content.Intent;
+import android.media.AudioManager;
+import android.media.MediaPlayer;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Message;
+import android.support.v4.media.session.MediaSessionCompat;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.KeyEvent;
+
+import com.wdkl.ncs.android.lib.base.BaseApplication;
+import com.wdkl.ncs.android.middleware.common.Constant;
+import com.wdkl.ncs.android.middleware.common.MessageEvent;
+import com.wdkl.ncs.janus.rtc.AudioFocusManager;
+
+import org.greenrobot.eventbus.EventBus;
+
+public class MediaPlayHelper {
+    private static String TAG = MediaPlayHelper.class.getCanonicalName();
+
+    private static MediaPlayHelper sInstance = null;
+    private MediaPlayer mediaPlayer;
+    private HandlerThread playHandlerThread;
+    private Handler playHandler;
+    private MediaSessionCompat mediaSessionCompat;
+    private AudioFocusManager audioFocusManager;
+
+    private int mResId;
+    private String mUrl;
+    private float mVolume;
+    private boolean mLoop;
+
+    /**
+     * 播放res资源
+     */
+    public static final int PLAY_RES = 100;
+    /**
+     * 播放url资源
+     */
+    public static final int PLAY_URL = 101;
+    /**
+     * 停止
+     */
+    public static final int STOP = 102;
+    /**
+     * 释放
+     */
+    public static final int RELEASE = 103;
+
+
+    private MediaPlayHelper() {
+        createHandlerThread();
+        audioFocusManager = new AudioFocusManager(BaseApplication.appContext);
+    }
+
+    public static MediaPlayHelper getInstance() {
+        if (sInstance == null) {
+            synchronized (MediaPlayHelper.class) {
+                if (sInstance == null) {
+                    sInstance = new MediaPlayHelper();
+                }
+            }
+        }
+        return sInstance;
+    }
+
+    private void createHandlerThread() {
+        if (playHandlerThread == null) {
+            playHandlerThread = new HandlerThread("playHandlerThread");
+            playHandlerThread.start();
+        }
+
+        if (playHandler == null) {
+            playHandler = new Handler(playHandlerThread.getLooper()) {
+                @Override
+                public void handleMessage(Message msg) {
+                    switch (msg.what) {
+                        case PLAY_RES:
+                            playResMusicNow();
+                            break;
+                        case PLAY_URL:
+                            playUrlMusicNow();
+                            break;
+                        case STOP:
+                            stopMusicNow();
+                            break;
+                        case RELEASE:
+                            releaseMediaNow();
+                            break;
+                        default:
+                            break;
+                    }
+                }
+            };
+        }
+    }
+
+    public void playResMusic(int id, float vol, boolean loop) {
+        mResId = id;
+        mVolume = vol;
+        mLoop = loop;
+        playHandler.sendEmptyMessage(PLAY_RES);
+    }
+
+    public void playUrlMusic(String url, float vol, boolean loop) {
+        mUrl = url;
+        mVolume = vol;
+        mLoop = loop;
+        playHandler.sendEmptyMessage(PLAY_URL);
+    }
+
+    public void stopMusic() {
+        playHandler.sendEmptyMessage(STOP);
+    }
+
+    public void releaseMusic() {
+        playHandler.sendEmptyMessage(RELEASE);
+    }
+
+    //播放本地res音频资源
+    private void playResMusicNow() {
+        if (mediaPlayer != null) {
+            mediaPlayer.stop();
+        }
+        mediaPlayer = MediaPlayer.create(BaseApplication.appContext, mResId);
+        try {
+            mediaPlayer.setLooping(mLoop);
+            mediaPlayer.setVolume(mVolume, mVolume);
+            mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
+            mediaPlayer.start();
+            mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
+                @Override
+                public void onCompletion(MediaPlayer player) {
+                    //playMusicComplete();
+                    //stopMusicNow();
+                }
+            });
+            mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
+                @Override
+                public boolean onError(MediaPlayer player, int what, int extra) {
+                    //playMusicError();
+                    stopMusicNow();
+                    releaseMediaSession();
+                    return false;
+                }
+            });
+            initMediaSession();
+        } catch (Exception e) {
+            //playMusicError();
+            e.printStackTrace();
+        }
+    }
+
+    //播放远程或本地存储音频资源
+    private void playUrlMusicNow() {
+        if (mediaPlayer != null) {
+            mediaPlayer.stop();
+        }
+        mediaPlayer = new MediaPlayer();
+        try {
+            mediaPlayer.reset();
+            mediaPlayer.setDataSource(mUrl);
+            mediaPlayer.setLooping(mLoop);
+            mediaPlayer.setVolume(mVolume, mVolume);
+            mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
+            mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
+                @Override
+                public void onPrepared(MediaPlayer player) {
+                    if (mediaPlayer != null) {
+                        mediaPlayer.start();
+                    }
+                }
+            });
+            mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
+                @Override
+                public void onCompletion(MediaPlayer player) {
+                    //playMusicComplete();
+                    //stopMusicNow();
+                }
+            });
+            mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
+                @Override
+                public boolean onError(MediaPlayer player, int what, int extra) {
+                    //playMusicError();
+                    stopMusicNow();
+                    return false;
+                }
+            });
+            mediaPlayer.prepareAsync();
+        } catch (Exception e) {
+            //playMusicError();
+            e.printStackTrace();
+        }
+    }
+
+    private void stopMusicNow() {
+        if (mediaPlayer != null) {
+            mediaPlayer.setOnPreparedListener(null);
+            mediaPlayer.setOnCompletionListener(null);
+            try {
+                if (mediaPlayer.isPlaying()) {
+                    mediaPlayer.stop();
+                }
+            } catch (IllegalStateException e) {
+                e.printStackTrace();
+            }
+        }
+        mediaPlayer = null;
+        releaseMediaSession();
+    }
+
+    private void releaseMediaNow() {
+        if (mediaPlayer != null) {
+            mediaPlayer.setOnPreparedListener(null);
+            mediaPlayer.setOnCompletionListener(null);
+            try {
+                mediaPlayer.stop();
+                mediaPlayer.release();
+            } catch (IllegalStateException e) {
+                e.printStackTrace();
+            }
+        }
+        mediaPlayer = null;
+        releaseMediaSession();
+    }
+
+    public boolean isMediaPlaying() {
+        if (mediaPlayer != null) {
+            return mediaPlayer.isPlaying();
+        }
+        return false;
+    }
+
+    private void initMediaSession(){
+        if (mediaSessionCompat!=null){
+            releaseMediaSession();
+        }
+
+        audioFocusManager.requestFocus();
+
+        mediaSessionCompat = new MediaSessionCompat(BaseApplication.appContext,TAG);
+        mediaSessionCompat.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS);
+        mediaSessionCompat.setActive(true);
+        mediaSessionCompat.setCallback(new MediaSessionCompat.Callback(){
+            @Override
+            public boolean onMediaButtonEvent(Intent intent) {
+                String action = intent.getAction();
+                if (action != null) {
+                    if (TextUtils.equals(action, Intent.ACTION_MEDIA_BUTTON)) {
+                        KeyEvent keyEvent = intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
+                        if (keyEvent.getAction() == KeyEvent.ACTION_DOWN) {
+                            Integer keyCode = keyEvent.getKeyCode();
+                            Log.i(TAG, "mediasession keycode " + keyCode);
+                            switch (keyCode) {
+                                case KeyEvent.KEYCODE_MEDIA_PLAY:
+                                case KeyEvent.KEYCODE_MEDIA_PAUSE:
+                                    EventBus.getDefault().post(new MessageEvent(1, Constant.EVENT_BLUETOOTH_ACCEPT_CALL));
+                                    break;
+                                default:
+                                    break;
+                            }
+                        }
+                    }
+                }
+                return super.onMediaButtonEvent(intent);
+            }
+        });
+    }
+
+    private void releaseMediaSession(){
+        if (mediaSessionCompat!=null){
+            mediaSessionCompat.setCallback(null);
+            mediaSessionCompat.setActive(false);
+            mediaSessionCompat.release();
+            mediaSessionCompat = null;
+
+            audioFocusManager.releaseAudioFocus();
+        }
+    }
+}

+ 115 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/util/MediaPlayer.kt

@@ -0,0 +1,115 @@
+package com.wdkl.ncs.android.component.nursehome.util
+
+import android.media.AudioManager
+import android.media.MediaPlayer
+import android.util.Log
+import com.umeng.weixin.umengwx.e
+import java.io.IOException
+import java.lang.IllegalStateException
+
+class MediaPlayer {
+    private val TAG = MediaPlayer::class.java.getSimpleName()
+
+    var mMediaPlayer: MediaPlayer? = null
+
+    init {
+        Log.e(TAG, "初始化播放器")
+        mMediaPlayer = MediaPlayer()
+        //这样设置 不能控制本音乐的音量大小 也就是setVolume无效
+//        mMediaPlayer!!.setAudioStreamType(AudioManager.STREAM_MUSIC)
+        mMediaPlayer!!.setAudioStreamType(AudioManager.STREAM_VOICE_CALL)
+        mMediaPlayer!!.setOnCompletionListener {
+            Log.e(TAG, "播放完成")
+        }
+
+        mMediaPlayer!!.setOnPreparedListener {
+            Log.e(TAG, "加载完长")
+            mMediaPlayer!!.start()
+        }
+        mMediaPlayer!!.setOnErrorListener { mp, what, extra ->
+            Log.e(TAG, "异常")
+            false
+        }
+
+    }
+
+    //启动播放
+    fun startMediaPlayer(url: String) {
+        if ((mMediaPlayer != null && mMediaPlayer!!.isPlaying())) {
+            mMediaPlayer!!.stop()
+        }
+        mMediaPlayer!!.reset()
+        //设置音频文件到MediaPlayer对象中
+        //测试地址 "http://file.kuyinyun.com/group1/M00/90/B7/rBBGdFPXJNeAM-nhABeMElAM6bY151.mp3"
+        try {
+            mMediaPlayer!!.setDataSource(url)
+            //让MediaPlayer对象准备,用这个方法防止加载时耗时导致anr
+            mMediaPlayer!!.prepareAsync()
+        } catch (e: IOException) {
+            e.printStackTrace()
+            Log.e(TAG, "播放异常")
+        }catch (e:IllegalStateException) {
+            e.message
+            Log.e(TAG, "IllegalStateException+播放异常");
+        }
+
+    }
+
+    /**
+     * 暂停播放
+     */
+    fun pauseMediaPlayer() {
+        if (mMediaPlayer != null) {
+            mMediaPlayer!!.pause()
+        }
+
+    }
+
+    /**
+     * 继续播放
+     */
+    fun continueToPlayMediaPlayer() {
+        if (mMediaPlayer != null) {
+            mMediaPlayer!!.start()
+        }
+
+    }
+
+    /**
+     * 停止播放
+     */
+    fun stopMediaPlayer() {
+        if (mMediaPlayer != null) {
+            mMediaPlayer!!.stop()
+        }
+    }
+
+    /**
+     * 释放播放器资源
+     */
+    fun releaseMediaPlayer() {
+        if (mMediaPlayer != null) {
+            try {
+                mMediaPlayer!!.stop()
+                mMediaPlayer!!.release()
+            } catch (e: IllegalStateException) {
+
+            }
+
+        }
+        mMediaPlayer = null
+    }
+
+    /**
+     * 音量设置
+     *setDataSource()方法之后设置才有效
+     * @param volume
+     */
+    fun setVolume(volume: Float) {
+        if (mMediaPlayer != null) {
+            mMediaPlayer!!.setVolume(volume, volume)
+        }
+    }
+
+
+}

+ 658 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/util/NetHelper.java

@@ -0,0 +1,658 @@
+package com.wdkl.ncs.android.component.home.util;
+
+import android.Manifest;
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.os.Build;
+import android.provider.Settings;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+
+import com.wdkl.ncs.android.lib.base.BaseApplication;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Timer;
+import java.util.TimerTask;
+
+
+public class NetHelper {
+    private WifiManager wifiManager;
+    private ConnectivityManager connManager;
+    private static NetHelper sInstance = null;
+
+    private static Timer timerNetStatus = null;
+    private static final int SCHEDULE_TIME = 20000;
+    public static boolean NetConn = false;
+
+    public static final int NETWORK_NONE = -1;
+    public static final int NETWORK_WIFI = 1;
+    public static final int NETWORK_2G = 2;
+    public static final int NETWORK_3G = 3;
+    public static final int NETWORK_4G = 4;
+    public static final int NETWORK_MOBILE = 5;
+
+    /**
+     * 以太网是否ping成功
+     */
+    public static final String ETHERNETSTATUS = "ethernetStatus";
+
+    public NetHelper() {
+    }
+
+    public static NetHelper getInstance() {
+        if (sInstance == null) {
+            synchronized (NetHelper.class) {
+                if (sInstance == null) {
+                    sInstance = new NetHelper();
+                }
+            }
+        }
+        return sInstance;
+    }
+
+    public void init() {
+        wifiManager = (WifiManager) BaseApplication.appContext.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
+        connManager = (ConnectivityManager) BaseApplication.appContext.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
+    }
+
+    /**
+     * ping 网络
+     *
+     * @param host
+     * @param pingCount
+     * @param stringBuffer
+     * @return
+     */
+    public static boolean ping(String host, int pingCount, StringBuffer stringBuffer) {
+        String line = null;
+        Process process = null;
+        BufferedReader successReader = null;
+        String command = "ping -c " + pingCount + " " + host;
+        boolean isSuccess = false;
+        try {
+            process = Runtime.getRuntime().exec(command);
+            if (process == null) {
+                append(stringBuffer, "ping fail:process is null.");
+                return false;
+            }
+            successReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
+            while ((line = successReader.readLine()) != null) {
+                append(stringBuffer, line);
+            }
+            int status = process.waitFor();
+            if (status == 0) {
+                append(stringBuffer, "exec cmd success:" + command);
+                isSuccess = true;
+            } else {
+                append(stringBuffer, "exec cmd fail.");
+                isSuccess = false;
+            }
+            append(stringBuffer, "exec finished.");
+        } catch (IOException e) {
+        } catch (InterruptedException e) {
+        } finally {
+            if (process != null) {
+                process.destroy();
+            }
+            if (successReader != null) {
+                try {
+                    successReader.close();
+                } catch (IOException e) {
+                }
+            }
+        }
+
+        return isSuccess;
+    }
+
+    private static void append(StringBuffer stringBuffer, String text) {
+        if (stringBuffer != null) {
+            stringBuffer.append(text + "\n");
+        }
+    }
+
+    /**
+     * 获取网关  Waderson
+     * <p>
+     * 1 WIFI情况下获取网关 2 有线网络下的DHCP模式连接 3 有线网络其他连接方式:比如静态ip、pppoe拨号、ipoe拨号等
+     */
+    public static String getLocalElement(int type) {
+        String e = "";
+        if (1 == type) {
+            //e = getLocalElementByWifi();
+        } else if (2 == type) {
+            e = getLocalElementByDhcp();
+        } else if (3 == type) {
+            e = getLocalElementByIp();
+        }
+        if (!TextUtils.isEmpty(e) && e.length() >= 11 && e.length() <= 15) {
+            return e;
+        } else {
+            return "192.168.101.1";
+        }
+    }
+
+
+    /**
+     * 有线网络下的DHCP模式连接
+     */
+    public static String getLocalElementByDhcp() {
+        BufferedReader bufferedReader = null;
+        String str2 = "";
+        String str3 = "getprop dhcp.eth0.gateway";
+        Process exec;
+        BufferedReader bufferedReader2 = null;
+        try {
+            exec = Runtime.getRuntime().exec(str3);
+            try {
+                bufferedReader2 = new BufferedReader(new InputStreamReader(exec.getInputStream()));
+            } catch (Throwable th3) {
+                if (bufferedReader != null) {
+                    bufferedReader.close();
+                }
+                if (exec != null) {
+                    exec.exitValue();
+                }
+            }
+            try {
+                str3 = bufferedReader2.readLine();
+                if (str3 != null) {
+                    TextUtils.isEmpty(str3);
+                }
+                try {
+                    bufferedReader2.close();
+                } catch (IOException iOException222) {
+                    iOException222.printStackTrace();
+                }
+                if (exec != null) {
+                    try {
+                        exec.exitValue();
+                    } catch (Exception e5) {
+                    }
+                }
+            } catch (IOException e6) {
+                str3 = str2;
+                if (bufferedReader2 != null) {
+                    bufferedReader2.close();
+                }
+                if (exec != null) {
+                    exec.exitValue();
+                }
+                return str3;
+            }
+        } catch (IOException e62) {
+            bufferedReader2 = null;
+            exec = null;
+            str3 = str2;
+            if (bufferedReader2 != null) {
+                try {
+                    bufferedReader2.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+            if (exec != null) {
+                exec.exitValue();
+            }
+            return str3;
+        } catch (Throwable th4) {
+            exec = null;
+            if (bufferedReader != null) {
+                try {
+                    bufferedReader.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+            if (exec != null) {
+                exec.exitValue();
+            }
+        }
+        return str3;
+    }
+
+    /**
+     * 有线网络其他连接方式:比如静态ip、pppoe拨号、ipoe拨号等
+     */
+    public static String getLocalElementByIp() {
+        BufferedReader bufferedReader = null;
+        String result = "";
+        String str2 = "";
+        String str3 = "ip route list table 0";
+        Process exec;
+        BufferedReader bufferedReader2 = null;
+        try {
+            exec = Runtime.getRuntime().exec(str3);
+            try {
+                bufferedReader2 = new BufferedReader(new InputStreamReader(exec.getInputStream()));
+            } catch (Throwable th3) {
+                if (bufferedReader != null) {
+                    bufferedReader.close();
+                }
+                if (exec != null) {
+                    exec.exitValue();
+                }
+            }
+            try {
+                str2 = bufferedReader2.readLine();
+                if (str2 != null) {
+                    str2 = str2.trim();
+                    String[] strings = str2.split("\\s+");
+                    if (strings.length > 3) {
+                        result = strings[2];
+                    }
+                }
+                try {
+                    bufferedReader2.close();
+                } catch (IOException iOException222) {
+                    iOException222.printStackTrace();
+                }
+                if (exec != null) {
+                    try {
+                        exec.exitValue();
+                    } catch (Exception e5) {
+                    }
+                }
+            } catch (IOException e6) {
+                if (bufferedReader2 != null) {
+                    bufferedReader2.close();
+                }
+                if (exec != null) {
+                    exec.exitValue();
+                }
+                return result;
+            }
+        } catch (IOException e62) {
+            bufferedReader2 = null;
+            exec = null;
+            if (bufferedReader2 != null) {
+                try {
+                    bufferedReader2.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+            if (exec != null) {
+                exec.exitValue();
+            }
+            return result;
+        } catch (Throwable th4) {
+            exec = null;
+            if (bufferedReader != null) {
+                try {
+                    bufferedReader.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+            if (exec != null) {
+                exec.exitValue();
+            }
+        }
+        return result;
+    }
+
+    /**
+     * 得到MAC
+     *
+     * @return String
+     */
+    public String getMacAddress() {
+        if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.O){//小于安卓8 走这里
+            String mac = "";
+            try {
+                mac = getLocalMacAddressFromIp();
+                if (TextUtils.isEmpty(mac)) {
+                    mac = getNetworkMac();
+                }
+                if (TextUtils.isEmpty(mac)) {
+                    mac = tryGetWifiMac();
+                }
+            } catch (Exception e) {
+            }
+            return mac;
+        }else {//大于安卓8走这里
+            List<NetworkInterface> interfaces = null;
+            try {
+                interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
+                for (NetworkInterface networkInterface : interfaces) {
+                    if (networkInterface != null && TextUtils.isEmpty(networkInterface.getName()) == false) {
+                        if ("wlan0".equalsIgnoreCase(networkInterface.getName())) {
+                            byte[] macBytes = networkInterface.getHardwareAddress();
+                            if (macBytes != null && macBytes.length > 0) {
+                                StringBuilder str = new StringBuilder();
+                                for (byte b : macBytes) {
+                                    str.append(String.format("%02X:", b));
+                                }
+                                if (str.length() > 0) {
+                                    str.deleteCharAt(str.length() - 1);
+                                }
+                                return str.toString();
+                            }
+                        }
+                    }
+                }
+            } catch (SocketException e) {
+                e.printStackTrace();
+            }
+            return "unknown";
+
+        }
+    }
+
+    /**
+     * 兼容安卓5-10 获取Mac地址
+     * @return
+     */
+    public String getMacAddress2() {
+        List<NetworkInterface> interfaces = null;
+        try {
+            interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
+            for (NetworkInterface networkInterface : interfaces) {
+                if (networkInterface != null && TextUtils.isEmpty(networkInterface.getName()) == false) {
+                    if ("wlan0".equalsIgnoreCase(networkInterface.getName())) {
+                        byte[] macBytes = networkInterface.getHardwareAddress();
+                        if (macBytes != null && macBytes.length > 0) {
+                            StringBuilder str = new StringBuilder();
+                            for (byte b : macBytes) {
+                                str.append(String.format("%02X:", b));
+                            }
+                            if (str.length() > 0) {
+                                str.deleteCharAt(str.length() - 1);
+                            }
+                            return str.toString();
+                        }
+                    }
+                }
+            }
+        } catch (SocketException e) {
+            e.printStackTrace();
+        }
+        return "unknown";
+    }
+
+
+    /**
+     * 通过WiFiManager获取mac地址
+     * 这个方法Android 7.0是获取不到的,返回的是null,其实是返回“02:00:00:00:00:00”
+     *
+     * @return
+     */
+    public String tryGetWifiMac() {
+        String mac;
+        WifiInfo wi = wifiManager.getConnectionInfo();
+        if (wi == null || wi.getMacAddress() == null) {
+            mac = null;
+        }
+        if ("02:00:00:00:00:00".equals(wi.getMacAddress().trim())) {
+            mac = null;
+        } else {
+            mac = wi.getMacAddress().trim();
+        }
+        return mac;
+    }
+
+    /**
+     * 通过网络接口获取
+     *
+     * @return
+     */
+    public static String getNetworkMac() {
+        try {
+            List<NetworkInterface> all = Collections.list(NetworkInterface.getNetworkInterfaces());
+            for (NetworkInterface nif : all) {
+                // if (!nif.getName().equalsIgnoreCase("wlan0") && !nif.getName().equalsIgnoreCase("eth0") && !nif.getName().equalsIgnoreCase("eth1"))
+                if (!nif.getName().equalsIgnoreCase("eth0") && !nif.getName().equalsIgnoreCase("eth1") && !nif.getName().equalsIgnoreCase("eth2"))
+                    continue;
+                byte[] macBytes = nif.getHardwareAddress();
+                if (macBytes == null) {
+                    return null;
+                }
+                StringBuilder res1 = new StringBuilder();
+                for (byte b : macBytes) {
+                    res1.append(String.format("%02X:", b));
+                }
+                if (res1.length() > 0) {
+                    res1.deleteCharAt(res1.length() - 1);
+                }
+                return res1.toString();
+            }
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+        return null;
+    }
+
+    public String getIMEI() {
+        //获取序列号
+        String serial = null;
+        try {
+            serial = android.os.Build.SERIAL;
+            if (serial.equalsIgnoreCase("unknown")||serial.equalsIgnoreCase("0123456789abcdef")) {
+                final TelephonyManager mTelephony = (TelephonyManager) BaseApplication.appContext.getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE);
+                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+                    if (BaseApplication.appContext.getApplicationContext().checkSelfPermission(Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
+                        serial = null;
+                    }
+                }
+                assert mTelephony != null;
+                if (mTelephony.getDeviceId() != null) {
+                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+                        serial = mTelephony.getImei();
+                    } else {
+                        serial = mTelephony.getDeviceId();
+                    }
+                } else {
+                    serial = Settings.Secure.getString(BaseApplication.appContext.getApplicationContext().getContentResolver(), Settings.Secure.ANDROID_ID);
+                }
+
+            }
+        } catch (Exception e) {
+
+        }
+        return serial;
+    }
+
+    public String getIMEI2() {
+        String serial = "null";
+        try {
+            final TelephonyManager mTelephony = (TelephonyManager) BaseApplication.appContext.getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE);
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+                if (BaseApplication.appContext.getApplicationContext().checkSelfPermission(Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
+                    return serial;
+                }
+            }
+
+            assert mTelephony != null;
+            if (mTelephony.getDeviceId() != null) {
+                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+                    serial = mTelephony.getImei();
+                } else {
+                    serial = mTelephony.getDeviceId();
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return serial;
+    }
+
+
+    /**
+     * 根据IP地址获取MAC地址
+     *
+     * @return
+     */
+    @SuppressLint("NewApi")
+    public static String getLocalMacAddressFromIp() {
+        String strMacAddr = null;
+        try {
+            // 获得IpD地址
+            InetAddress ip = getLocalInetAddress();
+            byte[] b = NetworkInterface.getByInetAddress(ip)
+                    .getHardwareAddress();
+            StringBuffer buffer = new StringBuffer();
+            for (int i = 0; i < b.length; i++) {
+                if (i != 0) {
+                    buffer.append(':');
+                }
+                String str = Integer.toHexString(b[i] & 0xFF);
+                buffer.append(str.length() == 1 ? 0 + str : str);
+            }
+            strMacAddr = buffer.toString().toUpperCase();
+
+        } catch (Exception e) {
+
+        }
+
+        return strMacAddr;
+    }
+
+    /**
+     * 获取移动设备本地IP
+     *
+     * @return
+     */
+    public static InetAddress getLocalInetAddress() {
+        InetAddress ip = null;
+        try {
+            // 列举
+            Enumeration<NetworkInterface> en_netInterface = NetworkInterface
+                    .getNetworkInterfaces();
+            while (en_netInterface.hasMoreElements()) {// 是否还有元素
+                NetworkInterface ni = (NetworkInterface) en_netInterface
+                        .nextElement();// 得到下一个元素
+                Enumeration<InetAddress> en_ip = ni.getInetAddresses();// 得到一个ip地址的列举
+                while (en_ip.hasMoreElements()) {
+                    ip = en_ip.nextElement();
+                    if (!ip.isLoopbackAddress()
+                            && ip.getHostAddress().indexOf(":") == -1)
+                        break;
+                    else
+                        ip = null;
+                }
+
+                if (ip != null) {
+                    break;
+                }
+            }
+        } catch (SocketException e) {
+
+            e.printStackTrace();
+        }
+        return ip;
+    }
+
+    //获取本地ip地址
+    public String getLocalIP() {
+        try {
+            for (Enumeration<NetworkInterface> enNetI = NetworkInterface.getNetworkInterfaces(); enNetI.hasMoreElements(); ) {
+                NetworkInterface netI = enNetI.nextElement();
+                for (Enumeration<InetAddress> enumIpAddr = netI.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
+                    InetAddress inetAddress = enumIpAddr.nextElement();
+                    if (inetAddress instanceof Inet4Address && !inetAddress.isLoopbackAddress()) {
+                        return inetAddress.getHostAddress();
+                    }
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    public int getNetworkType() {
+        if (connManager != null && connManager.getActiveNetworkInfo() != null) {
+            return connManager.getActiveNetworkInfo().getType();
+        }
+
+        return -1;
+    }
+
+    /**
+     * 获取当前网络连接的类型
+     *
+     * @param context context
+     * @return int
+     */
+    public int getNetworkState(Context context) {
+        ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); // 获取网络服务
+        if (null == connManager) { // 为空则认为无网络
+            return NETWORK_NONE;
+        }
+        // 获取网络类型,如果为空,返回无网络
+        NetworkInfo activeNetInfo = connManager.getActiveNetworkInfo();
+        if (activeNetInfo == null || !activeNetInfo.isAvailable()) {
+            return NETWORK_NONE;
+        }
+        // 判断是否为WIFI
+        NetworkInfo wifiInfo = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
+        if (null != wifiInfo) {
+            NetworkInfo.State state = wifiInfo.getState();
+            if (null != state) {
+                if (state == NetworkInfo.State.CONNECTED || state == NetworkInfo.State.CONNECTING) {
+                    return NETWORK_WIFI;
+                }
+            }
+        }
+        // 若不是WIFI,则去判断是2G、3G、4G网
+        TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+        int networkType = telephonyManager.getNetworkType();
+        switch (networkType) {
+            /*
+             GPRS : 2G(2.5) General Packet Radia Service 114kbps
+             EDGE : 2G(2.75G) Enhanced Data Rate for GSM Evolution 384kbps
+             UMTS : 3G WCDMA 联通3G Universal Mobile Telecommunication System 完整的3G移动通信技术标准
+             CDMA : 2G 电信 Code Division Multiple Access 码分多址
+             EVDO_0 : 3G (EVDO 全程 CDMA2000 1xEV-DO) Evolution - Data Only (Data Optimized) 153.6kps - 2.4mbps 属于3G
+             EVDO_A : 3G 1.8mbps - 3.1mbps 属于3G过渡,3.5G
+             1xRTT : 2G CDMA2000 1xRTT (RTT - 无线电传输技术) 144kbps 2G的过渡,
+             HSDPA : 3.5G 高速下行分组接入 3.5G WCDMA High Speed Downlink Packet Access 14.4mbps
+             HSUPA : 3.5G High Speed Uplink Packet Access 高速上行链路分组接入 1.4 - 5.8 mbps
+             HSPA : 3G (分HSDPA,HSUPA) High Speed Packet Access
+             IDEN : 2G Integrated Dispatch Enhanced Networks 集成数字增强型网络 (属于2G,来自维基百科)
+             EVDO_B : 3G EV-DO Rev.B 14.7Mbps 下行 3.5G
+             LTE : 4G Long Term Evolution FDD-LTE 和 TDD-LTE , 3G过渡,升级版 LTE Advanced 才是4G
+             EHRPD : 3G CDMA2000向LTE 4G的中间产物 Evolved High Rate Packet Data HRPD的升级
+             HSPAP : 3G HSPAP 比 HSDPA 快些
+             */
+            // 2G网络
+            case TelephonyManager.NETWORK_TYPE_GPRS:
+            case TelephonyManager.NETWORK_TYPE_CDMA:
+            case TelephonyManager.NETWORK_TYPE_EDGE:
+            case TelephonyManager.NETWORK_TYPE_1xRTT:
+            case TelephonyManager.NETWORK_TYPE_IDEN:
+                return NETWORK_2G;
+            // 3G网络
+            case TelephonyManager.NETWORK_TYPE_EVDO_A:
+            case TelephonyManager.NETWORK_TYPE_UMTS:
+            case TelephonyManager.NETWORK_TYPE_EVDO_0:
+            case TelephonyManager.NETWORK_TYPE_HSDPA:
+            case TelephonyManager.NETWORK_TYPE_HSUPA:
+            case TelephonyManager.NETWORK_TYPE_HSPA:
+            case TelephonyManager.NETWORK_TYPE_EVDO_B:
+            case TelephonyManager.NETWORK_TYPE_EHRPD:
+            case TelephonyManager.NETWORK_TYPE_HSPAP:
+                return NETWORK_3G;
+            // 4G网络
+            case TelephonyManager.NETWORK_TYPE_LTE:
+                return NETWORK_4G;
+            default:
+                return NETWORK_MOBILE;
+        }
+    }
+}

+ 233 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/util/SPUtils.java

@@ -0,0 +1,233 @@
+package com.wdkl.ncs.android.component.home.util;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+
+import com.wdkl.ncs.android.middleware.common.Constant;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ * @Author: WangYong on 2020/11/3
+ * @Description:
+ */
+public class SPUtils {
+    public SPUtils() {
+        /* cannot be instantiated */
+        throw new UnsupportedOperationException("cannot be instantiated");
+    }
+
+    // 系统语言
+    private final String SP_NAME = "language_setting";
+    private final String TAG_LANGUAGE = "language_select";
+    private static volatile SPUtils instance;
+    private final SharedPreferences mSharedPreferences;
+    private Locale systemCurrentLocal = Locale.CHINESE;
+
+    public SPUtils(Context context) {
+        mSharedPreferences = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
+    }
+
+    public void saveLanguage(int select) {
+        SharedPreferences.Editor edit = mSharedPreferences.edit();
+        edit.putInt(TAG_LANGUAGE, select);
+        edit.commit();
+    }
+
+    public int getSelectLanguage() {
+        return mSharedPreferences.getInt(TAG_LANGUAGE, 1);
+    }
+
+    public Locale getSystemCurrentLocal() {
+        return systemCurrentLocal;
+    }
+
+    public void setSystemCurrentLocal(Locale local) {
+        systemCurrentLocal = local;
+    }
+
+    public static SPUtils getInstance(Context context) {
+        if (instance == null) {
+            synchronized (SPUtils.class) {
+                if (instance == null) {
+                    instance = new SPUtils(context);
+                }
+            }
+        }
+        return instance;
+    }
+
+    /**
+     * 保存数据的方法,我们需要拿到保存数据的具体类型,然后根据类型调用不同的保存方法
+     *
+     * @param context
+     * @param key
+     * @param object
+     */
+    public static void put(Context context, String key, Object object) {
+
+        SharedPreferences sp = context.getSharedPreferences(Constant.PREFERENCE_USER, Context.MODE_PRIVATE);
+        SharedPreferences.Editor editor = sp.edit();
+
+        if (object instanceof String) {
+            editor.putString(key, (String) object);
+        } else if (object instanceof Integer) {
+            editor.putInt(key, (Integer) object);
+        } else if (object instanceof Boolean) {
+            editor.putBoolean(key, (Boolean) object);
+        } else if (object instanceof Float) {
+            editor.putFloat(key, (Float) object);
+        } else if (object instanceof Long) {
+            editor.putLong(key, (Long) object);
+        } else {
+            editor.putString(key, object.toString());
+        }
+
+        SharedPreferencesCompat.apply(editor);
+    }
+
+
+    /**
+     * 得到保存数据的方法,我们根据默认值得到保存的数据的具体类型,然后调用相对于的方法获取值
+     *
+     * @param context
+     * @param key
+     * @param defaultObject
+     * @return
+     */
+    public static Object get(Context context, String key, Object defaultObject) {
+        SharedPreferences sp = context.getSharedPreferences(Constant.PREFERENCE_USER, Context.MODE_PRIVATE);
+
+        if (defaultObject instanceof String) {
+            return sp.getString(key, (String) defaultObject);
+        } else if (defaultObject instanceof Integer) {
+            return sp.getInt(key, (Integer) defaultObject);
+        } else if (defaultObject instanceof Boolean) {
+            return sp.getBoolean(key, (Boolean) defaultObject);
+        } else if (defaultObject instanceof Float) {
+            return sp.getFloat(key, (Float) defaultObject);
+        } else if (defaultObject instanceof Long) {
+            return sp.getLong(key, (Long) defaultObject);
+        }
+
+        return null;
+    }
+
+
+//
+//    /**
+//     * 获取token
+//     *
+//     * @return
+//     */
+//    public static String getToken(Context context) {
+//        return (String) get(context, Constant.APP_UUID, "");
+//    }
+
+    /**
+     * 移除某个key值已经对应的值
+     *
+     * @param context
+     * @param key
+     */
+    public static void remove(Context context, String key) {
+        SharedPreferences sp = context.getSharedPreferences(Constant.PREFERENCE_USER, Context.MODE_PRIVATE);
+        SharedPreferences.Editor editor = sp.edit();
+        editor.remove(key);
+        SharedPreferencesCompat.apply(editor);
+    }
+
+    /**
+     * 清除所有数据
+     *
+     * @param context
+     */
+    public static void clear(Context context) {
+        SharedPreferences sp = context.getSharedPreferences(Constant.PREFERENCE_USER, Context.MODE_PRIVATE);
+        SharedPreferences.Editor editor = sp.edit();
+        editor.clear();
+        SharedPreferencesCompat.apply(editor);
+    }
+
+    /**
+     * 查询某个key是否已经存在
+     *
+     * @param context
+     * @param key
+     * @return
+     */
+    public static boolean contains(Context context, String key) {
+        SharedPreferences sp = context.getSharedPreferences(Constant.PREFERENCE_USER, Context.MODE_PRIVATE);
+        return sp.contains(key);
+    }
+
+    /**
+     * 返回所有的键值对
+     *
+     * @param context
+     * @return
+     */
+    public static Map<String, ?> getAll(Context context) {
+        SharedPreferences sp = context.getSharedPreferences(Constant.PREFERENCE_USER, Context.MODE_PRIVATE);
+        return sp.getAll();
+    }
+//
+//    /**
+//     * 存放mac地址
+//     *
+//     * @return
+//     */
+//    public static String getMac() {
+//        return (String) get(MyApplication.getAppContext(),Constant.MAC_ADDRESS, "");
+//    }
+//
+//    public static void setMac(Context context,String macAddress) {
+//        put(context,Constant.MAC_ADDRESS, macAddress);
+//    }
+
+    /**
+     * 创建一个解决SharedPreferencesCompat.apply方法的一个兼容类
+     *
+     * @author zhy
+     */
+    private static class SharedPreferencesCompat {
+        private static final Method sApplyMethod = findApplyMethod();
+
+        /**
+         * 反射查找apply的方法
+         *
+         * @return
+         */
+        @SuppressWarnings({"unchecked", "rawtypes"})
+        private static Method findApplyMethod() {
+            try {
+                Class clz = SharedPreferences.Editor.class;
+                return clz.getMethod("apply");
+            } catch (NoSuchMethodException e) {
+            }
+
+            return null;
+        }
+
+        /**
+         * 如果找到则使用apply执行,否则使用commit
+         *
+         * @param editor
+         */
+        public static void apply(SharedPreferences.Editor editor) {
+            try {
+                if (sApplyMethod != null) {
+                    sApplyMethod.invoke(editor);
+                    return;
+                }
+            } catch (IllegalArgumentException e) {
+            } catch (IllegalAccessException e) {
+            } catch (InvocationTargetException e) {
+            }
+            editor.commit();
+        }
+    }
+}

+ 159 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/util/ServerConfigDialogHelper.java

@@ -0,0 +1,159 @@
+package com.wdkl.ncs.android.component.home.util;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.AdapterView;
+import android.widget.EditText;
+import android.widget.GridView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.wdkl.ncs.android.component.home.R;
+import com.wdkl.ncs.android.component.home.adapter.NumAdapter;
+import com.wdkl.ncs.android.lib.base.BaseApplication;
+import com.wdkl.ncs.android.lib.utils.ExtendMethodsKt;
+import com.wdkl.ncs.android.middleware.utils.CommonUtils;
+
+
+public class ServerConfigDialogHelper {
+
+    private static AlertDialog callDialog;
+    private static String pwd = "";
+
+    public static void showPasswordDialog(final Activity activity) {
+        View contentView = LayoutInflater.from(activity).inflate(R.layout.server_config_dialog_lay, null);
+        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+        builder.setView(contentView);
+
+        final String[] numbers = {"1","2","3","4","5","6","7","8","9"};
+        final TextView password = contentView.findViewById(R.id.tv_psw_view);
+        final LinearLayout llPwd = contentView.findViewById(R.id.ll_password);
+        final LinearLayout llServer = contentView.findViewById(R.id.ll_server_config);
+        GridView gridView = contentView.findViewById(R.id.grid_psw);
+        NumAdapter adapter = new NumAdapter(numbers, activity);
+        gridView.setAdapter(adapter);
+        gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+            @Override
+            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+                if (pwd.length() <= 2) {
+                    pwd = pwd + numbers[position];
+                    password.setText(pwd);
+                }
+                Log.d("serverIp", "input password len: " + pwd.length() + "--" + pwd);
+            }
+        });
+
+        TextView delete = contentView.findViewById(R.id.btn_delete);
+        TextView cancel = contentView.findViewById(R.id.btn_cancel);
+        TextView confirm = contentView.findViewById(R.id.btn_confirm);
+        delete.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                Log.d("serverIp", "delete password len: " + pwd.length() + "--" + pwd);
+                if (pwd.length() > 1) {
+                    pwd = pwd.substring(0, pwd.length()-1);
+                    password.setText(pwd);
+                } else {
+                    pwd = "";
+                    password.setText(pwd);
+                    password.setHint("请输入密码");
+                }
+            }
+        });
+
+        cancel.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                dismissCallDialog();
+            }
+        });
+
+        confirm.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if ("666".equals(pwd)) {
+                    llPwd.setVisibility(View.GONE);
+                    llServer.setVisibility(View.VISIBLE);
+                } else {
+                    Toast.makeText(activity, "密码错误", Toast.LENGTH_SHORT).show();
+                }
+            }
+        });
+
+        final EditText editUrl = contentView.findViewById(R.id.edit_url);
+        final EditText editPort = contentView.findViewById(R.id.edit_port);
+        final EditText editSipUrl = contentView.findViewById(R.id.edit_sip_url);
+        final EditText editSipPort = contentView.findViewById(R.id.edit_sip_port);
+        TextView saveConfig = contentView.findViewById(R.id.btn_save_config);
+        TextView cancelConfig = contentView.findViewById(R.id.btn_cancel_config);
+        editUrl.setText(CommonUtils.getUrl(BaseApplication.appContext));
+        editPort.setText(CommonUtils.getUrlPort(BaseApplication.appContext));
+        //editSipUrl.setText(CommonUtils.getSipUrl(BaseApplication.appContext));
+        //editSipPort.setText(CommonUtils.getSipPort(BaseApplication.appContext));
+        saveConfig.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                String url = editUrl.getText().toString();
+                String port = editPort.getText().toString();
+                if (TextUtils.isEmpty(url) || TextUtils.isEmpty(port)) {
+                    ExtendMethodsKt.showMessage("参数不能为空");
+                } else {
+                    //保存配置
+                    CommonUtils.setUrl(BaseApplication.appContext, url);
+                    CommonUtils.setUrlPort(BaseApplication.appContext, port);
+                    //CommonUtils.setSipUrl(BaseApplication.appContext, editSipUrl.getText().toString());
+                    //CommonUtils.setSipPort(BaseApplication.appContext, editSipPort.getText().toString());
+                    dismissCallDialog();
+                }
+            }
+        });
+        cancelConfig.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                dismissCallDialog();
+            }
+        });
+
+
+        callDialog = builder.create();
+        //callDialog.setCanceledOnTouchOutside(false);
+        //callDialog.setCancelable(false);
+        callDialog.show();
+
+        //设置dialog宽高及位置
+        try {
+            Window window = callDialog.getWindow();
+            window.setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
+            WindowManager.LayoutParams lp = window.getAttributes();
+            lp.width = 480;
+            lp.height = 720;
+            lp.gravity = Gravity.CENTER;
+            window.setAttributes(lp);
+
+            window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
+                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
+                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+                    | View.SYSTEM_UI_FLAG_FULLSCREEN);
+            window.clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public static void dismissCallDialog() {
+        pwd = "";
+        if (callDialog != null && callDialog.isShowing()) {
+            callDialog.dismiss();
+        }
+    }
+}

+ 84 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/util/SoundPoolManager.java

@@ -0,0 +1,84 @@
+package com.wdkl.ncs.android.component.home.util;
+
+import android.media.AudioAttributes;
+import android.media.AudioManager;
+import android.media.SoundPool;
+import android.os.Build;
+
+import com.wdkl.ncs.android.component.home.R;
+import com.wdkl.ncs.android.lib.base.BaseApplication;
+
+import java.util.HashMap;
+
+public class SoundPoolManager {
+
+    private static SoundPoolManager instance;
+    private SoundPool soundPool;
+    private HashMap<Integer, Integer> soundID = new HashMap<>();
+    private boolean isLoaded = false;
+    private boolean inited = false;
+
+    public static SoundPoolManager getInstance() {
+        if (instance == null) {
+            instance = new SoundPoolManager();
+        }
+        return instance;
+    }
+
+    public void init() {
+        if (inited) {
+            return;
+        }
+
+        if(Build.VERSION.SDK_INT > 21){
+            SoundPool.Builder builder = new SoundPool.Builder();
+            //传入音频数量
+            builder.setMaxStreams(5);
+            //AudioAttributes是一个封装音频各种属性的方法
+            AudioAttributes.Builder attrBuilder = new AudioAttributes.Builder();
+            //设置音频流的合适的属性
+            attrBuilder.setLegacyStreamType(AudioManager.STREAM_MUSIC);//STREAM_MUSIC
+            //加载一个AudioAttributes
+            builder.setAudioAttributes(attrBuilder.build());
+            soundPool = builder.build();
+        }else{
+            soundPool = new SoundPool(5, AudioManager.STREAM_MUSIC, 0);
+        }
+
+        //来电
+        soundID.put(1, soundPool.load(BaseApplication.appContext, R.raw.incoming_call, 1));
+        //去电
+        soundID.put(2, soundPool.load(BaseApplication.appContext, R.raw.outgoing_call, 1));
+        //测试
+        soundID.put(3, soundPool.load(BaseApplication.appContext, R.raw.mic_test, 1));
+        soundID.put(4, soundPool.load(BaseApplication.appContext, R.raw.test_start, 1));
+        soundID.put(5, soundPool.load(BaseApplication.appContext, R.raw.reinforced, 1));
+        soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
+            @Override
+            public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
+                isLoaded = true;
+                inited = true;
+            }
+        });
+    }
+
+    public int playSound(int index, float leftVol, float rightVol, int loop) {
+        try {
+            if (isLoaded) {
+                return soundPool.play(soundID.get(index), leftVol, rightVol, 1, loop, 1);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return -1;
+    }
+
+    public void stopPlaySound(int streamId) {
+        soundPool.stop(streamId);
+    }
+
+    public void release() {
+        soundPool.release();
+    }
+}

+ 202 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/util/SpeechUtil.java

@@ -0,0 +1,202 @@
+package com.wdkl.ncs.android.component.home.util;
+
+import android.content.Context;
+import android.os.Build;
+import android.speech.tts.TextToSpeech;
+import android.speech.tts.UtteranceProgressListener;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.wdkl.ncs.android.middleware.common.Constant;
+
+import java.util.ArrayList;
+import java.util.Locale;
+
+public class SpeechUtil {
+    private static final String TAG = "SpeechUtil";
+
+    private TextToSpeech textToSpeech;
+    private static SpeechUtil speech;
+    private int speakIndex = 0;
+    private int loopCount = 1;
+    private boolean isStop = true;
+    public volatile static ArrayList<String> speechTextList = new ArrayList<>();
+    private Thread speechThread;
+    private boolean isSpeechLoop = true;
+    private String speakSpeech;
+    private final Object lockObject = new Object();
+
+    public static SpeechUtil getInstance() {
+        if (speech == null) {
+            synchronized (SpeechUtil.class) {
+                if (speech == null) {
+                    speech = new SpeechUtil();
+                }
+            }
+        }
+        return speech;
+    }
+
+    public void init(Context context) {
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
+            textToSpeech = new TextToSpeech(context, new TextToSpeech.OnInitListener() {
+                @Override
+                public void onInit(int status) {
+                    if (status == TextToSpeech.SUCCESS) {
+                        int supported = textToSpeech.setLanguage(Locale.CHINESE);
+                        if ((supported != TextToSpeech.LANG_AVAILABLE) && (supported != TextToSpeech.LANG_COUNTRY_AVAILABLE)) {
+                            Constant.ttsState= 1;
+                            Log.d(TAG, "onInit: 当前不支持中文");
+                        } else {
+                            Constant.ttsState = 2;
+                            Log.d(TAG, "onInit: 支持中文");
+                        }
+                        Log.d(TAG, "onInit: TTS引擎初始化成功");
+                    } else {
+                        Constant.ttsState = 0;
+                        Log.d(TAG, "onInit: TTS引擎初始化失败");
+                    }
+                }
+            }, "com.iflytek.speechcloud");
+        } else {
+            textToSpeech = new TextToSpeech(context, new TextToSpeech.OnInitListener() {
+                @Override
+                public void onInit(int status) {
+                    if (status == TextToSpeech.SUCCESS) {
+                        int supported = textToSpeech.setLanguage(Locale.CHINESE);
+                        if ((supported != TextToSpeech.LANG_AVAILABLE) && (supported != TextToSpeech.LANG_COUNTRY_AVAILABLE)) {
+                            Constant.ttsState= 1;
+                            Log.d(TAG, "onInit: 当前不支持中文");
+                        } else {
+                            Constant.ttsState= 2;
+                            Log.d(TAG, "onInit: 支持中文");
+                        }
+                        Log.d(TAG, "onInit: TTS引擎初始化成功");
+                    } else {
+                        Constant.ttsState= 0;
+                        Log.d(TAG, "onInit: TTS引擎初始化失败");
+                    }
+                }
+            });
+        }
+        textToSpeech.setSpeechRate(1f);
+    }
+
+    public void newSpeech(String text, boolean emergency) {
+        synchronized (lockObject) {
+            if (Constant.ttsState == 2) {
+                if (emergency) {
+                    speechTextList.add(0, text);
+                } else {
+                    speechTextList.add(text);
+                }
+                startSpeechThread();
+            }
+        }
+    }
+
+    public synchronized void speak(final String text) {
+        isStop = false;
+        textToSpeech.speak(text, TextToSpeech.QUEUE_FLUSH, null, "uniqueId");
+        textToSpeech.setOnUtteranceProgressListener(new UtteranceProgressListener() {
+            @Override
+            public void onStart(String utteranceId) {
+                //LogUtil.d(TAG, "speak onStart..." + utteranceId);
+            }
+
+            @Override
+            public void onDone(String utteranceId) {
+                speakIndex++;
+                //LogUtil.d(TAG, "speak onDone...index: " + speakIndex + ", loop: " + loopCount);
+                if (speakIndex < loopCount) {
+                    //循环播报
+                    speak(text);
+                } else {
+                    //语音播报完毕
+                    speakIndex = 0;
+                    isStop = true;
+                }
+            }
+
+            @Override
+            public void onError(String utteranceId) {
+                isStop = true;
+                Log.d(TAG, "speak onError..." + utteranceId);
+            }
+        });
+    }
+
+    public void stopSpeak() {
+        if (textToSpeech.isSpeaking()) {
+            textToSpeech.stop();
+            speechTextList.clear();
+            isStop = true;
+            speakIndex = 0;
+            Log.d(TAG, "stop speak");
+        }
+    }
+
+    public void removeSpeak(String text) {
+        synchronized (lockObject) {
+            if (!TextUtils.isEmpty(text) && !TextUtils.isEmpty(speakSpeech)) {
+                if (text.equals(speakSpeech) && textToSpeech.isSpeaking()) {
+                    textToSpeech.stop();
+                    speechTextList.remove(text);
+                    isStop = true;
+                    speakIndex = 0;
+                } else {
+                    speechTextList.remove(text);
+                }
+            }
+        }
+    }
+
+    public void setSpeechLoopCount(int count) {
+        loopCount = count;
+    }
+
+    public void release() {
+        speechTextList.clear();
+        isStop = true;
+        speakIndex = 0;
+        if (textToSpeech != null) {
+            textToSpeech.stop();
+            textToSpeech.shutdown();
+            textToSpeech = null;
+        }
+    }
+
+    public void startSpeechThread() {
+        if (null == speechThread) {
+            speechThread = new Thread(new SpeechRunnable());
+            speechThread.start();
+        } else if (!speechThread.isAlive()) {
+            speechThread.start();
+        }
+    }
+
+    public class SpeechRunnable implements Runnable {
+        public void run() {
+            while (isSpeechLoop) {
+                //synchronized (lockObject) {
+                    if (speechTextList.size() > 0 && isStop) {
+                        speakSpeech = speechTextList.get(0);
+                        Log.d(TAG, "speakSpeech: " + speakSpeech);
+                        speak(speakSpeech);
+
+                        //if (speechTextList.contains(speakSpeech)) {
+                            speechTextList.remove(speakSpeech);
+                        //}
+                    }
+                //}
+
+                try {
+                    Thread.sleep(50);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+}

+ 30 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/util/TimeTransition.kt

@@ -0,0 +1,30 @@
+package com.wdkl.ncs.android.component.nursehome.util
+
+import com.umeng.weixin.handler.s
+import java.text.SimpleDateFormat
+import java.util.*
+
+
+class TimeTransition {
+
+    fun stampToDate(s:Long):String{
+        return TimeStampToTime(s,"MM-dd HH:mm")
+    }
+
+    fun stampToTime(s:Long):String{
+        return TimeStampToTime(s,"HH:mm:ss")
+    }
+    /**
+     * 时间戳转时间
+     */
+    fun TimeStampToTime(s:Long, timestamp:String):String{
+        val res: String
+        val simpleDateFormat = SimpleDateFormat(timestamp)
+        val lt = s
+        val date = Date(lt)
+        res = simpleDateFormat.format(date)
+        return res
+}
+
+
+}

+ 159 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/util/Util.kt

@@ -0,0 +1,159 @@
+package com.wdkl.ncs.android.component.home.util
+
+import android.annotation.SuppressLint
+import android.app.KeyguardManager
+import android.content.Context
+import android.content.Context.KEYGUARD_SERVICE
+import android.os.Build
+import android.os.Environment
+import android.os.PowerManager
+import android.telephony.TelephonyManager
+import android.util.Log
+import com.enation.javashop.utils.base.tool.SystemTool
+import com.google.common.base.Strings
+import java.io.File
+import java.io.FileInputStream
+import java.io.FileOutputStream
+import java.io.IOException
+import java.lang.Exception
+import java.util.*
+
+object Util {
+
+    var IMEI = ""
+    var UUID_FILE_NAME = "wdkl_uuid.txt"
+
+    /*
+      激活获取IMEI用
+    */
+    @SuppressLint("MissingPermission", "PrivateApi")
+    fun getIMEI(context: Context): String {
+        if (Build.VERSION.SDK_INT >= 29) {
+            val UUIDStr = readSD()
+            if (UUIDStr == null || UUIDStr.isEmpty()) { //如果为空或者空字符串就生成UUID创建文件并写入UUID
+                val uuid: String = Date().getTime().toString()
+                writeSD(uuid)
+                IMEI = uuid
+            } else {
+                IMEI = UUIDStr
+            }
+            return IMEI
+        }
+
+        IMEI = SystemTool.getPhoneImei(context)
+        if (Strings.isNullOrEmpty(IMEI)) {
+            val tm = (context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager)
+            try {
+                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+                    IMEI = tm.imei
+                } else {
+                    IMEI = tm.deviceId
+                }
+            }catch (e:Exception){
+            }
+
+            if (Strings.isNullOrEmpty(IMEI)) {
+                IMEI = SystemTool.getLocalMacAddress()
+//                IMEI = "35" + //we make this look like a valid IMEI
+//                        Build.BOARD.length % 10 + Build.BRAND.length % 10 + Build.CPU_ABI.length % 10 + Build.DEVICE.length % 10 + Build.DISPLAY.length % 10 + Build.HOST.length % 10 + Build.ID.length % 10 + Build.MANUFACTURER.length % 10 + Build.MODEL.length % 10 + Build.PRODUCT.length % 10 + Build.TAGS.length % 10 + Build.TYPE.length % 10 + Build.USER.length % 10 //13 digits
+            }
+        }
+        return IMEI
+    }
+
+    /**
+     * 亮屏并解锁
+     */
+    @SuppressLint("InvalidWakeLockTag")
+    fun wakeUpAndUnlock(context: Context): PowerManager.WakeLock? {
+        val pm = context.getSystemService(Context.POWER_SERVICE) as PowerManager
+        var wakeLock: PowerManager.WakeLock? = null
+
+        val screenOn = pm.isInteractive
+        if (!screenOn) { //如果是熄灭状态
+            wakeLock = pm.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP or PowerManager.SCREEN_DIM_WAKE_LOCK, "TAG")
+            wakeLock.acquire(3000)//亮屏
+        }
+
+        // 屏幕解锁
+        val keyguardManager = context.getSystemService(KEYGUARD_SERVICE) as KeyguardManager
+        val keyguardLock = keyguardManager.newKeyguardLock("unLock")
+        // 屏幕锁定
+        keyguardLock.reenableKeyguard()
+        keyguardLock.disableKeyguard() // 解锁
+        return wakeLock
+    }
+
+    @SuppressLint("InvalidWakeLockTag")
+    fun getCpuWakeLock(context: Context): PowerManager.WakeLock {
+        val pm = context.getSystemService(Context.POWER_SERVICE) as PowerManager
+        val cpuWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK or PowerManager.ON_AFTER_RELEASE,
+                context.javaClass.canonicalName)
+        return cpuWakeLock
+    }
+
+    fun appendSpace(para: String): String? {
+        val length = para.length
+        val value = CharArray(length shl 1)
+        var i = 0
+        var j = 0
+        while (i < length) {
+            value[j] = para[i]
+            value[1 + j] = ' '
+            ++i
+            j = i shl 1
+        }
+        return String(value)
+    }
+
+    fun writeSD(content: String): String? {
+        //文件输出流
+        var out: FileOutputStream? = null
+        //设置文件路径
+        val file = File(Environment.getExternalStorageDirectory(), UUID_FILE_NAME)
+        return try {
+            out = FileOutputStream(file)
+            out.write(content.toByteArray())
+            content
+        } catch (e: Exception) {
+            e.printStackTrace()
+            ""
+        } finally {
+            try {
+                if (out != null) {
+                    out.close()
+                }
+            } catch (e: IOException) {
+                e.printStackTrace()
+            }
+        }
+    }
+
+    fun readSD(): String? {
+        //文件输入流
+        var `in`: FileInputStream? = null
+        //设置文件路径
+        val file = File(Environment.getExternalStorageDirectory(), UUID_FILE_NAME)
+        return try {
+            `in` = FileInputStream(file)
+            //使用缓冲来读
+            val buf = ByteArray(1024) //每1024字节读一次
+            val builder = StringBuilder()
+            while (`in`.read(buf) !== -1) {
+                builder.append(String(buf).trim { it <= ' ' })
+            }
+            builder.toString()
+        } catch (e: java.lang.Exception) {
+            e.printStackTrace()
+            ""
+        } finally {
+            try {
+                if (`in` != null) {
+                    `in`.close()
+                }
+            } catch (e: IOException) {
+                e.printStackTrace()
+            }
+        }
+    }
+}

+ 184 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/util/VoiceManagerUtil.java

@@ -0,0 +1,184 @@
+package com.wdkl.ncs.android.component.home.util;
+
+import android.content.Context;
+import android.media.AudioManager;
+
+/**
+ * 类名称:VoiceManagerUtil <br>
+ * 类描述:声音控制工具类 <br>
+ * 创建人:Waderson Shll (TEL:15675117662)<br>
+ * 创建时间:2018-03-15 <br>
+ * 特别提醒:如有需要该类可任意创建与调用;在未通知本人的情况下该类禁止任何修改!<br>
+ */
+public class VoiceManagerUtil {
+    /**
+     * 获取提示音音量最大值
+     *
+     * @param context
+     */
+    public static int getAlarmMax(Context context) {
+        AudioManager mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        return mAudioManager.getStreamMaxVolume(AudioManager.STREAM_ALARM);
+    }
+
+    /**
+     * 获取提示音音量当前值
+     *
+     * @param context
+     */
+    public static int getAlarmNow(Context context) {
+        AudioManager mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        return mAudioManager.getStreamVolume(AudioManager.STREAM_ALARM);
+    }
+
+    /**
+     * 获取多媒体音量最大值
+     *
+     * @param context
+     */
+    public static int getMusicMax(Context context) {
+        AudioManager mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        return mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
+    }
+
+    /**
+     * 获取多媒体音量当前值
+     *
+     * @param context
+     */
+    public static int getMusicNow(Context context) {
+        AudioManager mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        return mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
+    }
+
+    /**
+     * 获取铃声音量最大值
+     *
+     * @param context
+     */
+    public static int getRingMax(Context context) {
+        AudioManager mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        return mAudioManager.getStreamMaxVolume(AudioManager.STREAM_RING);
+    }
+
+    /**
+     * 获取铃声音量当前值
+     *
+     * @param context
+     */
+    public static int getRingNow(Context context) {
+        AudioManager mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        return mAudioManager.getStreamVolume(AudioManager.STREAM_RING);
+    }
+
+    /**
+     * 获取系统音量最大值
+     *
+     * @param context
+     */
+    public static int getSystemMax(Context context) {
+        AudioManager mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        return mAudioManager.getStreamMaxVolume(AudioManager.STREAM_SYSTEM);
+    }
+
+    /**
+     * 获取系统音量当前值
+     *
+     * @param context
+     */
+    public static int getSystemNow(Context context) {
+        AudioManager mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        return mAudioManager.getStreamVolume(AudioManager.STREAM_SYSTEM);
+    }
+
+    /**
+     * 获取通话音量最大值
+     *
+     * @param context
+     */
+    public static int getCallMax(Context context) {
+        AudioManager mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        return mAudioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL);
+    }
+
+    /**
+     * 获取通话音量当前值
+     *
+     * @param context
+     */
+    public static int getCallNow(Context context) {
+        AudioManager mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        return mAudioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL);
+    }
+
+    /**
+     * 设置提示音音量
+     *
+     * @param context
+     * @param percent (百分比;只能0--100之间)
+     */
+    public static void setAlarmVoice(Context context, int percent) {
+        float vPercent=((float)percent)/100f;
+        vPercent = vPercent < 0 ? 0 : vPercent;
+        vPercent = vPercent > 1 ? 1 : vPercent;
+        AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        audioManager.setStreamVolume(AudioManager.STREAM_ALARM, (int) (getAlarmMax(context) * vPercent), 0);
+    }
+
+    /**
+     * 设置多媒体音量
+     *
+     * @param context
+     * @param percent (百分比;只能0--100之间)
+     */
+    public static void setMusicVoice(Context context, int percent) {
+        float vPercent=((float)percent)/100f;
+        vPercent = vPercent < 0 ? 0 : vPercent;
+        vPercent = vPercent > 1 ? 1 : vPercent;
+        AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, (int) (getMusicMax(context) * vPercent), 0);
+    }
+
+    /**
+     * 设置铃声音量
+     *
+     * @param context
+     * @param percent (百分比;只能0--100之间)
+     */
+    public static void setRingVoice(Context context, int percent) {
+        float vPercent=((float)percent)/100f;
+        vPercent = vPercent < 0 ? 0 : vPercent;
+        vPercent = vPercent > 1 ? 1 : vPercent;
+        AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        audioManager.setStreamVolume(AudioManager.STREAM_RING, (int) (getRingMax(context) * vPercent), 0);
+    }
+
+    /**
+     * 设置系统音量
+     *
+     * @param context
+     * @param percent (百分比;只能0--100之间)
+     */
+    public static void setSystemVoice(Context context, int percent) {
+        float vPercent=((float)percent)/100f;
+        vPercent = vPercent < 0 ? 0 : vPercent;
+        vPercent = vPercent > 1 ? 1 : vPercent;
+        AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        audioManager.setStreamVolume(AudioManager.STREAM_SYSTEM, (int) (getSystemMax(context) * vPercent), 0);
+    }
+
+    /**
+     * 设置通话音量
+     *
+     * @param context
+     * @param percent (百分比;只能0--100之间)
+     */
+    public static void setCallVoice(Context context, int percent) {
+        float vPercent=((float)percent)/100f;
+        vPercent = vPercent < 0 ? 0 : vPercent;
+        vPercent = vPercent > 1 ? 1 : vPercent;
+        AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        audioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL, (int) (getCallMax(context) * vPercent), 0);
+    }
+
+}

+ 238 - 0
android_visiting/src/main/java/com/wdkl/ncs/android/component/home/util/XCrashUtils.java

@@ -0,0 +1,238 @@
+package com.wdkl.ncs.android.component.home.util;
+
+import android.app.AlarmManager;
+import android.app.Application;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+import com.wdkl.ncs.android.component.home.BuildConfig;
+import com.wdkl.ncs.android.component.home.helper.HttpHelper;
+import com.wdkl.ncs.android.component.welcome.activity.WelcomeActivity;
+import com.wdkl.ncs.android.middleware.api.UrlManager;
+
+import org.json.JSONObject;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+
+import okhttp3.Call;
+import okhttp3.Callback;
+import okhttp3.FormBody;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+import xcrash.ICrashCallback;
+import xcrash.TombstoneManager;
+import xcrash.TombstoneParser;
+import xcrash.XCrash;
+
+public class XCrashUtils {
+    private final static String TAG = "XCrashUtils";
+
+    private Application app;
+    private OkHttpClient okHttpClient;
+
+    // callback for java crash, native crash and ANR
+    private final ICrashCallback callback = new ICrashCallback() {
+        @Override
+        public void onCrash(String logPath, String emergency) {
+            Log.d(TAG, "log path: " + (logPath != null ? logPath : "(null)") + ", emergency: " + (emergency != null ? emergency : "(null)"));
+
+            if (emergency != null) {
+                debug(logPath, emergency);
+
+                // Disk is exhausted, send crash report immediately.
+                //sendThenDeleteCrashLog(logPath, emergency);
+            } else {
+                // Add some expanded sections. Send crash report at the next time APP startup.
+
+                // OK
+                TombstoneManager.appendSection(logPath, "expanded_key_1", "expanded_content");
+                TombstoneManager.appendSection(logPath, "expanded_key_2", "expanded_content_row_1\nexpanded_content_row_2");
+
+                // Invalid. (Do NOT include multiple consecutive newline characters ("\n\n") in the content string.)
+                // TombstoneManager.appendSection(logPath, "expanded_key_3", "expanded_content_row_1\n\nexpanded_content_row_2");
+
+                debug(logPath, null);
+            }
+
+            // Disk is exhausted, send crash report immediately.
+            //sendThenDeleteCrashLog(logPath, emergency);
+
+            //非debug版本上传crash日志
+            if (!BuildConfig.DEBUG) {
+                uploadCrashLog(logPath);
+            } else {
+                restartApp();
+            }
+        }
+    };
+
+    //ANR Catcher
+    private final ICrashCallback anrCallback = new ICrashCallback() {
+        @Override
+        public void onCrash(String logPath, String emergency) {
+            Log.d(TAG, "log path: " + (logPath != null ? logPath : "(null)") + ", emergency: " + (emergency != null ? emergency : "(null)"));
+
+            /*if (emergency != null) {
+                debug(logPath, emergency);
+
+                // Disk is exhausted, send crash report immediately.
+                //sendThenDeleteCrashLog(logPath, emergency);
+            } else {
+                // Add some expanded sections. Send crash report at the next time APP startup.
+
+                // OK
+                TombstoneManager.appendSection(logPath, "expanded_key_1", "expanded_content");
+                TombstoneManager.appendSection(logPath, "expanded_key_2", "expanded_content_row_1\nexpanded_content_row_2");
+
+                // Invalid. (Do NOT include multiple consecutive newline characters ("\n\n") in the content string.)
+                // TombstoneManager.appendSection(logPath, "expanded_key_3", "expanded_content_row_1\n\nexpanded_content_row_2");
+
+                debug(logPath, null);
+            }*/
+
+            restartApp();
+        }
+    };
+
+    public void init(Application application) {
+        Log.d(TAG, "xCrash SDK init: start ---- is debug version? " + BuildConfig.DEBUG);
+        app = application;
+
+        // Initialize xCrash.
+        XCrash.init(application, new XCrash.InitParameters()
+                .setAppVersion(BuildConfig.VERSION_NAME)
+                .setJavaRethrow(true)
+                .setJavaLogCountMax(10)
+                .setJavaDumpAllThreadsWhiteList(new String[]{"^main$", "^Binder:.*", ".*Finalizer.*"})
+                .setJavaDumpAllThreadsCountMax(10)
+                .setJavaCallback(callback)
+                .setNativeRethrow(true)
+                .setNativeLogCountMax(10)
+                .setNativeDumpAllThreadsWhiteList(new String[]{"^xcrash\\.sample$", "^Signal Catcher$", "^Jit thread pool$", ".*(R|r)ender.*", ".*Chrome.*"})
+                .setNativeDumpAllThreadsCountMax(10)
+                .setNativeCallback(callback)
+                .setAnrRethrow(true)
+                .setAnrLogCountMax(10)
+                .setAnrCallback(anrCallback)
+                .setPlaceholderCountMax(3)
+                .setPlaceholderSizeKb(512)
+                .setLogDir(application.getExternalFilesDir("xcrash").toString())
+                .setLogFileMaintainDelayMs(5000));
+    }
+
+    private void uploadCrashLog(String path) {
+        final File logFile = new File(path);
+        if (logFile.exists()) {
+            final UrlManager urlManager = UrlManager.Companion.build();
+            String url = urlManager.getBuyer() + "ncs/upload/file";
+            HttpHelper.upload(url, logFile, new HttpHelper.UploadCallback() {
+                @Override
+                public void onFail() {
+                    Log.e(TAG,"错误日志文件上传失败!");
+                    restartApp();
+                }
+
+                @Override
+                public void onSuccess(String data) {
+                    Log.e(TAG,"错误日志文件上传成功!" + data);
+                    sendThenDeleteCrashLog(urlManager.getBuyer() + data, null);
+                    //删除日志文件
+                    //logFile.delete();
+                }
+            });
+        }
+    }
+
+    private void sendThenDeleteCrashLog(final String logPath, String emergency) {
+        try {
+            // Parse
+            //Map<String, String> map = TombstoneParser.parse(logPath, emergency);
+            //String crashReport = new JSONObject(map).toString();
+
+            if(okHttpClient == null){
+                okHttpClient = new OkHttpClient();
+            }
+
+            FormBody.Builder formBody = new FormBody.Builder();
+            formBody.add("class_name", app.getPackageName());
+            formBody.add("method_name", "");
+            formBody.add("exception_name", "");
+            formBody.add("err_msg", "");
+            formBody.add("stack_trace", logPath);
+
+            UrlManager urlManager = UrlManager.Companion.build();
+            Request request  = new Request.Builder()
+                    .url(urlManager.getBuyer() + "device/error_log")
+                    .post(formBody.build())
+                    .build();
+
+            okHttpClient.newCall(request).enqueue(new Callback() {
+                @Override
+                public void onFailure(Call call, IOException e) {
+                    Log.e(TAG,"错误日志名称上传失败"+e.getMessage());
+                    restartApp();
+                }
+
+                @Override
+                public void onResponse(Call call, Response response) throws IOException {
+                    Log.d(TAG,"错误日志名称上传成功");
+                    TombstoneManager.deleteTombstone(logPath);
+                    //String data = response.body().string();
+                    //Log.d(TAG,"错误日志数据 data "+data);
+                    restartApp();
+                }
+            });
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        // Send the crash report to server-side.
+        // ......
+
+        // If the server-side receives successfully, delete the log file.
+        //
+        // Note: When you use the placeholder file feature,
+        //       please always use this method to delete tombstone files.
+        //
+        //TombstoneManager.deleteTombstone(logPath);
+    }
+
+    private void debug(String logPath, String emergency) {
+        // Parse and save the crash info to a JSON file for debugging.
+        FileWriter writer = null;
+        try {
+            File debug = new File(XCrash.getLogDir() + "/debug.json");
+            debug.createNewFile();
+            writer = new FileWriter(debug, false);
+            writer.write(new JSONObject(TombstoneParser.parse(logPath, emergency)).toString());
+        } catch (Exception e) {
+            Log.d(TAG, "debug failed", e);
+        } finally {
+            if (writer != null) {
+                try {
+                    writer.close();
+                } catch (Exception ignored) {
+                }
+            }
+        }
+    }
+
+    private void restartApp() {
+        //重新启动app
+        Intent mStartActivity = new Intent(app.getApplicationContext(), WelcomeActivity.class);
+        mStartActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+        int mPendingIntentId = 123456;
+        PendingIntent mPendingIntent = PendingIntent.getActivity(app.getApplicationContext(), mPendingIntentId, mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT);
+        AlarmManager mgr = (AlarmManager) app.getApplicationContext().getSystemService(Context.ALARM_SERVICE);
+        mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 2000, mPendingIntent);
+
+        android.os.Process.killProcess(android.os.Process.myPid());
+        System.exit(0);
+    }
+
+}

BIN
android_visiting/src/main/res/drawable-hdpi/hu_jiao.png


BIN
android_visiting/src/main/res/drawable-hdpi/hu_jiao_bg.png


BIN
android_visiting/src/main/res/drawable-hdpi/wei_chu_li_bg.png


BIN
android_visiting/src/main/res/drawable-hdpi/yi_chu_li_bg.png


BIN
android_visiting/src/main/res/drawable-hdpi/yu_yin_wei_chu_li.png


BIN
android_visiting/src/main/res/drawable-mdpi/bao_ma_tou_xiang.png


BIN
android_visiting/src/main/res/drawable-mdpi/dian_liang.png


BIN
android_visiting/src/main/res/drawable-mdpi/geng_duo.png


BIN
android_visiting/src/main/res/drawable-mdpi/gu_ke_lie_biao.png


BIN
android_visiting/src/main/res/drawable-mdpi/hu_chu_wei_jie.png


BIN
android_visiting/src/main/res/drawable-mdpi/hu_chu_yi_jie.png


BIN
android_visiting/src/main/res/drawable-mdpi/hu_jiao.png


BIN
android_visiting/src/main/res/drawable-mdpi/hu_jiao_bg.png


BIN
android_visiting/src/main/res/drawable-mdpi/hu_ru_wei_jie.png


BIN
android_visiting/src/main/res/drawable-mdpi/hu_ru_yi_jie.png


BIN
android_visiting/src/main/res/drawable-mdpi/hu_shi_to_xiang.png


BIN
android_visiting/src/main/res/drawable-mdpi/ju_jie.png


BIN
android_visiting/src/main/res/drawable-mdpi/sip_lian_jie.png


BIN
android_visiting/src/main/res/drawable-mdpi/tong_hu_ji_lu.png


BIN
android_visiting/src/main/res/drawable-mdpi/wei_bo_fang.png


BIN
android_visiting/src/main/res/drawable-mdpi/wei_chu_li.png


BIN
android_visiting/src/main/res/drawable-mdpi/wei_chu_li_bg.png


BIN
android_visiting/src/main/res/drawable-mdpi/wifi_lian_jie.png


BIN
android_visiting/src/main/res/drawable-mdpi/yi_bo_fang.png


BIN
android_visiting/src/main/res/drawable-mdpi/yi_chu_li.png


BIN
android_visiting/src/main/res/drawable-mdpi/yi_chu_li_bg.png


BIN
android_visiting/src/main/res/drawable-mdpi/yu_yin_gua_duan.png


BIN
android_visiting/src/main/res/drawable-mdpi/yu_yin_jie_ting.png


BIN
android_visiting/src/main/res/drawable-mdpi/yu_yin_wei_chu_li.png


BIN
android_visiting/src/main/res/drawable-mdpi/zhe_die.png


BIN
android_visiting/src/main/res/drawable/av_handfree_hover.png


BIN
android_visiting/src/main/res/drawable/btn_back.png


BIN
android_visiting/src/main/res/drawable/ic_answer_normal.png


BIN
android_visiting/src/main/res/drawable/ic_answer_press.png


BIN
android_visiting/src/main/res/drawable/ic_hangup_normal.png


BIN
android_visiting/src/main/res/drawable/ic_hangup_press.png


BIN
android_visiting/src/main/res/drawable/ic_nurse.png


BIN
android_visiting/src/main/res/drawable/icon_hd_live.png


BIN
android_visiting/src/main/res/drawable/icon_hd_live_item.png


BIN
android_visiting/src/main/res/drawable/icon_switch_off.png


BIN
android_visiting/src/main/res/drawable/icon_switch_on.png


+ 5 - 0
android_visiting/src/main/res/drawable/item_selector.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@color/color_gray2" android:state_pressed="true"/>
+    <item android:drawable="@color/color_white"/>
+</selector>

BIN
android_visiting/src/main/res/drawable/main_bg.png


BIN
android_visiting/src/main/res/drawable/main_bg_1280x800.jpg


BIN
android_visiting/src/main/res/drawable/main_bg_1920x1080.jpg


BIN
android_visiting/src/main/res/drawable/main_bg_800x1280.png


+ 6 - 0
android_visiting/src/main/res/drawable/round_button_100dp.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="oval">
+    <solid android:color="#0081ff"/>
+    <size android:width="100dp" android:height="100dp"/>
+</shape>

+ 0 - 0
android_visiting/src/main/res/drawable/round_button_80dp.xml


Some files were not shown because too many files changed in this diff