Kaynağa Gözat

代码集成统一化,5寸分机,7寸分机等设备代码放到统一仓库管理,通过开关配置来编译不同版本

weizhengliang 2 yıl önce
işleme
1e5394c7fe
100 değiştirilmiş dosya ile 10557 ekleme ve 0 silme
  1. 11 0
      .gitignore
  2. 1 0
      android_bed/.gitignore
  3. 124 0
      android_bed/build.gradle
  4. 21 0
      android_bed/proguard-rules.pro
  5. BIN
      android_bed/src/main/assets/launch.apk
  6. 37 0
      android_bed/src/main/h7_3128/AndroidManifest.xml
  7. 160 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/activity/AppUpdateActivity.kt
  8. 1436 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/activity/Callingbed2Activity.kt
  9. 77 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/adapter/ActionAdapter.kt
  10. 118 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/adapter/AdviceAdapter.kt
  11. 248 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/adapter/CallRecordsItemAdapter.kt
  12. 96 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/adapter/CostItemAdapter.kt
  13. 83 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/adapter/CostItemAdapter2.kt
  14. 67 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/adapter/EventHistoryAdapter.kt
  15. 56 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/adapter/NumAdapter.java
  16. 63 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/adapter/NurseConfigAdpter.kt
  17. 12 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/agreement/Callingbed2Agreement.kt
  18. 30 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/di/Callingbed2Component.kt
  19. 107 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/fragment/AdviceFragment.kt
  20. 141 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/fragment/BaseCallFragment.kt
  21. 362 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/fragment/CallFragment.kt
  22. 101 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/fragment/CostFragment.kt
  23. 112 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/fragment/CostFragment2.kt
  24. 195 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/fragment/MainFragment.kt
  25. 301 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/fragment/QrCodeFragment.kt
  26. 630 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/fragment/SkyCallFragment.kt
  27. 216 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/fragment/TestFragment.kt
  28. 135 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/fragment/VoiceMsgFragment.kt
  29. 252 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/AnrFcExceptionUtil.java.bak
  30. 234 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/AppUpdateHelper.java
  31. 93 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/AppUtil.java
  32. 189 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/AsyncPlayer.java
  33. 87 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/CallDialogHelper.java
  34. 19 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/DoorLightHelper.java
  35. 190 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/HttpHelper.java
  36. 140 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/LanguageSetDialogHelper.java
  37. 80 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/LocaleMangerUtils.java
  38. 219 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/MediaPlayHelper.java
  39. 532 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/NetHelper.java
  40. 128 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/PasswordDialogHelper.java
  41. 126 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/RecordHelper.java
  42. 22 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/RingPlayHelper.java
  43. 47 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/SOSHelper.java
  44. 81 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/ScreenManagerUtil.kt
  45. 65 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/SerialPortHelper.java
  46. 160 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/ServerConfigDialogHelper.java
  47. 83 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/SoundPoolManager.java
  48. 51 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/Utils.java
  49. 185 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/VoiceManagerUtil.java
  50. 56 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/WarningDialogHelper.java
  51. 242 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/XCrashUtils.java
  52. 20 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/launch/Callingbed2Launch.kt
  53. 406 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/settings/SettingConfig.java
  54. 579 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/sip/SipHelper.java.bak
  55. 17 0
      android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/sip/SipStatus.java.bak
  56. 7 0
      android_bed/src/main/h7_3128/res/anim/slide_down_in.xml
  57. 7 0
      android_bed/src/main/h7_3128/res/anim/slide_left_in.xml
  58. 7 0
      android_bed/src/main/h7_3128/res/anim/slide_right_out.xml
  59. 7 0
      android_bed/src/main/h7_3128/res/anim/slide_up_out.xml
  60. 34 0
      android_bed/src/main/h7_3128/res/drawable-v24/ic_launcher_foreground.xml
  61. BIN
      android_bed/src/main/h7_3128/res/drawable/ic_answer.png
  62. BIN
      android_bed/src/main/h7_3128/res/drawable/ic_answer_normal.png
  63. BIN
      android_bed/src/main/h7_3128/res/drawable/ic_answer_press.png
  64. 5 0
      android_bed/src/main/h7_3128/res/drawable/ic_baseline_backspace.xml
  65. 5 0
      android_bed/src/main/h7_3128/res/drawable/ic_baseline_cancel.xml
  66. 5 0
      android_bed/src/main/h7_3128/res/drawable/ic_baseline_pause.xml
  67. 5 0
      android_bed/src/main/h7_3128/res/drawable/ic_baseline_play.xml
  68. BIN
      android_bed/src/main/h7_3128/res/drawable/ic_hangup.png
  69. BIN
      android_bed/src/main/h7_3128/res/drawable/ic_hangup_normal.png
  70. BIN
      android_bed/src/main/h7_3128/res/drawable/ic_hangup_press.png
  71. 170 0
      android_bed/src/main/h7_3128/res/drawable/ic_launcher_background.xml
  72. BIN
      android_bed/src/main/h7_3128/res/drawable/ic_nurse.png
  73. BIN
      android_bed/src/main/h7_3128/res/drawable/ic_nurse_call.png
  74. 22 0
      android_bed/src/main/h7_3128/res/drawable/po_seekbar.xml
  75. BIN
      android_bed/src/main/h7_3128/res/drawable/seek_bar.png
  76. 9 0
      android_bed/src/main/h7_3128/res/drawable/seekbar_thumb.xml
  77. 5 0
      android_bed/src/main/h7_3128/res/drawable/selector_action_button_bg.xml
  78. 5 0
      android_bed/src/main/h7_3128/res/drawable/selector_action_button_text_color.xml
  79. 5 0
      android_bed/src/main/h7_3128/res/drawable/selector_bottom_btn_text_color.xml
  80. 5 0
      android_bed/src/main/h7_3128/res/drawable/selector_call_answer.xml
  81. 5 0
      android_bed/src/main/h7_3128/res/drawable/selector_call_end.xml
  82. 5 0
      android_bed/src/main/h7_3128/res/drawable/selector_call_hangup.xml
  83. 5 0
      android_bed/src/main/h7_3128/res/drawable/selector_main.xml
  84. 5 0
      android_bed/src/main/h7_3128/res/drawable/selector_record_btn.xml
  85. 7 0
      android_bed/src/main/h7_3128/res/drawable/shape_frame_bg.xml
  86. 137 0
      android_bed/src/main/h7_3128/res/layout/adapter_call_records_item.xml
  87. 27 0
      android_bed/src/main/h7_3128/res/layout/advice_view_lay.xml
  88. 67 0
      android_bed/src/main/h7_3128/res/layout/call_dialog_lay.xml
  89. 286 0
      android_bed/src/main/h7_3128/res/layout/callingbed2_main_lay.xml
  90. 27 0
      android_bed/src/main/h7_3128/res/layout/cost_view_lay.xml
  91. 17 0
      android_bed/src/main/h7_3128/res/layout/digital_item.xml
  92. 33 0
      android_bed/src/main/h7_3128/res/layout/item_action_view.xml
  93. 64 0
      android_bed/src/main/h7_3128/res/layout/item_advice.xml
  94. 39 0
      android_bed/src/main/h7_3128/res/layout/item_cost_detail.xml
  95. 52 0
      android_bed/src/main/h7_3128/res/layout/item_cost_detail2.xml
  96. 38 0
      android_bed/src/main/h7_3128/res/layout/item_cost_main_view.xml
  97. 70 0
      android_bed/src/main/h7_3128/res/layout/item_event_history.xml
  98. 44 0
      android_bed/src/main/h7_3128/res/layout/item_nurse_config.xml
  99. 83 0
      android_bed/src/main/h7_3128/res/layout/language_set_dialog.xml
  100. 0 0
      android_bed/src/main/h7_3128/res/layout/main_view2_layout.xml

+ 11 - 0
.gitignore

@@ -0,0 +1,11 @@
+*.iml
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
+/gradle
+.externalNativeBuild
+/.gradle
+/.idea

+ 1 - 0
android_bed/.gitignore

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

+ 124 - 0
android_bed/build.gradle

@@ -0,0 +1,124 @@
+if (componentTag){
+    apply plugin: 'com.android.application'
+    apply plugin: 'com.enation.javashop.aspectjrt'
+}else{
+    apply plugin: 'com.android.library'
+}
+
+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
+        dataBinding {
+            enabled = true
+        }
+    }
+
+    sourceSets {
+        println 'config app_device_type ===== ' + app_device_type
+        if ("fj_h7_z_3128_1" == app_device_type) {
+            main.java.srcDirs += 'src/main/h7_3128/java'
+            main.res.srcDirs += 'src/main/h7_3128/res'
+            main.manifest.srcFile 'src/main/h7_3128/AndroidManifest.xml'
+        }
+    }
+
+    lintOptions {
+        abortOnError false
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+        }
+    }
+
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+    }
+
+}
+
+dependencies {
+    compile fileTree(dir: 'libs', include: ['*.jar'])
+    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(':welcome')
+    compile project(':middleware')
+
+    //janus信令
+    compile project(':janus')
+
+    /**
+     * 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布局依赖
+     */
+    compile 'com.android.support.constraint:constraint-layout:1.1.0-beta5'
+
+    //compile 'com.github.anrwatchdog:anrwatchdog:1.3.0'
+
+    //使用xCrash捕获异常
+    implementation 'com.iqiyi.xcrash:xcrash-android-lib:3.0.0'
+}
+
+/**
+ * kawo组件化框架配置
+ */
+if(componentTag){
+    kawo {
+        /**
+         * Aop注解排除Jar
+         */
+        aspectExcludeJarFilter 'com.enation.geamtear.pay','AlipaySdk'
+    }
+}

+ 21 - 0
android_bed/proguard-rules.pro

@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile

BIN
android_bed/src/main/assets/launch.apk


+ 37 - 0
android_bed/src/main/h7_3128/AndroidManifest.xml

@@ -0,0 +1,37 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.wdkl.app.ncs.callingbed2">
+
+    <uses-permission android:name="android.permission.INTERNET"/>
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
+    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
+    <uses-permission android:name="android.permission.BLUETOOTH"/>
+    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
+    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+    <uses-permission android:name="android.permission.STATUS_BAR" />
+
+    <application
+        android:hardwareAccelerated="false"
+        android:allowBackup="true"
+        android:label="@string/app_name"
+        android:supportsRtl="true" >
+
+        <meta-data
+            android:name="com.enation.javashop.imagepluin.cache.MyGlideModule"
+            android:value="GlideModule" />
+        <meta-data
+            android:name="design_width_in_dp"
+            android:value="1024"/>
+        <meta-data
+            android:name="design_height_in_dp"
+            android:value="600"/>
+
+        <activity android:name=".activity.Callingbed2Activity"
+            android:launchMode="singleInstance"
+            android:screenOrientation="landscape"/>
+
+        <activity android:name=".activity.AppUpdateActivity"
+            android:screenOrientation="landscape"
+            android:launchMode="singleInstance"/>
+    </application>
+</manifest>

+ 160 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/activity/AppUpdateActivity.kt

@@ -0,0 +1,160 @@
+package com.wdkl.app.ncs.callingbed2.activity
+
+import android.content.Intent
+import android.os.Build
+import android.text.TextUtils
+import android.util.Log
+import com.enation.javashop.android.jrouter.external.annotation.Router
+import com.enation.javashop.net.engine.model.NetState
+import com.wdkl.app.ncs.callingbed2.R
+import com.wdkl.app.ncs.callingbed2.databinding.UpdateLayBinding
+import com.wdkl.app.ncs.callingbed2.helper.AppUpdateHelper
+import com.wdkl.app.ncs.callingbed2.helper.HttpHelper
+import com.wdkl.app.ncs.callingbed2.launch.Callingbed2Launch
+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.api.UrlManager
+import com.wdkl.ncs.android.middleware.common.Constant
+import com.wdkl.ncs.android.middleware.logic.contract.callingbed2.AppUpdateContract
+import com.wdkl.ncs.android.middleware.logic.presenter.callingbed2.AppUpdatePresenter
+import kotlinx.android.synthetic.main.update_lay.*
+import java.io.File
+
+@Router(path = "/callingbed/update")
+class AppUpdateActivity :BaseActivity<AppUpdatePresenter, UpdateLayBinding>(), AppUpdateContract.View {
+    private val TAG = "AppUpdateActivity"
+
+    private val urlManager = UrlManager.build()
+
+    override fun getLayId(): Int {
+        return R.layout.update_lay
+    }
+
+    override fun bindDagger() {
+        Callingbed2Launch.component.inject(this)
+    }
+
+    override fun init() {
+        Constant.APP_UPDATING = true
+        if (!TextUtils.isEmpty(Constant.APP_PATH)) {
+            val downloadPath = urlManager.base + Constant.APP_PATH
+            Log.e(TAG, "start download: $downloadPath")
+            downLoadAPK(downloadPath)
+        } else {
+            showMessage(R.string.download_error)
+            finish()
+        }
+    }
+
+    /**
+     * 下载APK包
+     */
+    fun downLoadAPK(url: String) {
+        Log.d(TAG, "downLoadAPK  url==$url")
+        activity_appupdate_dialog_progressview.setCurProgress(0)
+        activity_update_version.setText(Constant.APP_PATH.substringAfterLast("/"))
+        activity_update_version.setOnLongClickListener {
+            Log.d(TAG, "downLoadAPK cancel...")
+            HttpHelper.cancelRequestByTag(TAG)
+            activity.finish()
+
+            return@setOnLongClickListener true
+        }
+
+        HttpHelper.download(url, TAG, object : HttpHelper.DownloadListener {
+            override fun onDownloadSuccess() {
+                Log.d("download", "onDownloadSuccess==")
+                runOnUiThread {
+                    activity_update_text_download.setText(R.string.updating)
+                }
+
+                if ("rk3288".equals(Build.MODEL)) {
+                    installApkForRk3288()
+                } else {
+                    startInstallApk()
+                }
+            }
+
+            override fun onDownloading(progress: Int) {
+                runOnUiThread {
+                    activity_appupdate_dialog_progressview.setCurProgress(progress)
+                }
+            }
+
+            override fun onDownloadFailed() {
+                Log.d("download", "onDownloadFailed==")
+                finish()
+            }
+        })
+    }
+
+    fun startInstallApk() {
+        Thread{
+            AppUpdateHelper.updateApp(this, object : AppUpdateHelper.UpdateCallBack {
+                override fun onFailed() {
+                    runOnUiThread {
+                        showMessage(R.string.update_fail)
+                        finish()
+                    }
+                }
+
+                override fun onSuccess() {
+                    runOnUiThread {
+                        showMessage(R.string.update_success)
+                        //finish()
+                        android.os.Process.killProcess(android.os.Process.myPid())
+                        System.exit(0)
+                    }
+                }
+            })
+        }.start()
+    }
+
+    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(R.string.update_fail)
+            finish()
+        }
+    }
+
+    override fun bindEvent() {
+        //
+    }
+
+    override fun destory() {
+        Constant.APP_UPDATING = false
+    }
+
+    //数据加载错误
+    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 = {
+
+        })
+    }
+}

Dosya farkı çok büyük olduğundan ihmal edildi
+ 1436 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/activity/Callingbed2Activity.kt


+ 77 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/adapter/ActionAdapter.kt

@@ -0,0 +1,77 @@
+package com.wdkl.app.ncs.callingbed2.adapter
+
+import android.content.Context
+import android.support.v7.widget.RecyclerView
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import com.bumptech.glide.Glide
+import com.bumptech.glide.load.engine.DiskCacheStrategy
+import com.wdkl.app.ncs.callingbed2.R
+import com.wdkl.ncs.android.middleware.api.UrlManager
+import com.wdkl.ncs.android.middleware.model.ActionItem
+
+class ActionAdapter : RecyclerView.Adapter<ActionAdapter.ViewHolder>{
+    private var context: Context
+    private var data: ArrayList<ActionItem>
+    private lateinit var onItemClickListener: OnItemClickListener
+
+    private val urlManager = UrlManager.build()
+
+    constructor(context: Context, data: ArrayList<ActionItem>): super() {
+        this.context = context
+        this.data = data
+    }
+
+    fun setOnItemClickListener(listener: OnItemClickListener) {
+        this.onItemClickListener = listener
+    }
+
+    fun updateData(data: ArrayList<ActionItem>) {
+        this.data = data
+        notifyDataSetChanged()
+    }
+
+    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder {
+        val view = LayoutInflater.from(parent?.context).inflate(R.layout.item_action_view, parent, false)
+        val viewHolder = ViewHolder(view)
+
+        return viewHolder
+    }
+
+    override fun getItemCount(): Int {
+        return data?.size
+    }
+
+    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+        holder.textView.text = data?.get(position).name
+        Glide.with(holder.imageView.context)
+                .load(urlManager.base + data?.get(position).iconSrc)
+                .diskCacheStrategy(DiskCacheStrategy.ALL)
+                .into(holder.imageView)
+
+        holder.actionView.setOnClickListener {
+            onItemClickListener?.onItemClick(holder.itemView, data?.get(position).id)
+        }
+    }
+
+
+    class ViewHolder: RecyclerView.ViewHolder {
+        var actionView : View
+        var textView : TextView
+        var imageView : ImageView
+
+        constructor(itemView: View): super(itemView) {
+            actionView = itemView.findViewById(R.id.ll_action_view)
+            textView = itemView.findViewById(R.id.tv_action)
+            imageView = itemView.findViewById(R.id.iv_action)
+        }
+    }
+
+    interface OnItemClickListener {
+        fun onItemClick(view: View, keyId: Int)
+    }
+}

+ 118 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/adapter/AdviceAdapter.kt

@@ -0,0 +1,118 @@
+package com.wdkl.app.ncs.callingbed2.adapter
+
+import android.content.Context
+import android.graphics.Color
+import android.support.v7.widget.RecyclerView
+import android.text.TextUtils
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import com.alibaba.fastjson.JSONArray
+import com.alibaba.fastjson.JSONObject
+import com.wdkl.app.ncs.callingbed2.R
+import com.wdkl.ncs.android.lib.utils.TimeHandle
+import com.wdkl.ncs.android.middleware.model.dos.AdviceDO
+import com.wdkl.ncs.android.middleware.tcp.enums.AdviceTypeEnum
+import com.wdkl.ncs.android.middleware.utils.StringUtil
+
+class AdviceAdapter : RecyclerView.Adapter<AdviceAdapter.ViewHolder> {
+
+    private var context: Context
+    private var advices: ArrayList<AdviceDO>
+
+    constructor(context: Context, data: ArrayList<AdviceDO>) {
+        this.context = context
+        this.advices = data
+    }
+
+    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder {
+        val view = LayoutInflater.from(parent?.context).inflate(R.layout.item_advice, parent, false)
+        val viewHolder = ViewHolder(view)
+
+        return viewHolder
+    }
+
+    override fun onBindViewHolder(holder: ViewHolder?, position: Int) {
+        if (advices.get(position).type == AdviceTypeEnum.LONG_TERM.name) {
+            holder?.adviceType?.setTextColor(Color.parseColor("#2F9DF1"))
+            holder?.adviceType?.text = StringUtil.getResString(R.string.advice_long_term)
+        } else if (advices.get(position).type == AdviceTypeEnum.TEMP.name) {
+            holder?.adviceType?.setTextColor(Color.RED)
+            holder?.adviceType?.text = StringUtil.getResString(R.string.advice_temp)
+        } else {
+            holder?.adviceType?.setTextColor(Color.RED)
+            holder?.adviceType?.text = StringUtil.getResString(R.string.advice_unknown)
+        }
+
+        if (advices.get(position).status != null && advices.get(position).status == 1) {
+            holder?.adviceStatus?.setTextColor(Color.GREEN)
+            holder?.adviceStatus?.text = StringUtil.getResString(R.string.advice_status_valid)
+        } else {
+            holder?.adviceStatus?.setTextColor(Color.RED)
+            holder?.adviceStatus?.text = StringUtil.getResString(R.string.advice_status_invalid)
+        }
+
+        if (advices.get(position).startTime != null) {
+            holder?.adviceStartTime?.text = StringUtil.getResString(R.string.advice_start_time) + TimeHandle.getDateTime(advices.get(position).startTime * 1000L, "yyyy-MM-dd")
+        } else {
+            holder?.adviceStartTime?.text = StringUtil.getResString(R.string.advice_start_time) + "--:--"
+        }
+        if (advices.get(position).endTime != null) {
+            holder?.adviceEndTime?.text = StringUtil.getResString(R.string.advice_end_time) + TimeHandle.getDateTime(advices.get(position).endTime * 1000L, "yyyy-MM-dd")
+        } else {
+            holder?.adviceEndTime?.text = StringUtil.getResString(R.string.advice_end_time) + "--:--"
+        }
+
+        if (!TextUtils.isEmpty(advices.get(position).content)) {
+            holder?.adviceContent?.text = StringUtil.getResString(R.string.advice_content) + "          " + advices.get(position).content
+        } else {
+            holder?.adviceContent?.text = StringUtil.getResString(R.string.advice_content)
+        }
+
+        if (!TextUtils.isEmpty(advices.get(position).detail)) {
+            var detail = ""
+            val jsonArray = JSONArray.parseArray(advices.get(position).detail)
+            for (item in jsonArray) {
+                val advice = item as JSONObject
+                detail = detail + advice.get("name") + " : " + advice.get("value") + "  "
+            }
+
+            holder?.adviceDetail?.text = StringUtil.getResString(R.string.advice_detail) + "          " + detail
+        } else {
+            holder?.adviceDetail?.text = StringUtil.getResString(R.string.advice_detail)
+        }
+    }
+
+    override fun getItemCount(): Int {
+        return advices.size
+    }
+
+    fun updateAdvices(data: List<AdviceDO>, clear: Boolean) {
+        if (clear) {
+            advices.clear()
+            advices.addAll(data)
+        } else {
+            advices.addAll(data)
+        }
+        notifyDataSetChanged()
+    }
+
+    class ViewHolder : RecyclerView.ViewHolder {
+        var adviceType : TextView
+        var adviceStatus : TextView
+        var adviceStartTime : TextView
+        var adviceEndTime : TextView
+        var adviceContent : TextView
+        var adviceDetail : TextView
+
+        constructor(item : View) : super(item) {
+            adviceType = item.findViewById(R.id.tv_item_advice_type)
+            adviceStatus = item.findViewById(R.id.tv_item_advice_status)
+            adviceStartTime = item.findViewById(R.id.tv_item_advice_start_time)
+            adviceEndTime = item.findViewById(R.id.tv_item_advice_end_time)
+            adviceContent = item.findViewById(R.id.tv_item_advice_content)
+            adviceDetail = item.findViewById(R.id.tv_item_advice_detail)
+        }
+    }
+}

+ 248 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/adapter/CallRecordsItemAdapter.kt

@@ -0,0 +1,248 @@
+package com.wdkl.ncs.android.component.nursehome.adapter
+
+import android.content.Intent
+import android.support.v4.content.ContextCompat.startActivity
+import android.text.TextUtils
+import android.util.Log
+import android.view.View
+import android.view.ViewGroup
+import com.alibaba.android.vlayout.LayoutHelper
+import com.alibaba.android.vlayout.layout.LinearLayoutHelper
+import com.wdkl.app.ncs.callingbed2.R
+import com.wdkl.app.ncs.callingbed2.databinding.AdapterCallRecordsItemBinding
+import com.wdkl.ncs.android.lib.adapter.BaseDelegateAdapter
+import com.wdkl.ncs.android.lib.utils.BaseRecyclerViewHolder
+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.logic.contract.shop.ShopCategoryActivityContract
+import com.wdkl.ncs.android.middleware.model.dos.CallingHistoryDO
+import com.wdkl.ncs.android.middleware.model.dos.InteractionDO
+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.EventUtil
+import com.wdkl.ncs.android.middleware.tcp.channel.ImUtil
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel
+import com.wdkl.ncs.android.middleware.tcp.enums.TcpType
+
+/**
+ * 呼叫记录适配器
+ */
+class CallRecordsItemAdapter(var data: ArrayList<InteractionVO>) : BaseDelegateAdapter<BaseRecyclerViewHolder<AdapterCallRecordsItemBinding>, InteractionVO>() {
+    var TAG = CallRecordsItemAdapter::class.java.getSimpleName()
+
+    /**
+     * 数据提供者
+     */
+    override fun dataProvider(): Any {
+        return data
+    }
+
+    /**
+     * Item坐标
+     */
+    override fun itemFilter(position: Int): Boolean {
+        return true
+    }
+
+    /**
+     * 获取Item总数
+     */
+    override fun getItemCount(): Int {
+        return data.size
+    }
+
+    //刷新数据
+    fun updateCallRecords(data: ArrayList<InteractionVO>) {
+        this.data = data
+        notifyDataSetChanged()
+    }
+
+    /**
+     * 创建LayoutHelper
+     */
+    override fun onCreateLayoutHelper(): LayoutHelper {
+        return LinearLayoutHelper(0, data.size)
+    }
+
+    /**
+     * 创建ViewHolder
+     */
+    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): BaseRecyclerViewHolder<AdapterCallRecordsItemBinding> {
+        return BaseRecyclerViewHolder.build(parent, R.layout.adapter_call_records_item)
+    }
+
+    /**
+     * 绑定数据
+     */
+    override fun onBindViewHolder(holder: BaseRecyclerViewHolder<AdapterCallRecordsItemBinding>?, position: Int) {
+        holder?.bind { binding ->
+            val itemData = getItem(position)
+            if (itemData.createDate != null) {
+                binding.callTimeTv.text = TimeHandle.getDateTime(itemData.createDate * 1000, "MM-dd HH:mm")
+            }
+            if (itemData.actionAccept != null) {
+                binding.processingTimeTv.text = TimeHandle.getDateTime(itemData.actionAccept * 1000, "MM-dd HH:mm")
+            }
+
+            //是否已播放 已响应
+            if (itemData.actionEnd != null) {
+                /*Log.e(TAG, "" + itemData.actionEnd+" "+position)
+                Log.e(TAG, "" + itemData.actionType+" "+position)
+                Log.e(TAG, "" + itemData.data+" "+position)
+                Log.e(TAG, "" + itemData.actionType+" "+position)
+                Log.e(TAG, "" + TcpType.IM.name+" "+position)*/
+
+                binding.treatmentStateImagev.setImageResource(R.mipmap.ic_event_done)
+//                binding.callStatusImagev.setImageResource(R.drawable.yi_jie)
+                binding.treatmentStateImagev.visibility = View.VISIBLE
+                binding.processingTimeTv.visibility = View.VISIBLE
+
+                //判断是呼入还是呼出 1 分机到主机 2主机到分机
+                if(itemData.actionDirectionType == 1){
+                    binding.sickbedTv.text = itemData.toFrameFullName
+                    binding.nameTv.text = itemData.toMemberName
+                    //TODO 图标显示不正常 暂时没放完整图标
+                    binding.callStatusImagev.setImageResource(R.mipmap.ic_call_done)
+                }else if(itemData.actionDirectionType == 2 || itemData.actionDirectionType == 3){
+                    binding.sickbedTv.text = itemData.fromFrameFullName
+                    binding.nameTv.text = itemData.fromMemberName
+                    binding.callStatusImagev.setImageResource(R.mipmap.ic_call_done)
+                }
+
+                if(itemData.actionType == TcpType.EVENT.name){//事件已经响应 相应的数据
+                    binding.playTv.visibility = View.GONE
+                    binding.projectTv.visibility = View.VISIBLE
+                    binding.conductorNameTv.visibility = View.VISIBLE
+                    binding.projectTv.text = itemData.data
+                    binding.conductorNameTv.text = itemData.toMemberName
+                    binding.processingTimeTv.text = TimeHandle.getDateTime(itemData.actionEnd*1000, "MM-dd HH:mm")
+                    binding.projectTv.setBackgroundResource(R.mipmap.ic_event_handled)
+                }else if (itemData.actionType == TcpType.IM.name){//语音已播放
+
+                    binding.projectTv.visibility = View.GONE
+                    binding.playTv.visibility = View.VISIBLE
+                    binding.conductorNameTv.visibility = View.GONE
+                    binding.playTv.setBackgroundResource(R.mipmap.ic_play_done)
+                    binding.processingTimeTv.text = "已播放"
+
+                }else if(itemData.actionType == TcpType.VOICE.name){ //语音呼叫已接听
+                    binding.projectTv.visibility = View.GONE
+                    binding.playTv.visibility = View.VISIBLE
+                    binding.treatmentStateImagev.visibility = View.GONE
+                    binding.processingTimeTv.visibility = View.GONE
+
+                }else if(itemData.actionType == TcpType.VIDEO.name){ //视频呼叫已接听
+
+                    binding.projectTv.visibility = View.GONE
+                    binding.playTv.visibility = View.VISIBLE
+                    binding.treatmentStateImagev.visibility = View.GONE
+                    binding.processingTimeTv.visibility = View.GONE
+                }
+
+            } else {
+                /*Log.e(TAG, "" + itemData.actionEnd+" "+position)
+                Log.e(TAG, "" + itemData.actionType+" "+position)
+                Log.e(TAG, "" + itemData.data+" "+position)
+                Log.e(TAG, "" + itemData.actionDirectionType+" "+position)*/
+
+                //判断是呼入还是呼出 1 分机到主机 2主机到分机
+                if(itemData.actionDirectionType == 1){
+                    Log.e(TAG, "进入。。。。" )
+                    binding.sickbedTv.text = itemData.toFrameFullName
+                    binding.nameTv.text = itemData.toMemberName
+                    // 图标显示不正常 暂时没放完整图标
+                    binding.callStatusImagev.setImageResource(R.mipmap.ic_call_undo)
+                }else if(itemData.actionDirectionType == 2 || itemData.actionDirectionType == 3){
+                    binding.sickbedTv.text = itemData.fromFrameFullName
+                    binding.nameTv.text = itemData.fromMemberName
+                    binding.callStatusImagev.setImageResource(R.mipmap.ic_call_undo)
+                }
+
+                binding.treatmentStateImagev.setImageResource(R.mipmap.ic_event_undo)
+//                binding.callStatusImagev.setImageResource(R.drawable.wei_jie)
+                binding.conductorNameTv.visibility = View.GONE
+                binding.treatmentStateImagev.visibility = View.VISIBLE
+                binding.processingTimeTv.visibility = View.VISIBLE
+                if(itemData.actionType == TcpType.EVENT.name){//事件未处理
+                    binding.playTv.visibility = View.GONE
+                    binding.projectTv.visibility = View.VISIBLE
+                    binding.projectTv.text = itemData.data
+                    binding.projectTv.setBackgroundResource(R.mipmap.ic_event_unhandle)
+                    binding.processingTimeTv.text = "未处理"
+                }else if (itemData.actionType == TcpType.IM.name){//语音未播放
+                    binding.projectTv.visibility = View.GONE
+                    binding.playTv.visibility = View.VISIBLE
+                    binding.playTv.setBackgroundResource(R.mipmap.ic_play)
+                    binding.processingTimeTv.text = "未播放"
+                }else if(itemData.actionType == TcpType.VOICE.name){ //语音呼叫未接听
+                    binding.projectTv.visibility = View.GONE
+                    binding.playTv.visibility = View.GONE
+                    binding.treatmentStateImagev.visibility = View.GONE
+                    binding.processingTimeTv.visibility = View.GONE
+                }else if(itemData.actionType == TcpType.VIDEO.name){ //视频呼叫未接听
+                    binding.projectTv.visibility = View.GONE
+                    binding.playTv.visibility = View.GONE
+                    binding.treatmentStateImagev.visibility = View.GONE
+                    binding.processingTimeTv.visibility = View.GONE
+
+                }
+            }
+
+
+/*            binding.projectTv.setOnClickListener {
+                //事件处理监听
+//                    点击之后发送通知
+//                    showMessage("点击了事件按钮")
+                if (itemData.actionEnd != null)return@setOnClickListener
+                Log.e(TAG, "点击了事件按钮")
+
+                Thread(Runnable {
+                    run {
+                        Log.e(TAG, "aaassss "+Constants.ids +"kong")
+
+                        if (!Constants.ids.equals("")) {
+                            var eventTcpModel = EventUtil.eventResponse(Constants.ids.toInt(), itemData.fromDeviceId, itemData.id)
+//                        val map = HashMap<String,Int>()
+//                        map.put("id",1)
+//                        eventTcpModel.setData(map)
+                            TcpClient.getInstance().sendMsg(eventTcpModel.toJson())
+                        } else {
+                            showMessage("获取不到当给前设备id")
+                        }
+                    }
+                }).start()
+
+                //处理完之后要刷新数据
+            }*/
+
+/*            binding.playTv.setOnClickListener {
+                if (itemData.actionEnd != null)return@setOnClickListener
+                //点击之后播放语音留言
+                showMessage("点击了播放留言")
+                Thread(Runnable {
+                    run {
+                        if (!Constants.ids.equals("")) {
+                            var imUtilTcpModel = ImUtil.imRead(Constants.ids.toInt(), itemData.fromDeviceId, itemData.id)
+
+//                val map = HashMap<String,Int>()
+//                map.put("id",1)
+//                imUtilTcpModel.setData(map)
+                            TcpClient.getInstance().sendMsg(imUtilTcpModel.toJson())
+                            var mediaPlayer = MediaPlayer()
+                            mediaPlayer.startMediaPlayer("http://192.168.1.112:8006"+itemData.data)
+                            mediaPlayer.setVolume(0.3f)
+
+                        } else {
+                            showMessage("获取不到当给前设备id")
+                        }
+                    }
+                }).start()
+
+                //处理完之后要刷新数据
+            }*/
+
+        }
+    }
+
+}

+ 96 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/adapter/CostItemAdapter.kt

@@ -0,0 +1,96 @@
+package com.wdkl.app.ncs.callingbed2.adapter
+
+import android.content.Context
+import android.support.v7.widget.LinearLayoutManager
+import android.support.v7.widget.RecyclerView
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import com.wdkl.app.ncs.callingbed2.R
+import com.wdkl.ncs.android.middleware.model.vo.CustomerFeeConfigByGroupNameVO
+import com.wdkl.ncs.android.middleware.model.vo.CustomerFeeConfigVO
+import com.wdkl.ncs.android.middleware.utils.StringUtil
+
+class CostItemAdapter : RecyclerView.Adapter<CostItemAdapter.ParentViewHolder> {
+
+    private var context: Context
+    private var mainData: ArrayList<CustomerFeeConfigByGroupNameVO>
+
+    constructor(context: Context, data: ArrayList<CustomerFeeConfigByGroupNameVO>) {
+        this.context = context
+        this.mainData = data
+    }
+
+    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ParentViewHolder {
+        val view = LayoutInflater.from(parent?.context).inflate(R.layout.item_cost_main_view, parent, false)
+        val viewHolder = ParentViewHolder(view)
+
+        return viewHolder
+    }
+
+    override fun onBindViewHolder(holder: ParentViewHolder?, position: Int) {
+        holder?.costGroupName?.text = mainData.get(position).feeGroupName
+        holder?.costGroupTotal?.text = StringUtil.getResString(R.string.subtotal) + mainData.get(position).subtotal
+
+        val layoutManager = LinearLayoutManager(context)
+        holder?.costDetail?.layoutManager = layoutManager
+        holder?.costDetail?.adapter = CostDetailAdapter(mainData.get(position).customerFeeConfigList)
+    }
+
+    override fun getItemCount(): Int {
+        return mainData.size
+    }
+
+    class ParentViewHolder : RecyclerView.ViewHolder {
+        var costGroupName : TextView
+        var costGroupTotal : TextView
+        var costDetail : RecyclerView
+
+        constructor(itemView: View): super(itemView) {
+            costGroupName = itemView.findViewById(R.id.tv_cost_group_name)
+            costGroupTotal = itemView.findViewById(R.id.tv_cost_group_total)
+            costDetail = itemView.findViewById(R.id.rv_cost_detail)
+        }
+    }
+
+    class CostDetailAdapter : RecyclerView.Adapter<CostDetailAdapter.ChildViewHolder> {
+        private var costData: List<CustomerFeeConfigVO>
+
+        constructor(data: List<CustomerFeeConfigVO>) {
+            costData = data
+        }
+
+        override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ChildViewHolder {
+            val view = LayoutInflater.from(parent?.context).inflate(R.layout.item_cost_detail, parent, false)
+            val viewHolder = ChildViewHolder(view)
+
+            return viewHolder
+        }
+
+        override fun onBindViewHolder(holder: ChildViewHolder?, position: Int) {
+            holder?.costName?.text = costData.get(position).feeName
+            holder?.costValue?.text = "" + costData.get(position).feeValue
+            holder?.costId?.text = costData.get(position).keyCode
+            holder?.costUnit?.text = costData.get(position).unit
+        }
+
+        override fun getItemCount(): Int {
+            return costData.size
+        }
+
+        class ChildViewHolder : RecyclerView.ViewHolder {
+            var costName : TextView
+            var costValue : TextView
+            var costId : TextView
+            var costUnit : TextView
+
+            constructor(item : View) : super(item) {
+                costName = item.findViewById(R.id.tv_item_cost_name)
+                costValue = item.findViewById(R.id.tv_item_cost_value)
+                costId = item.findViewById(R.id.tv_item_cost_id)
+                costUnit = item.findViewById(R.id.tv_item_cost_unit)
+            }
+        }
+    }
+}

+ 83 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/adapter/CostItemAdapter2.kt

@@ -0,0 +1,83 @@
+package com.wdkl.app.ncs.callingbed2.adapter
+
+import android.content.Context
+import android.support.v7.widget.LinearLayoutManager
+import android.support.v7.widget.RecyclerView
+import android.text.TextUtils
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import com.wdkl.app.ncs.callingbed2.R
+import com.wdkl.ncs.android.lib.utils.TimeHandle
+import com.wdkl.ncs.android.middleware.model.vo.CustomerFeeConfigByGroupNameVO
+import com.wdkl.ncs.android.middleware.model.vo.CustomerFeeConfigVO
+import com.wdkl.ncs.android.middleware.utils.StringUtil
+
+class CostItemAdapter2 : RecyclerView.Adapter<CostItemAdapter2.ViewHolder> {
+
+    private var context: Context
+    private var costData: ArrayList<CustomerFeeConfigVO>
+
+    constructor(context: Context, data: ArrayList<CustomerFeeConfigVO>) {
+        this.context = context
+        this.costData = data
+    }
+
+    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder {
+        val view = LayoutInflater.from(parent?.context).inflate(R.layout.item_cost_detail2, parent, false)
+        val viewHolder = ViewHolder(view)
+
+        return viewHolder
+    }
+
+    override fun onBindViewHolder(holder: ViewHolder?, position: Int) {
+        holder?.costGroupName?.text = costData.get(position).groupName
+        if (costData.get(position).feeTime != null) {
+            holder?.costTime?.text = TimeHandle.getDateTime(costData.get(position).feeTime * 1000L, "yyyy-MM-dd HH:mm")
+        } else {
+            holder?.costTime?.text = "--"
+        }
+        if (!TextUtils.isEmpty(costData.get(position).unit)) {
+            holder?.costName?.text = costData.get(position).feeName + "/" + costData.get(position).unit
+        } else {
+            holder?.costName?.text = costData.get(position).feeName
+        }
+        holder?.costValue?.text = "" + costData.get(position).feeValue
+        if (!TextUtils.isEmpty(costData.get(position).description)) {
+            holder?.costDetail?.text = StringUtil.getResString(R.string.cost_detail) + costData.get(position).description
+        } else {
+            holder?.costDetail?.text = StringUtil.getResString(R.string.cost_detail)
+        }
+    }
+
+    override fun getItemCount(): Int {
+        return costData.size
+    }
+
+    fun updateCostData(data: List<CustomerFeeConfigVO>, clear: Boolean) {
+        if (clear) {
+            costData.clear()
+            costData.addAll(data)
+        } else {
+            costData.addAll(data)
+        }
+        notifyDataSetChanged()
+    }
+
+    class ViewHolder : RecyclerView.ViewHolder {
+        var costGroupName : TextView
+        var costTime : TextView
+        var costName : TextView
+        var costValue : TextView
+        var costDetail : TextView
+
+        constructor(item : View) : super(item) {
+            costGroupName = item.findViewById(R.id.tv_item_cost_group_name)
+            costTime = item.findViewById(R.id.tv_item_cost_time)
+            costName = item.findViewById(R.id.tv_item_cost_name)
+            costValue = item.findViewById(R.id.tv_item_cost_value)
+            costDetail = item.findViewById(R.id.tv_item_cost_detail)
+        }
+    }
+}

+ 67 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/adapter/EventHistoryAdapter.kt

@@ -0,0 +1,67 @@
+package com.wdkl.app.ncs.callingbed2.adapter
+
+import android.content.Context
+import android.support.v7.widget.RecyclerView
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import com.wdkl.app.ncs.callingbed2.R
+import com.wdkl.ncs.android.middleware.model.EventHistoryItem
+
+class EventHistoryAdapter : RecyclerView.Adapter<EventHistoryAdapter.ViewHolder>{
+    private var context: Context
+    private var data: ArrayList<EventHistoryItem>
+
+    constructor(context: Context, data: ArrayList<EventHistoryItem>): super() {
+        this.context = context
+        this.data = data
+    }
+
+    fun updateData(data: ArrayList<EventHistoryItem>) {
+        this.data = data
+        notifyDataSetChanged()
+    }
+
+    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder {
+        val view = LayoutInflater.from(parent?.context).inflate(R.layout.item_event_history, parent, false)
+        val viewHolder = ViewHolder(view)
+
+        return viewHolder
+    }
+
+    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+        holder.roomName.text = data.get(position).room
+        holder.customName.text = data.get(position).customer
+        holder.actionTime.text = data.get(position).endTime
+        holder.actionName.text = data.get(position).actionData
+        holder.actionState.text = data.get(position).actionState
+    }
+
+    override fun getItemCount(): Int {
+        return data.size
+    }
+
+
+
+    class ViewHolder: RecyclerView.ViewHolder {
+        var customImg : ImageView
+        var callStateImg : ImageView
+        var roomName : TextView
+        var customName : TextView
+        var actionTime : TextView
+        var actionName : TextView
+        var actionState : TextView
+
+        constructor(itemView: View): super(itemView) {
+            customImg = itemView.findViewById(R.id.iv_custom)
+            callStateImg = itemView.findViewById(R.id.iv_call_state)
+            roomName = itemView.findViewById(R.id.tv_room_name)
+            customName = itemView.findViewById(R.id.tv_customer_name)
+            actionTime = itemView.findViewById(R.id.tv_action_time)
+            actionName = itemView.findViewById(R.id.tv_action_name)
+            actionState = itemView.findViewById(R.id.tv_action_state)
+        }
+    }
+}

+ 56 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/adapter/NumAdapter.java

@@ -0,0 +1,56 @@
+package com.wdkl.app.ncs.callingbed2.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.app.ncs.callingbed2.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;
+    }
+}

+ 63 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/adapter/NurseConfigAdpter.kt

@@ -0,0 +1,63 @@
+package com.wdkl.app.ncs.callingbed2.adapter
+
+import android.content.Context
+import android.graphics.Color
+import android.support.v7.widget.RecyclerView
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.LinearLayout
+import android.widget.TextView
+import com.wdkl.app.ncs.callingbed2.R
+import com.wdkl.ncs.android.middleware.model.dto.NurseConfigDto
+import java.lang.Exception
+
+class NurseConfigAdpter : RecyclerView.Adapter<NurseConfigAdpter.ViewHolder> {
+    private var context: Context
+    private var data: ArrayList<NurseConfigDto>
+
+    constructor(context: Context, data: ArrayList<NurseConfigDto>) {
+        this.context = context
+        this.data = data
+    }
+
+    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder {
+        val view = LayoutInflater.from(parent?.context).inflate(R.layout.item_nurse_config, parent, false)
+        val viewHolder = ViewHolder(view)
+
+        return viewHolder
+    }
+
+    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+        try {
+            holder.nurseItem.setBackgroundColor(Color.parseColor("#"+data.get(position).nurseColorRbg))
+            holder.nurseName.setText(data.get(position).nurseConfigName)
+            holder.nurseValue.setText(data.get(position).nurseOptionName)
+        } catch (e: Exception) {
+            e.printStackTrace()
+        }
+    }
+
+    override fun getItemCount(): Int {
+        return data.size
+    }
+
+    fun updateData(data: ArrayList<NurseConfigDto>) {
+        this.data = data
+        notifyDataSetChanged()
+    }
+
+    class ViewHolder: RecyclerView.ViewHolder {
+        //var nurseColor : TextView
+        var nurseName : TextView
+        var nurseValue : TextView
+        var nurseItem : LinearLayout
+
+        constructor(itemView: View): super(itemView) {
+            //nurseColor = itemView.findViewById(R.id.tv_nurse_color)
+            nurseName = itemView.findViewById(R.id.tv_nurse_config_name)
+            nurseValue = itemView.findViewById(R.id.tv_nurse_config_value)
+            nurseItem = itemView.findViewById(R.id.ll_nurse_item)
+        }
+    }
+}

+ 12 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/agreement/Callingbed2Agreement.kt

@@ -0,0 +1,12 @@
+package com.wdkl.app.ncs.callingbed2.agreement
+
+import com.wdkl.ncs.android.middleware.model.dto.NurseConfigDto
+
+interface Callingbed2Agreement {
+
+    //更新护理数据
+    fun updateNurseConfig(list: List<NurseConfigDto>)
+
+    //检查APP版本
+    fun checkAppVersion()
+}

+ 30 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/di/Callingbed2Component.kt

@@ -0,0 +1,30 @@
+package com.wdkl.app.ncs.callingbed2.di
+
+import com.wdkl.app.ncs.callingbed2.activity.AppUpdateActivity
+import com.wdkl.app.ncs.callingbed2.activity.Callingbed2Activity
+import com.wdkl.app.ncs.callingbed2.fragment.*
+import com.wdkl.ncs.android.middleware.di.ApplicationComponent
+import dagger.Component
+
+@Component(dependencies = arrayOf(ApplicationComponent::class))
+interface Callingbed2Component {
+    fun inject(activity: Callingbed2Activity)
+
+    fun inject(activity: AppUpdateActivity)
+
+    fun inject(activity: MainFragment)
+
+    fun inject(activity: CallFragment)
+
+    fun inject(activity: VoiceMsgFragment)
+
+    fun inject(activity: QrCodeFragment)
+
+    fun inject(activity: CostFragment)
+
+    fun inject(activity: CostFragment2)
+
+    fun inject(activity: AdviceFragment)
+
+    fun inject(activity: TestFragment)
+}

+ 107 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/fragment/AdviceFragment.kt

@@ -0,0 +1,107 @@
+package com.wdkl.app.ncs.callingbed2.fragment
+
+import android.support.v7.widget.LinearLayoutManager
+import com.enation.javashop.net.engine.model.NetState
+import com.wdkl.app.ncs.callingbed2.R
+import com.wdkl.app.ncs.callingbed2.adapter.AdviceAdapter
+import com.wdkl.app.ncs.callingbed2.databinding.AdviceViewLayBinding
+import com.wdkl.app.ncs.callingbed2.launch.Callingbed2Launch
+import com.wdkl.ncs.android.lib.base.BaseFragment
+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.logic.contract.callingbed2.AdviceFragmentContract
+import com.wdkl.ncs.android.middleware.logic.presenter.callingbed2.AdviceFragmentPresenter
+import com.wdkl.ncs.android.middleware.model.dos.AdviceDO
+import kotlinx.android.synthetic.main.advice_view_lay.*
+
+class AdviceFragment : BaseFragment<AdviceFragmentPresenter, AdviceViewLayBinding>(), AdviceFragmentContract.View {
+
+    private var pageNo = 1
+    private lateinit var adapter: AdviceAdapter
+
+    override fun getLayId(): Int {
+        return R.layout.advice_view_lay
+    }
+
+    override fun bindDagger() {
+        Callingbed2Launch.component.inject(this)
+    }
+
+    override fun init() {
+        adapter = AdviceAdapter(activity, ArrayList())
+        val layoutManager = LinearLayoutManager(activity)
+        rv_advice_main_view.layoutManager = layoutManager
+        rv_advice_main_view.adapter = adapter
+
+        if (Constant.CUSTOM_ID != -1) {
+            presenter.loadAdvicesByPage(pageNo, 10, Constant.CUSTOM_ID)
+        } else {
+            showMessage("no custom id")
+        }
+    }
+
+    override fun bindEvent() {
+        advice_refresh.setOnRefreshListener {
+            if (Constant.CUSTOM_ID != -1) {
+                pageNo = 1
+                presenter.loadAdvicesByPage(pageNo, 10, Constant.CUSTOM_ID)
+            } else {
+                showMessage("no custom id")
+            }
+        }
+
+        advice_refresh.setOnLoadMoreListener {
+            if (Constant.CUSTOM_ID != -1) {
+                pageNo += 1
+                presenter.loadAdvicesByPage(pageNo, 10, Constant.CUSTOM_ID)
+            } else {
+                showMessage("no custom id")
+            }
+        }
+    }
+
+    override fun destory() {
+        //
+    }
+
+    override fun showAdvices(advices: ArrayList<AdviceDO>) {
+        advice_refresh.finishRefresh()
+        advice_refresh.finishLoadMore()
+
+        if (pageNo == 1) {
+            adapter.updateAdvices(advices, true)
+        } else {
+            adapter.updateAdvices(advices, false)
+        }
+    }
+
+    override fun onError(message: String, type: Int) {
+        //errorLog("error",message)
+        showMessage(message)
+        advice_refresh.finishRefresh()
+        advice_refresh.finishLoadMore()
+    }
+
+    override fun onNoNet() {
+        showMessage("none network")
+        advice_refresh.finishRefresh()
+        advice_refresh.finishLoadMore()
+    }
+
+    override fun complete(message: String, type: Int) {
+    }
+
+    override fun start() {
+    }
+
+    override fun networkMonitor(state: NetState) {
+        state.filter(onWifi = {
+
+        },onMobile = {
+
+        },offline = {
+
+        })
+    }
+}

+ 141 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/fragment/BaseCallFragment.kt

@@ -0,0 +1,141 @@
+package com.wdkl.app.ncs.callingbed2.fragment
+
+import android.os.Bundle
+import android.os.CountDownTimer
+import android.support.v4.app.Fragment
+import android.view.LayoutInflater
+import android.view.MotionEvent
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import com.enation.javashop.utils.base.tool.BaseToolActivity
+import com.wdkl.app.ncs.callingbed2.R
+import com.wdkl.app.ncs.callingbed2.helper.RingPlayHelper
+import com.wdkl.app.ncs.callingbed2.helper.SerialPortHelper
+import com.wdkl.app.ncs.callingbed2.settings.SettingConfig
+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.VoiceUtil
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel
+import org.greenrobot.eventbus.EventBus
+
+abstract class BaseCallFragment: Fragment(), View.OnTouchListener {
+
+    private var layout: View? = null
+
+    protected lateinit var baseActivity: BaseToolActivity
+
+    //通话状态:0-去电, 1-来电, 2-探视
+    protected var callState : Int = 0
+    protected var tcpModel: TcpModel? = null
+    protected var bcPlay: Boolean = false
+
+    //计时器
+    lateinit var countDownTimer: CountDownTimer
+
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        retainInstance = true
+        callState = arguments.getInt("call_state")
+        bcPlay = arguments.getBoolean("bc_play")
+        if (arguments.getSerializable("tcp_model") != null) {
+            tcpModel = arguments.getSerializable("tcp_model") as TcpModel
+        }
+    }
+
+    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()
+    }
+
+    protected abstract fun getLayId(): Int
+
+    protected abstract fun init()
+
+    protected abstract fun bindEvent()
+
+    protected abstract fun destroy()
+
+    protected abstract fun callEnd(handoff: Boolean)
+
+    override fun onTouch(v: View?, event: MotionEvent?): Boolean {
+        return true
+    }
+
+    //初始化计时器
+    protected fun initCountDownTimer(view: TextView) {
+        val overTime = SettingConfig.getSipOverTime(baseActivity) * 1000L
+        countDownTimer = object: CountDownTimer(overTime, 1000) {
+            override fun onTick(millisUntilFinished: Long) {
+                if (view != null) {
+                    val time = millisUntilFinished/1000
+                    val timeText = getString(R.string.countdown_time, time)
+                    view.setText(timeText)
+                }
+            }
+
+            override fun onFinish() {
+                //呼叫超时,返回到主界面
+                RingPlayHelper.stopRingTone()
+                showMessage(R.string.no_response)
+                Constant.CALL_STATE = Constant.CALL_STANDBY
+                VoiceUtil.cancelAudioCall(Constant.DEVICE_ID)
+                SerialPortHelper.setCallStatus("0")
+                //backToMain()
+                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("BackCall", Constant.EVENT_REMOVE_CALL_FRAGMENT))
+    }
+
+}

+ 362 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/fragment/CallFragment.kt

@@ -0,0 +1,362 @@
+package com.wdkl.app.ncs.callingbed2.fragment
+
+import android.os.CountDownTimer
+import android.os.SystemClock
+import android.text.TextUtils
+import android.util.Log
+import android.view.View
+import com.enation.javashop.net.engine.model.NetState
+import com.google.gson.Gson
+import com.wdkl.app.ncs.callingbed2.R
+import com.wdkl.app.ncs.callingbed2.activity.Callingbed2Activity
+import com.wdkl.app.ncs.callingbed2.agreement.Callingbed2Agreement
+import com.wdkl.app.ncs.callingbed2.databinding.VoiceCallLayBinding
+import com.wdkl.app.ncs.callingbed2.helper.MediaPlayHelper
+import com.wdkl.app.ncs.callingbed2.helper.SoundPoolManager
+import com.wdkl.app.ncs.callingbed2.launch.Callingbed2Launch
+import com.wdkl.app.ncs.callingbed2.settings.SettingConfig
+//import com.wdkl.app.ncs.sip.event.AEvent
+//import com.wdkl.app.ncs.sip.event.IEventListener
+//import com.wdkl.app.ncs.sip.helper.StarRtcHelper
+import com.wdkl.ncs.android.lib.base.BaseFragment
+import com.wdkl.ncs.android.lib.utils.debugLog
+import com.wdkl.ncs.android.lib.utils.errorLog
+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.callingbed2.CallFragmentContract
+import com.wdkl.ncs.android.middleware.logic.presenter.callingbed2.MainFragmentPresenter
+import com.wdkl.ncs.android.middleware.model.vo.InteractionVO
+import com.wdkl.ncs.android.middleware.tcp.channel.VoiceUtil
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel
+import com.wdkl.ncs.android.middleware.tcp.enums.TcpAction
+import kotlinx.android.synthetic.main.voice_call_lay.*
+import org.greenrobot.eventbus.EventBus
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+
+class CallFragment : BaseFragment<MainFragmentPresenter, VoiceCallLayBinding>(), CallFragmentContract.View/*, IEventListener*/ {
+    val TAG = "CallFragment"
+
+    //通话状态:0-去电, 1-来电, 2-接通, 3-挂断
+    var callState : Int = 0
+    //呼叫倒计时
+    lateinit var countDownTimer: CountDownTimer
+    //来电设备id
+    var fromId: Int = -1
+    //目的设备id
+    var toId: Int = -1
+    //Sip通话目标设备id
+    var sipTargetId: String = ""
+    //Interaction ID
+    var interactionId: Int = -1
+    //去电铃声id
+    //var outCallStreamId: Int = -1
+    //来电铃声id
+    //var inCallStreamId: Int = -1
+
+
+    override fun getLayId(): Int {
+        return R.layout.voice_call_lay
+    }
+
+    override fun bindDagger() {
+        Callingbed2Launch.component.inject(this)
+    }
+
+    override fun init() {
+        initCountDownTimer()
+        //StarRtcHelper.getInstance().addAudioCallListeners(this)
+
+        when (callState) {
+            0 -> {
+                //去电
+                sendCall()
+                VoiceUtil.startAudioCall(Constant.DEVICE_ID)
+                //播放铃音
+                MediaPlayHelper.getInstance().playResMusic(R.raw.outgoing_call, 0.6f, true)
+            }
+
+            1 -> {
+                //来电
+                incomingCall()
+                //播放铃声
+                MediaPlayHelper.getInstance().playResMusic(R.raw.incoming_call, 1.0f, true)
+            }
+
+            2 -> {
+                //接通
+                //acceptCall()
+            }
+
+            3 -> {
+                //挂断
+                //rejectCall()
+            }
+        }
+    }
+
+    override fun bindEvent() {
+        //去电或正在通话界面挂断按钮
+        voice_call_hangup.setOnClickListener {
+            //挂断通话,返回首页
+            if (Constant.CALL_STATE == Constant.CALL_CALLING) {
+                Constant.CALL_STATE = Constant.CALL_STANDBY
+                //StarRtcHelper.getInstance().hangupAudioCall()
+                VoiceUtil.handoffAudioCall(Constant.DEVICE_ID, fromId, interactionId)
+                backToMain()
+            } else {
+                Constant.CALL_STATE = Constant.CALL_STANDBY
+                VoiceUtil.cancelAudioCall(Constant.DEVICE_ID)
+                cancelCall()
+            }
+        }
+        //来电界面挂断按钮
+        voice_call_ring_hangoff.setOnClickListener {
+            //挂断通话,返回首页
+            MediaPlayHelper.getInstance().stopMusic()
+            Constant.CALL_STATE = Constant.CALL_STANDBY
+            VoiceUtil.rejectAudioCall(Constant.DEVICE_ID, fromId, interactionId)
+            backToMain()
+        }
+        //来电界面接听按钮
+        voice_call_ring_pickup_audio.setOnClickListener {
+            //接收通话,向主叫方发出已接听的TCP消息,主叫方接收该消息后向我发起sip通话请求,我自动接听sip通话
+            Log.d("wzlll", "pickup call state: " + Constant.CALL_STATE + ", my id: " + Constant.DEVICE_ID + ", from id: " + fromId + ", interaction id: " + interactionId + ", target sip: " + sipTargetId)
+            MediaPlayHelper.getInstance().stopMusic()
+            //if (!TextUtils.isEmpty(sipTargetId)) {
+                Constant.CALL_STATE = Constant.CALL_INCOMING
+                VoiceUtil.acceptAudioCall(Constant.DEVICE_ID, fromId, interactionId)
+            //}
+        }
+    }
+
+    override fun onStart() {
+        EventBus.getDefault().register(this)
+        super.onStart()
+    }
+
+    override fun onStop() {
+        EventBus.getDefault().unregister(this)
+        super.onStop()
+    }
+
+    override fun destory() {
+        countDownTimer.cancel()
+        if (Constant.CALL_STATE == Constant.CALL_CALLING) {
+            //StarRtcHelper.getInstance().hangupAudioCall()
+            VoiceUtil.handoffAudioCall(Constant.DEVICE_ID, fromId, interactionId)
+        }
+        Constant.CALL_STATE = Constant.CALL_STANDBY
+        //StarRtcHelper.getInstance().removeAudioCallListeners(this)
+        MediaPlayHelper.getInstance().stopMusic()
+    }
+
+    override fun onError(message: String, type: Int) {
+        getUtils().dismissDialog()
+        errorLog("error",message)
+        showMessage(message)
+    }
+
+    override fun complete(message: String, type: Int) {
+        getUtils().dismissDialog()
+    }
+
+    override fun start() {
+        getUtils().showDialog()
+    }
+
+    override fun networkMonitor(state: NetState) {
+        state.filter(onWifi = {
+
+        },onMobile = {
+
+        },offline = {
+
+        })
+    }
+
+/*    override fun dispatchEvent(aEventID: String, success: Boolean, eventObj: Any) {
+        Log.d("wzlll", "call state: " + Constant.CALL_STATE)
+        Log.d("wzlll", "received sip event: " + aEventID + ", success: " + success + ", event obj: " + eventObj.toString())
+        when (aEventID) {
+            AEvent.AEVENT_VOIP_REV_CALLING_AUDIO -> {
+                //分机呼叫主机,主机接听,同时发送sip通话请求,分机自动接听
+                if (Constant.CALL_STATE != Constant.CALL_CALLING) {
+                    MediaPlayHelper.getInstance().stopMusic()
+                    StarRtcHelper.getInstance().pickupAudioCall(activity, eventObj.toString())
+                    activity.runOnUiThread {
+                        acceptCall()
+                    }
+                }
+            }
+            AEvent.AEVENT_VOIP_REV_CALLING -> {
+                //语音通话请求
+                //if (Constant.CALL_STATE != Constant.CALL_CALLING) {
+                //    StarRtcHelper.getInstance().pickupAudioCall(activity, eventObj.toString())
+                //    activity.runOnUiThread {
+                //                        acceptCall()
+                //                    }
+                //}
+            }
+            AEvent.AEVENT_VOIP_REV_BUSY -> {
+                //对方线路忙
+                activity.runOnUiThread {
+                    //rejectCall()
+                    showMessage("线路忙!")
+                }
+            }
+
+            AEvent.AEVENT_VOIP_REV_REFUSED -> {
+                //对方拒绝通话
+                activity.runOnUiThread {
+                    //rejectCall()
+                }
+            }
+
+            AEvent.AEVENT_VOIP_REV_HANGUP -> {
+                //对方已挂断
+                activity.runOnUiThread {
+                    if (Constant.CALL_STATE == Constant.CALL_CALLING) {
+                        rejectCall()
+                    }
+                }
+            }
+
+            AEvent.AEVENT_VOIP_REV_CONNECT -> {
+                //对方接受通话
+                activity.runOnUiThread {
+                    //showMessage("通话成功!")
+                    //acceptCall()
+                }
+            }
+
+            AEvent.AEVENT_VOIP_REV_ERROR -> {
+                //通话错误
+                activity.runOnUiThread {
+                    //showMessage("通话错误!")
+                    rejectCall()
+                }
+            }
+        }
+    }*/
+
+    fun initCountDownTimer() {
+        val overTime = SettingConfig.getSipOverTime(getActivity()) * 1000L
+        countDownTimer = object: CountDownTimer(overTime, 1000) {
+            override fun onTick(millisUntilFinished: Long) {
+                val time = millisUntilFinished/1000
+                voice_call_timeout?.setText("呼叫倒计时: " + time + " 秒")
+            }
+
+            override fun onFinish() {
+                //呼叫超时,返回到主界面
+                showMessage("无人应答...")
+                MediaPlayHelper.getInstance().stopMusic()
+                VoiceUtil.cancelAudioCall(Constant.DEVICE_ID)
+                backToMain()
+            }
+        }
+    }
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    fun onMoonEvent(messageEvent: MessageEvent) {
+        when (messageEvent.getType()) {
+            Constant.EVENT_TCP_MSG -> {
+                val tcpModel = messageEvent.message as TcpModel
+                if (tcpModel.getAction() == TcpAction.VoiceAction.ACCEPT) { //我方呼出,对方接受
+                    //todo: 通话中界面更新;建立数据通话
+                    val interactionVO = Gson().fromJson(tcpModel.data.toString(), InteractionVO::class.java)
+                    interactionId = interactionVO.id
+                    fromId = tcpModel.fromId
+                    //acceptCall()
+                } else if (tcpModel.getAction() == TcpAction.VoiceAction.REJECT) { //我方呼出,对方拒绝
+                    //todo: 清掉呼出的TcpModel,通话中界面更新 --- 显示对方拒绝并停留3秒,结束至正常界面;更新左侧
+                    showMessage("对方已拒绝!")
+                    rejectCall()
+                } else if (tcpModel.getAction() == TcpAction.VoiceAction.CALLING) { //我方呼出,对方通话中
+                    //todo: 清掉呼出的TcpModel,通话中界面更新 --- 显示对方占线并停留3秒,结束至正常界面;更新左侧
+                    //对于分机来说,对方处于通话中应当还是可以正常呼叫,而不应该直接挂断
+                    //showMessage("对方处于通话中!")
+                    //rejectCall()
+                } else if (tcpModel.getAction() == TcpAction.VoiceAction.SUCCESS) { //呼叫成功
+                    val interactionVO = Gson().fromJson(tcpModel.data.toString(), InteractionVO::class.java)
+                    interactionId = interactionVO.id
+                    voice_call_calling_text.setText("呼叫成功,等待接听中...")
+                } else if (tcpModel.getAction() == TcpAction.VoiceAction.FAILED) { //我方呼出,对方不在线,设备离线或其它错误
+                    //todo: 清掉呼出的TcpModel,通话中界面更新 --- 显示对方离线并停留3秒,结束至正常界面;更新左侧
+                    showMessage("呼叫失败,对方可能不在线!")
+                    MediaPlayHelper.getInstance().stopMusic()
+                    rejectCall()
+                } else if (tcpModel.getAction() == TcpAction.VoiceAction.HANDOFF) { //对方挂断,不论我方呼出或呼入
+                    //todo: 清掉呼出的TcpModel,通话中界面更新 --- 显示对方已挂断并停留3秒,结束至正常界面;更新左侧
+                    //showMessage("通话结束!")
+                    MediaPlayHelper.getInstance().stopMusic()
+                    rejectCall()
+                } else if (tcpModel.getAction() == TcpAction.VoiceAction.CANCEL) {
+                    //对方呼叫时取消
+                    MediaPlayHelper.getInstance().stopMusic()
+                    cancelCall()
+                }
+            }
+        }
+    }
+
+    //呼叫
+    fun sendCall() {
+        Constant.CALL_STATE = Constant.CALL_OUTGOING
+        voice_call_calling_text.setText("正在呼叫...")
+        voice_call_hangup_view.visibility = View.VISIBLE
+        voice_call_ring_view.visibility = View.GONE
+        voice_call_timer.visibility = View.GONE
+        voice_call_timeout.visibility = View.VISIBLE
+        countDownTimer.start()
+    }
+
+    //来电
+    fun incomingCall() {
+        Constant.CALL_STATE = Constant.CALL_INCOMING
+        countDownTimer.cancel()
+        voice_call_calling_text.setText("有新的来电...")
+        voice_call_hangup_view.visibility = View.GONE
+        voice_call_ring_view.visibility = View.VISIBLE
+        voice_call_timer.visibility = View.GONE
+        voice_call_timeout.visibility = View.GONE
+    }
+
+    //接通
+    fun acceptCall() {
+        Constant.CALL_STATE = Constant.CALL_CALLING
+        countDownTimer.cancel()
+        voice_call_calling_text.setText("通话中...")
+        voice_call_hangup_view.visibility = View.VISIBLE
+        voice_call_ring_view.visibility = View.GONE
+        voice_call_timer.visibility = View.VISIBLE
+        voice_call_timeout.visibility = View.GONE
+        voice_call_timer.base = SystemClock.elapsedRealtime()
+        voice_call_timer.start()
+    }
+
+    //挂断通话
+    fun rejectCall() {
+        Constant.CALL_STATE = Constant.CALL_STANDBY
+        countDownTimer.cancel()
+        voice_call_timer.base = SystemClock.elapsedRealtime()
+        voice_call_timer.stop()
+        backToMain()
+    }
+
+    //呼叫取消
+    fun cancelCall() {
+        Constant.CALL_STATE = Constant.CALL_STANDBY
+        countDownTimer.cancel()
+        voice_call_timer.base = SystemClock.elapsedRealtime()
+        voice_call_timer.stop()
+        backToMain()
+    }
+
+    private fun backToMain() {
+        EventBus.getDefault().post(MessageEvent("BackToMain", Constant.EVENT_BACK_MAIN))
+    }
+}

+ 101 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/fragment/CostFragment.kt

@@ -0,0 +1,101 @@
+package com.wdkl.app.ncs.callingbed2.fragment
+
+import android.support.v7.widget.LinearLayoutManager
+import com.enation.javashop.net.engine.model.NetState
+import com.wdkl.app.ncs.callingbed2.R
+import com.wdkl.app.ncs.callingbed2.adapter.CostItemAdapter
+import com.wdkl.app.ncs.callingbed2.databinding.CostViewLayBinding
+import com.wdkl.app.ncs.callingbed2.launch.Callingbed2Launch
+import com.wdkl.ncs.android.lib.base.BaseFragment
+import com.wdkl.ncs.android.lib.utils.errorLog
+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.logic.contract.callingbed2.CostFragmentContract
+import com.wdkl.ncs.android.middleware.logic.presenter.callingbed2.CostFragmentPresenter
+import com.wdkl.ncs.android.middleware.model.vo.CustomerFeeConfigByGroupNameVO
+import com.wdkl.ncs.android.middleware.model.vo.CustomerFeeConfigVO
+import kotlinx.android.synthetic.main.cost_view_lay.*
+
+class CostFragment : BaseFragment<CostFragmentPresenter, CostViewLayBinding>(), CostFragmentContract.View {
+
+    override fun getLayId(): Int {
+        return R.layout.cost_view_lay
+    }
+
+    override fun bindDagger() {
+        Callingbed2Launch.component.inject(this)
+    }
+
+    override fun init() {
+        if (Constant.CUSTOM_ID != -1) {
+            presenter.loadCustomCost(Constant.CUSTOM_ID)
+        } else {
+            showMessage("no custom id")
+        }
+
+
+        //test
+        /*val feeConfigList = ArrayList<CustomerFeeConfigVO>()
+        val feeConfig = CustomerFeeConfigVO()
+        feeConfig.feeName = "阿莫西林胶囊"
+        feeConfig.feeValue = 20.0
+        feeConfig.keyCode = "E0012"
+        feeConfig.unit = "1"
+        feeConfigList.add(feeConfig)
+
+        val feeCostList = ArrayList<CustomerFeeConfigByGroupNameVO>()
+        val feeCost = CustomerFeeConfigByGroupNameVO()
+        feeCost.feeGroupName = "西药"
+        feeCost.subtotal = 20.0
+        feeCost.customerFeeConfigList = feeConfigList
+        feeCostList.add(feeCost)
+
+        val layoutManager = LinearLayoutManager(activity)
+        rv_cost_main_view.layoutManager = layoutManager
+        rv_cost_main_view.adapter = CostItemAdapter(activity, feeCostList)*/
+    }
+
+    override fun bindEvent() {
+        //
+    }
+
+    override fun destory() {
+        //
+    }
+
+    override fun showCustomCost(cost: ArrayList<CustomerFeeConfigByGroupNameVO>) {
+        val layoutManager = LinearLayoutManager(activity)
+        rv_cost_main_view.layoutManager = layoutManager
+        rv_cost_main_view.adapter = CostItemAdapter(activity, cost)
+    }
+
+    override fun showCustomCost2(customFees: ArrayList<CustomerFeeConfigVO>) {
+        //
+    }
+
+    override fun onError(message: String, type: Int) {
+        //errorLog("error",message)
+        showMessage(message)
+    }
+
+    override fun onNoNet() {
+        showMessage("none network")
+    }
+
+    override fun complete(message: String, type: Int) {
+    }
+
+    override fun start() {
+    }
+
+    override fun networkMonitor(state: NetState) {
+        state.filter(onWifi = {
+
+        },onMobile = {
+
+        },offline = {
+
+        })
+    }
+}

+ 112 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/fragment/CostFragment2.kt

@@ -0,0 +1,112 @@
+package com.wdkl.app.ncs.callingbed2.fragment
+
+import android.support.v7.widget.LinearLayoutManager
+import com.enation.javashop.net.engine.model.NetState
+import com.wdkl.app.ncs.callingbed2.R
+import com.wdkl.app.ncs.callingbed2.adapter.CostItemAdapter2
+import com.wdkl.app.ncs.callingbed2.databinding.CostViewLayBinding
+import com.wdkl.app.ncs.callingbed2.launch.Callingbed2Launch
+import com.wdkl.ncs.android.lib.base.BaseFragment
+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.logic.contract.callingbed2.CostFragmentContract
+import com.wdkl.ncs.android.middleware.logic.presenter.callingbed2.CostFragmentPresenter
+import com.wdkl.ncs.android.middleware.model.vo.CustomerFeeConfigByGroupNameVO
+import com.wdkl.ncs.android.middleware.model.vo.CustomerFeeConfigVO
+import kotlinx.android.synthetic.main.cost_view_lay.*
+
+class CostFragment2 : BaseFragment<CostFragmentPresenter, CostViewLayBinding>(), CostFragmentContract.View {
+
+    private var pageNo = 1
+    private lateinit var adapter: CostItemAdapter2
+
+    override fun getLayId(): Int {
+        return R.layout.cost_view_lay
+    }
+
+    override fun bindDagger() {
+        Callingbed2Launch.component.inject(this)
+    }
+
+    override fun init() {
+        adapter = CostItemAdapter2(activity, ArrayList())
+        val layoutManager = LinearLayoutManager(activity)
+        rv_cost_main_view.layoutManager = layoutManager
+        rv_cost_main_view.adapter = adapter
+
+        if (Constant.CUSTOM_ID != -1) {
+            presenter.loadCustomCostByPage(pageNo, 10, Constant.CUSTOM_ID)
+        } else {
+            showMessage("no custom id")
+        }
+    }
+
+    override fun bindEvent() {
+        cost_refresh.setOnRefreshListener {
+            if (Constant.CUSTOM_ID != -1) {
+                pageNo = 1
+                presenter.loadCustomCostByPage(pageNo, 10, Constant.CUSTOM_ID)
+            } else {
+                showMessage("no custom id")
+            }
+        }
+
+        cost_refresh.setOnLoadMoreListener {
+            if (Constant.CUSTOM_ID != -1) {
+                pageNo += 1
+                presenter.loadCustomCostByPage(pageNo, 10, Constant.CUSTOM_ID)
+            } else {
+                showMessage("no custom id")
+            }
+        }
+    }
+
+    override fun destory() {
+        //
+    }
+
+    override fun showCustomCost(cost: ArrayList<CustomerFeeConfigByGroupNameVO>) {
+        //
+    }
+
+    override fun showCustomCost2(customFees: ArrayList<CustomerFeeConfigVO>) {
+        cost_refresh.finishRefresh()
+        cost_refresh.finishLoadMore()
+
+        if (pageNo == 1) {
+            adapter.updateCostData(customFees, true)
+        } else {
+            adapter.updateCostData(customFees, false)
+        }
+    }
+
+    override fun onError(message: String, type: Int) {
+        //errorLog("error",message)
+        showMessage(message)
+        cost_refresh.finishRefresh()
+        cost_refresh.finishLoadMore()
+    }
+
+    override fun onNoNet() {
+        showMessage("none network")
+        cost_refresh.finishRefresh()
+        cost_refresh.finishLoadMore()
+    }
+
+    override fun complete(message: String, type: Int) {
+    }
+
+    override fun start() {
+    }
+
+    override fun networkMonitor(state: NetState) {
+        state.filter(onWifi = {
+
+        },onMobile = {
+
+        },offline = {
+
+        })
+    }
+}

+ 195 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/fragment/MainFragment.kt

@@ -0,0 +1,195 @@
+package com.wdkl.app.ncs.callingbed2.fragment
+
+import android.graphics.Color
+import android.text.TextUtils
+import android.text.method.ScrollingMovementMethod
+import android.view.View
+import com.enation.javashop.net.engine.model.NetState
+import com.wdkl.app.ncs.callingbed2.BuildConfig
+import com.wdkl.app.ncs.callingbed2.R
+import com.wdkl.app.ncs.callingbed2.activity.Callingbed2Activity
+import com.wdkl.app.ncs.callingbed2.databinding.MainView2LayoutBinding
+import com.wdkl.app.ncs.callingbed2.helper.HttpHelper
+import com.wdkl.app.ncs.callingbed2.launch.Callingbed2Launch
+import com.wdkl.ncs.android.lib.base.BaseFragment
+import com.wdkl.ncs.android.lib.utils.*
+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.callingbed2.MainFragmentContract
+import com.wdkl.ncs.android.middleware.logic.presenter.callingbed2.MainFragmentPresenter
+import com.wdkl.ncs.android.middleware.model.dos.EventDO
+import com.wdkl.ncs.android.middleware.model.dto.NurseConfigDto
+import com.wdkl.ncs.android.middleware.model.vo.CustomerInfoVO
+import com.wdkl.ncs.android.middleware.utils.StringUtil
+import kotlinx.android.synthetic.main.main_view2_layout.*
+import kotlinx.android.synthetic.main.view_bed_name.*
+import org.greenrobot.eventbus.EventBus
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+
+class MainFragment: BaseFragment<MainFragmentPresenter, MainView2LayoutBinding>(), MainFragmentContract.View {
+    val TAG = "MainFragment"
+
+
+    override fun getLayId(): Int {
+        return R.layout.main_view2_layout
+    }
+
+    override fun bindDagger() {
+        Callingbed2Launch.component.inject(this)
+    }
+
+    override fun init() {
+        //医嘱内容可以滚动显示
+        tv_order_content.movementMethod = ScrollingMovementMethod.getInstance()
+        tv_version.text = "V"+ BuildConfig.VERSION_NAME+"_"+BuildConfig.VERSION_CODE
+
+        updateInfo()
+    }
+
+    override fun bindEvent() {
+    }
+
+    override fun destory() {
+    }
+
+    override fun showCustomInfo(customInfo: CustomerInfoVO) {
+        //隐藏空页面并展示入住信息
+        ll_empty.visibility = View.GONE
+        ll_custom_view.visibility = View.VISIBLE
+
+        //显示入住信息
+        tv_custom_name.text = customInfo.named
+        if (customInfo.sex == 0) {
+            tv_custom_gender.setBackgroundResource(R.mipmap.ic_gender_female)
+        } else if (customInfo.sex == 1) {
+            tv_custom_gender.setBackgroundResource(R.mipmap.ic_gender_male)
+        }
+        tv_custom_age.text = "" + customInfo.age + customInfo.ageUnit
+        if (customInfo.inDate != null) {
+            tv_custom_indate.text = StringUtil.getResString(R.string.indate) + TimeHandle.getDateTime(customInfo.inDate * 1000, "yyyy.MM.dd")
+        }
+        if (TextUtils.isEmpty(customInfo.advice)) {
+            tv_order_content.text = StringUtil.getResString(R.string.str_empty)
+        } else {
+            tv_order_content.text = customInfo.advice
+        }
+
+        if (Constant.doctorValid == 1) {
+            ll_doctor_view.visibility = View.VISIBLE
+            tv_doctor_title.text = Constant.doctorTitle
+        } else {
+            ll_doctor_view.visibility = View.GONE
+        }
+
+        if (Constant.nurseValid == 1) {
+            ll_nurse_view.visibility = View.VISIBLE
+            tv_nurse_title.text = Constant.nurseTitle
+        } else {
+            ll_nurse_view.visibility = View.GONE
+        }
+        tv_doctor_name.text = customInfo.doctorName
+        tv_nurse_name.text = customInfo.nurseName
+
+        //更新护理项
+        if (customInfo.list != null) {
+            AppTool.Time.delay(1800) {
+                if (activity != null) {
+                    (activity as Callingbed2Activity).updateNurseConfig(customInfo.list)
+                }
+            }
+
+            updateMoreConfigs(customInfo.list)
+        }
+    }
+
+    override fun onError(message: String, type: Int) {
+        //errorLog("error",message)
+        showMessage(message)
+    }
+
+    override fun onNoNet() {
+        showMessage("none network")
+    }
+
+    override fun complete(message: String, type: Int) {
+    }
+
+    override fun start() {
+    }
+
+    override fun networkMonitor(state: NetState) {
+        state.filter(onWifi = {
+
+        },onMobile = {
+
+        },offline = {
+
+        })
+    }
+
+    override fun onStart() {
+        EventBus.getDefault().register(this)
+        super.onStart()
+    }
+
+    override fun onStop() {
+        EventBus.getDefault().unregister(this)
+        super.onStop()
+    }
+
+    private fun updateInfo() {
+        if (Constant.DEVICE_STATUS == 0) {
+            tv_bed_name.setText(R.string.device_disable)
+            tv_bed_name.setTextColor(resources.getColor(R.color.red_color))
+        } else {
+            tv_bed_name.text = Constant.BED_NAME
+            tv_bed_name.setTextColor(resources.getColor(R.color.main_color))
+        }
+
+        if (Constant.CUSTOM_ID != -1) {
+            ll_empty.visibility = View.GONE
+            presenter.loadCustomInfo(Constant.CUSTOM_ID)
+        }
+    }
+
+    private fun updateMoreConfigs(data: List<NurseConfigDto>) {
+        if (data.size > 5) {
+            ll_nurse_more.visibility = View.VISIBLE
+            if (data.size == 6) {
+                ll_nurse_item6.setBackgroundColor(Color.parseColor("#"+data[5].nurseColorRbg))
+                tv_nurse_name6.text = data[5].nurseConfigName
+                tv_nurse_value6.text = data[5].nurseOptionName
+            } else if (data.size == 7) {
+                ll_nurse_item6.setBackgroundColor(Color.parseColor("#"+data[5].nurseColorRbg))
+                tv_nurse_name6.text = data[5].nurseConfigName
+                tv_nurse_value6.text = data[5].nurseOptionName
+                ll_nurse_item7.setBackgroundColor(Color.parseColor("#"+data[6].nurseColorRbg))
+                tv_nurse_name7.text = data[6].nurseConfigName
+                tv_nurse_value7.text = data[6].nurseOptionName
+            } else if (data.size >= 8) {
+                ll_nurse_item6.setBackgroundColor(Color.parseColor("#"+data[5].nurseColorRbg))
+                tv_nurse_name6.text = data[5].nurseConfigName
+                tv_nurse_value6.text = data[5].nurseOptionName
+                ll_nurse_item7.setBackgroundColor(Color.parseColor("#"+data[6].nurseColorRbg))
+                tv_nurse_name7.text = data[6].nurseConfigName
+                tv_nurse_value7.text = data[6].nurseOptionName
+                ll_nurse_item8.setBackgroundColor(Color.parseColor("#"+data[7].nurseColorRbg))
+                tv_nurse_name8.text = data[7].nurseConfigName
+                tv_nurse_value8.text = data[7].nurseOptionName
+            }
+        } else {
+            ll_nurse_more.visibility = View.GONE
+        }
+    }
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    fun onMoonEvent(messageEvent: MessageEvent) {
+        when (messageEvent.getType()) {
+            Constant.EVENT_UPDATE_CUSTOM -> {
+                updateInfo()
+            }
+        }
+    }
+}

+ 301 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/fragment/QrCodeFragment.kt

@@ -0,0 +1,301 @@
+package com.wdkl.app.ncs.callingbed2.fragment
+
+import android.content.Intent
+import android.hardware.Camera
+import android.os.Build
+import android.provider.Settings
+import android.text.method.ScrollingMovementMethod
+import android.util.DisplayMetrics
+import android.view.SurfaceHolder
+import android.view.View
+import android.view.WindowManager
+import com.enation.javashop.net.engine.model.NetState
+import com.wdkl.app.ncs.callingbed2.BuildConfig
+import com.wdkl.app.ncs.callingbed2.R
+import com.wdkl.app.ncs.callingbed2.activity.Callingbed2Activity
+import com.wdkl.app.ncs.callingbed2.databinding.QrCodeLayBinding
+import com.wdkl.app.ncs.callingbed2.helper.*
+import com.wdkl.app.ncs.callingbed2.launch.Callingbed2Launch
+import com.wdkl.ncs.android.lib.base.BaseFragment
+import com.wdkl.ncs.android.lib.utils.*
+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.logic.contract.callingbed2.QrCodeFragmentContract
+import com.wdkl.ncs.android.middleware.logic.presenter.callingbed2.QrCodeFragmentPresenter
+import com.wdkl.ncs.android.middleware.utils.StringUtil
+import kotlinx.android.synthetic.main.qr_code_lay.*
+import kotlinx.android.synthetic.main.view_bed_name.*
+import java.io.DataOutputStream
+import java.io.IOException
+
+class QrCodeFragment : BaseFragment<QrCodeFragmentPresenter, QrCodeLayBinding>(), QrCodeFragmentContract.View {
+    val TAG = "QrCodeFragment"
+
+    val QR_CODE_PATH = "http://m.wdklian.com/care/apk/care.user?type=NCS_DEVICE"
+
+    private var mCamera: Camera? = null
+
+    private var clickTime: Long = 0
+    private var clickTimes: Int = 1
+
+    override fun getLayId(): Int {
+        return R.layout.qr_code_lay
+    }
+
+    override fun bindDagger() {
+        Callingbed2Launch.component.inject(this)
+    }
+
+    override fun init() {
+        if (Constant.DEVICE_STATUS == 0) {
+            tv_bed_name.setText(R.string.device_disable)
+            tv_bed_name.setTextColor(resources.getColor(R.color.red_color))
+        } else {
+            tv_bed_name.text = Constant.BED_NAME
+            tv_bed_name.setTextColor(resources.getColor(R.color.main_color))
+        }
+
+        tv_version.text = "V"+BuildConfig.VERSION_NAME+"_"+BuildConfig.VERSION_CODE
+
+        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.LOCAL_MAC)
+            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(Constant.DEVICE_TYPE)
+            builder.append("&device_name=")
+            builder.append(Constant.DEVICE_NAME)
+            val code = EcodeHelper().createQRImage(builder.toString(),200, null)
+            activity.runOnUiThread {
+                view_qr_code?.setImageBitmap(code)
+            }
+        }.start()
+        //val macAddr = NetHelper.getInstance().macAddress
+        val ipAddr = NetHelper.getInstance().localIP
+        if (Constant.DEVICE_STATUS == 0) {
+            tv_device_id.text = "Device ID: " + Constant.DEVICE_ID + " - " + StringUtil.getResString(R.string.str_disable)
+        } else if (Constant.DEVICE_STATUS == 1) {
+            tv_device_id.text = "Device ID: " + Constant.DEVICE_ID + " - " + StringUtil.getResString(R.string.str_enable)
+        } else {
+            tv_device_id.text = "Device ID: " + Constant.DEVICE_ID
+        }
+
+        val serverIp =  UrlManager.build().base.substringAfterLast("//").substringBefore(":")
+        tv_local_ip.text = "IP: " + ipAddr + " - " + serverIp
+        tv_local_mac.text = "MAC: " + Constant.LOCAL_MAC
+        tv_app_version.text = "Version: V" + BuildConfig.VERSION_NAME + "_" + BuildConfig.VERSION_CODE + "_" + Build.MODEL + "\r\nAndroid SDK: " + Build.VERSION.SDK_INT
+
+        val wmanager: WindowManager = activity.windowManager
+        val dm = DisplayMetrics()
+        wmanager.getDefaultDisplay().getMetrics(dm)
+        if ("rk3128".equals(Build.MODEL)) {
+            //tv_screen_param.text = "屏幕参数: 7寸IPS彩色液晶屏,分辨率" + dm.widthPixels + "x" + dm.heightPixels
+            tv_mcu_version.text = "MCU: " + Constant.MCU_VERSION_NUMBER
+        }
+
+        tv_about_me.movementMethod = ScrollingMovementMethod.getInstance()
+
+        if ("rk3128".equals(Build.MODEL)) {
+            if (Constant.CUSTOM_ID == -1) {
+                tv_device_test.visibility = View.VISIBLE
+            } else {
+                tv_device_test.visibility = View.GONE
+            }
+        } else {
+            tv_device_test.visibility = View.GONE
+        }
+    }
+
+    override fun bindEvent() {
+        tv_btn_update_app.setOnClickListener {
+            (activity as Callingbed2Activity).checkAppVersion()
+        }
+
+        tv_btn_reboot.setOnClickListener {
+            AppUpdateHelper.reboot(context, false)
+        }
+
+        //长按二维码启动camera预览
+        view_qr_code.setOnLongClickListener {
+            if (Constant.supportCamera) {
+                if (frame_camera_view.visibility == View.GONE) {
+                    frame_camera_view.visibility = View.VISIBLE
+                    startCameraPreview()
+                }
+            } else {
+                showMessage(R.string.str_no_camera)
+            }
+            return@setOnLongClickListener true
+        }
+
+        view_qr_code.setOnClickListener {
+            val time = System.currentTimeMillis()
+            if (time - clickTime < 1500) {
+                clickTimes++
+            } else {
+                clickTimes = 1
+            }
+
+            if (clickTimes > 9) {
+                openNetwrokDebug()
+                clickTimes = 1
+            }
+            clickTime = time
+        }
+
+        //点击10次床位textview进入系统设置
+        tv_bed_name.setOnClickListener {
+            val time = System.currentTimeMillis()
+            if (time - clickTime < 1500) {
+                clickTimes++
+            } else {
+                clickTimes = 1
+            }
+
+            if (clickTimes == 5) {
+                showMessage(R.string.enter_settings_tips)
+            }
+            if (clickTimes > 9) {
+                val intent = Intent(Settings.ACTION_SETTINGS)
+                startActivity(intent)
+                clickTimes = 1
+            }
+            clickTime = time
+        }
+
+        tv_btn_server_config.setOnClickListener {
+            ServerConfigDialogHelper.showPasswordDialog(activity)
+        }
+
+        tv_device_test.setOnClickListener {
+            PasswordDialogHelper.showPasswordDialog(activity) {
+                (activity as Callingbed2Activity).startTestMode()
+            }
+        }
+
+        tv_btn_language_setting.setOnClickListener {
+            LanguageSetDialogHelper.showDialog(activity)
+        }
+    }
+
+    //开启网络调试
+    private fun openNetwrokDebug() {
+        val commands = arrayListOf(
+            "/system/bin/sh",
+            "setprop service.adb.tcp.port 5555",
+            "stop adbd",
+            "start adbd"
+        )
+        try {
+            RunAsRoot(commands)
+            showMessage(R.string.enable_debug)
+        } catch (e: IOException) {
+            e.printStackTrace()
+        }
+    }
+
+    private fun RunAsRoot(cmds: ArrayList<String>) {
+        val p = Runtime.getRuntime().exec("su")
+        val os = DataOutputStream(p.outputStream)
+        for (tmpCmd in cmds) {
+            os.writeBytes(
+                """
+            $tmpCmd
+            
+            """.trimIndent()
+            )
+        }
+        os.writeBytes("exit\n")
+        os.flush()
+    }
+
+    private fun startCameraPreview() {
+        val num = Camera.getNumberOfCameras()
+        if (num > 0) {
+            try {
+                mCamera = Camera.open()
+            } catch (e: Exception) {
+                showMessage(R.string.str_open_camera_failed)
+                e.printStackTrace()
+            }
+
+            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 destory() {
+        if (mCamera != null) {
+            mCamera!!.stopPreview()
+            mCamera!!.release()
+            mCamera = null
+        }
+    }
+
+    override fun onError(message: String, type: Int) {
+        showMessage(message)
+    }
+
+    override fun complete(message: String, type: Int) {
+    }
+
+    override fun start() {
+    }
+
+    override fun networkMonitor(state: NetState) {
+        state.filter(onWifi = {
+
+        },onMobile = {
+
+        },offline = {
+
+        })
+    }
+
+    override fun setUrlString(url: String) {
+        //
+    }
+}

+ 630 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/fragment/SkyCallFragment.kt

@@ -0,0 +1,630 @@
+package com.wdkl.app.ncs.callingbed2.fragment
+
+import android.os.Handler
+import android.os.Looper
+import android.os.SystemClock
+import android.text.TextUtils
+import android.util.Log
+import android.view.View
+import android.view.ViewGroup
+import com.google.gson.Gson
+import com.wdkl.app.ncs.callingbed2.R
+import com.wdkl.app.ncs.callingbed2.helper.RingPlayHelper
+import com.wdkl.app.ncs.callingbed2.helper.SerialPortHelper
+import com.wdkl.app.ncs.callingbed2.helper.VoiceManagerUtil
+import com.wdkl.app.ncs.callingbed2.settings.SettingConfig
+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.channel.VideoUtil
+import com.wdkl.ncs.android.middleware.tcp.channel.VoiceUtil
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel
+import com.wdkl.ncs.android.middleware.tcp.enums.TcpAction
+import com.wdkl.ncs.android.middleware.tcp.enums.TcpType
+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"
+
+    //来电设备id
+    var fromId: Int = -1
+
+    private var interactionVO: InteractionVO? = null
+
+    private var localSurfaceView: SurfaceViewRenderer? = null
+    private var remoteSurfaceView: SurfaceViewRenderer? = null
+
+    private var janusClient: JanusClient? = null
+    private var room: Room?=null
+    private var videoRoomCallback: VideoRoomCallback? = null
+
+    private val handler = Handler(Looper.getMainLooper())
+
+    private var visiting: Boolean = false
+    private var audioCall: Boolean = true
+    private var callEnded: Boolean = false
+    private var outGoing: Boolean = false
+    private var callSuccess: Boolean = false
+
+    private var janusInit = false
+
+    override fun getLayId(): Int {
+        return R.layout.sky_voice_call_layout
+    }
+
+    override fun init() {
+        //初始化计时器
+        initCountDownTimer(sky_voice_call_timeout)
+        //tcp参数
+        if (tcpModel != null) {
+            fromId = tcpModel!!.fromId
+            interactionVO = Gson().fromJson(tcpModel!!.data.toString(), InteractionVO::class.java)
+        }
+
+        //判断是否有广播在播放
+        if (bcPlay) {
+            handler.postDelayed({
+                janusInit()
+            }, 2000)
+        } else {
+            janusInit()
+        }
+    }
+
+    private fun janusInit() {
+        //初始化 engine
+        if (Constant.CALL_TYPE == Constant.VIDEO_CALL) {
+            audioCall = false
+            WebRTCEngine.getInstance().init(false, this.context)
+        } else {
+            audioCall = true
+            WebRTCEngine.getInstance().init(true, this.context)
+        }
+
+        VoiceManagerUtil.setCallVoice(activity, SettingConfig.getExtensionCallVolume(activity))
+
+        //初始化 janusClient
+        janusClient = JanusClient(JanusConstant.JANUS_URL, Constant.SIP_ID.toBigInteger())
+
+        when (callState) {
+            0 -> {
+                //去电
+                outGoing = true
+                startOutgoing()
+                RingPlayHelper.playRingTone(baseActivity, R.raw.ring_back2, true)
+
+                janusClient!!.callState = EnumType.CallState.Outgoing
+                room = Room(Constant.SIP_ID.toBigInteger())
+            }
+
+            1 -> {
+                //来电
+                outGoing = false
+                showIncomingCall()
+
+                janusClient!!.callState = EnumType.CallState.Incoming
+                room = Room(Constant.TARGET_SIP.toBigInteger())
+
+                if (SettingConfig.getAutoAnswer(activity)) {
+                    //自动接听
+                    handler.postDelayed({
+                        if (!callEnded && Constant.CALL_STATE != Constant.CALL_CALLING) {
+                            RingPlayHelper.stopRingTone()
+                            VoiceUtil.acceptAudioCall(Constant.DEVICE_ID, fromId, interactionVO?.id)
+                            acceptCall()
+                            janusClient!!.connect(-1, false)
+                        }
+                    }, 1500)
+                } else {
+                    RingPlayHelper.playRingTone(baseActivity, R.raw.ring_tone, true)
+                }
+            }
+
+            2 -> {
+                //探视
+                outGoing = false
+                visiting = true
+                acceptCall()
+
+                janusClient!!.callState = EnumType.CallState.Incoming
+                room = Room(interactionVO!!.fromSipId.toBigInteger())
+            }
+        }
+
+        videoRoomCallback = VideoRoomCallback(janusClient, room, Constant.SIP_ID.toBigInteger())
+        videoRoomCallback!!.callSessionCallback = this
+        janusClient!!.setJanusCallback(videoRoomCallback)
+
+        if (visiting) {
+            janusClient!!.connect(-1, false)
+        }
+
+        janusInit = true
+    }
+
+    override fun bindEvent() {
+        //去电取消或通话挂断
+        sky_voice_call_hangup.setOnClickListener {
+            RingPlayHelper.stopRingTone()
+            if (Constant.CALL_STATE == Constant.CALL_CALLING) {
+                //结束sip通话
+                Constant.CALL_STATE = Constant.CALL_STANDBY
+                sky_voice_call_timer.stop()
+
+                callEnd(true)
+            } else {
+                Constant.CALL_STATE = Constant.CALL_STANDBY
+                VoiceUtil.cancelAudioCall(Constant.DEVICE_ID)
+                cancelCall()
+            }
+        }
+
+        //来电拒绝
+        sky_voice_call_ring_reject.setOnClickListener {
+            RingPlayHelper.stopRingTone()
+            Constant.CALL_STATE = Constant.CALL_STANDBY
+            VoiceUtil.rejectAudioCall(Constant.DEVICE_ID, fromId, interactionVO?.id)
+            callEnd(false)
+        }
+
+        //来电接听
+        sky_voice_call_ring_pickup_audio.setOnClickListener {
+            RingPlayHelper.stopRingTone()
+            Constant.CALL_STATE = Constant.CALL_INCOMING
+            VoiceUtil.acceptAudioCall(Constant.DEVICE_ID, fromId, interactionVO?.id)
+            acceptCall()
+            janusClient!!.connect(-1, false)
+        }
+    }
+
+    override fun destroy() {
+        cancelTimer()
+        Constant.CALL_STATE = Constant.CALL_STANDBY
+        if (sky_voice_call_timer != null) {
+            sky_voice_call_timer.stop()
+        }
+        RingPlayHelper.stopRingTone()
+        SerialPortHelper.setCallStatus("0")
+        handler.removeCallbacksAndMessages(null)
+    }
+
+    private fun startOutgoing() {
+        callSuccess = false
+        sky_voice_call_hangup.isEnabled = false
+        if (Constant.CALL_TYPE == Constant.VIDEO_CALL) {
+            VoiceUtil.startVideoCall(Constant.DEVICE_ID)
+        } else {
+            VoiceUtil.startAudioCall(Constant.DEVICE_ID)
+        }
+
+        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(R.string.call_fail)
+                RingPlayHelper.stopRingTone()
+                cancelCall()
+            }
+        }
+    }
+
+    //去电界面
+    private fun showOutgoingCall() {
+        Constant.CALL_STATE = Constant.CALL_OUTGOING
+        sky_voice_call_calling_text.setText(R.string.call_success)
+        sky_voice_call_outgoing.visibility = View.VISIBLE
+        sky_voice_call_incoming.visibility = View.GONE
+        sky_voice_call_timeout.visibility = View.VISIBLE
+        sky_voice_call_timer.visibility = View.GONE
+        SerialPortHelper.setCallStatus("1")
+
+        if (!audioCall) {
+            //显示视频画面
+            fullscreen_video_frame.visibility = View.VISIBLE
+            pip_video_frame.visibility = View.VISIBLE
+        }
+    }
+
+    //来电界面
+    private fun showIncomingCall() {
+        Constant.CALL_STATE = Constant.CALL_INCOMING
+        sky_voice_call_calling_text.setText(R.string.call_incoming)
+        sky_voice_call_outgoing.visibility = View.GONE
+        if (SettingConfig.getAutoAnswer(activity)) {
+            sky_voice_call_incoming.visibility = View.GONE
+        } else {
+            sky_voice_call_incoming.visibility = View.VISIBLE
+        }
+
+        sky_voice_call_timeout.visibility = View.GONE
+        sky_voice_call_timer.visibility = View.GONE
+        SerialPortHelper.setCallStatus("1")
+    }
+
+    //开始接听
+    private fun acceptCall() {
+        sky_voice_call_calling_text.setText(R.string.call_connecting)
+        sky_voice_call_outgoing.visibility = View.VISIBLE
+        sky_voice_call_incoming.visibility = View.GONE
+        sky_voice_call_timeout.visibility = View.GONE
+        sky_voice_call_timer.visibility = View.GONE
+        cancelTimer()
+    }
+
+    //呼叫取消
+    private fun cancelCall() {
+        cancelTimer()
+        Constant.CALL_STATE = Constant.CALL_STANDBY
+        SerialPortHelper.setCallStatus("0")
+        callEnd(false)
+    }
+
+    private fun showCalling(audioOnly: Boolean) {
+        if (callEnded) {
+            return
+        }
+
+        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
+        }
+
+        Constant.CALL_STATE = Constant.CALL_CALLING
+        sky_voice_call_calling_text.setText(R.string.call_in_call)
+        sky_voice_call_timeout.visibility = View.GONE
+        cancelTimer()
+        sky_voice_call_timer.visibility = View.VISIBLE
+        sky_voice_call_timer.base = SystemClock.elapsedRealtime()
+        sky_voice_call_timer.start()
+
+        //通话时关闭指示灯,防止热量太高导致设备重启
+        SerialPortHelper.setCallStatus("0")
+    }
+
+    override fun callEnd(handoff: Boolean) {
+        synchronized(this) {
+            if (callEnded) {
+                return
+            }
+            callEnded = true
+            Constant.CALL_STATE = Constant.CALL_STANDBY
+            if (sky_voice_call_timer != null) {
+                sky_voice_call_timer.stop()
+            }
+
+            Log.e(TAG, "call end !!!!!!!!!!!!!!!!!!")
+            if (handoff) {
+                if (visiting) {
+                    VideoUtil.handoffVideoCall(Constant.DEVICE_ID, fromId, interactionVO?.id)
+                } else {
+                    VoiceUtil.handoffAudioCall(Constant.DEVICE_ID, fromId, interactionVO?.id)
+                }
+            }
+
+            if (janusInit) {
+                if (janusClient!!.webSocketChannel != null) {
+                    janusClient!!.callState = EnumType.CallState.Idle
+                    if (callState == 0) {
+                        janusClient!!.destroyRoom(janusClient!!.currentHandleId, null)
+                    } else {
+                        janusClient!!.leaveRoom()
+                    }
+
+                    janusClient!!.setJanusCallback(null)
+                    janusClient!!.disConnect()
+                }
+            }
+
+            backToMain()
+        }
+    }
+
+
+    /********************************************************
+     ********************* webrtc通话回调 ********************
+     * 注意: 如涉及到UI更新的需要在主线程处理,务必注意
+     *******************************************************/
+    override fun didChangeState(var1: EnumType.CallState?) {
+        Log.e(TAG, "didChangeState: $var1")
+        if (var1 == EnumType.CallState.Connected) {
+            handler.post {
+                RingPlayHelper.stopRingTone()
+                //更新界面显示
+                showCalling(audioCall)
+
+                if (!outGoing) {
+                    //被叫接听时开始录音录像
+                    if (SettingConfig.getRecordEnable(activity)) {
+                        janusClient!!.beginRecord()
+                    }
+                }
+            }
+        }
+    }
+
+    override fun didDisconnected(userId: String?) {
+        Log.i(TAG, "disconnected user:" + userId + ",call user:" + Constant.TARGET_SIP)
+        if (userId.equals(Constant.TARGET_SIP)) {
+            Log.w(TAG, "didDisconnected: $userId")
+            handler.post {
+                showMessage("$userId disconnected")
+                callEnd(true)
+            }
+        }
+    }
+
+    override fun didError(error: String?) {
+        Log.e(TAG, "didError: $error")
+        handler.post {
+            showMessage(R.string.call_error)
+            callEnd(true)
+        }
+    }
+
+    override fun didHangUp(handlerId: BigInteger?) {
+        Log.e("hangup", "socket hangup")
+        handler.post {
+            callEnd(true)
+        }
+    }
+
+    //处理本地视频画面
+    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 (outGoing && remoteSurfaceView == null) {
+                    if (fullscreen_video_frame != null) {
+                        if (fullscreen_video_frame.getChildCount() != 0) {
+                            fullscreen_video_frame.removeAllViews()
+                        }
+                        fullscreen_video_frame.addView(localSurfaceView)
+                    }
+                } else {
+                    if (pip_video_frame != null) {
+                        if (pip_video_frame.getChildCount() != 0) {
+                            pip_video_frame.removeAllViews()
+                        }
+                        pip_video_frame.addView(localSurfaceView)
+                    }
+                }
+            }
+        }
+    }
+
+    override fun didReceiveRemoteVideoTrack(userId: BigInteger?) {
+        Log.e(TAG, "didReceiveRemoteVideoTrack  userId: $userId")
+        handler.post {
+            if (!callEnded) {
+                if (visiting) {
+                    if (Constant.visitId!!.toBigInteger() == userId) {
+                        //显示探视机和本机画面
+                        Log.e(TAG, "didReceiveRemoteVideoTrack, local visit 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 visit 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 {
+                    //本地画面
+                    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)
+                    }
+                }
+            }
+        }
+    }
+
+    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) {
+        when (messageEvent.type) {
+            Constant.EVENT_TCP_MSG -> {
+                if (messageEvent.message is TcpModel) {
+                    val curTcpModel = messageEvent.message as TcpModel
+                    if (curTcpModel.getType() == TcpType.VOICE) {
+                        if (curTcpModel.action == TcpAction.VoiceAction.CANCEL_BY_DOOR) {
+                            //如果当前正在通话中则不做取消处理
+                            if (Constant.CALL_STATE == Constant.CALL_CALLING) {
+                                return
+                            }
+
+                            Constant.CALL_STATE = Constant.CALL_STANDBY
+                            VoiceUtil.cancelAudioCall(Constant.DEVICE_ID)
+                            cancelCall()
+                            return
+                        }
+
+                        if (curTcpModel.data != null) {
+                            val curInteractionVO = Gson().fromJson(curTcpModel.data.toString(), InteractionVO::class.java)
+                            if (curTcpModel.getAction() == TcpAction.VoiceAction.ACCEPT) {
+                                //我方呼出,对方接受
+                                RingPlayHelper.stopRingTone()
+                                Constant.interactionId = curInteractionVO.id
+                                fromId = curTcpModel.fromId
+                                acceptCall()
+                            } else if (curTcpModel.getAction() == TcpAction.VoiceAction.REJECT) {
+                                //我方呼出,对方拒绝
+                                showMessage(R.string.call_reject)
+                                RingPlayHelper.stopRingTone()
+                                cancelCall()
+                            } else if (curTcpModel.getAction() == TcpAction.VoiceAction.CALLING) {
+                                //我方呼出,对方通话中
+                                showMessage(R.string.call_busy)
+                                AppTool.Time.delay(1500) {
+                                    RingPlayHelper.stopRingTone()
+                                    cancelCall()
+                                }
+                            } else if (curTcpModel.getAction() == TcpAction.VoiceAction.SUCCESS) {
+                                //呼叫成功
+                                //本机呼叫的时候tcpModel为空,只有呼叫成功的时候才能获得对应tcp相关数据
+                                callSuccess = true
+                                sky_voice_call_hangup.isEnabled = true
+                                interactionVO = curInteractionVO
+                                Constant.interactionId = curInteractionVO.id
+                                showOutgoingCall()
+
+                                if (SettingConfig.getRecordEnable(activity)) {
+                                    janusClient!!.connect(curInteractionVO.id, true)
+                                } else {
+                                    janusClient!!.connect(-1, false)
+                                }
+                            } else if (curTcpModel.getAction() == TcpAction.VoiceAction.FAILED) {
+                                //我方呼出,对方不在线,设备离线或其它错误
+                                callSuccess = true
+                                showMessage(R.string.call_failed)
+                                AppTool.Time.delay(1500) {
+                                    RingPlayHelper.stopRingTone()
+                                    cancelCall()
+                                }
+                            } else if (curTcpModel.getAction() == TcpAction.VoiceAction.HANDOFF) {
+                                //对方挂断,不论我方呼出或呼入
+                                if (Constant.interactionId == curInteractionVO.id) {
+                                    RingPlayHelper.stopRingTone()
+                                    cancelCall()
+                                }
+                            } else if (curTcpModel.getAction() == TcpAction.VoiceAction.CANCEL) {
+                                //对方呼叫时取消
+                                if (Constant.interactionId == curInteractionVO.id) {
+                                    RingPlayHelper.stopRingTone()
+                                    cancelCall()
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+            //外部呼叫按键
+            Constant.EVENT_SERIAL_EVENT -> {
+                if (!janusInit) {
+                    return
+                }
+
+                if (messageEvent.message is String) {
+                    val serialAction = messageEvent.message as String
+                    if (serialAction.equals("cancel")) {
+                        RingPlayHelper.stopRingTone()
+                        Constant.CALL_STATE = Constant.CALL_STANDBY
+                        VoiceUtil.cancelAudioCall(Constant.DEVICE_ID)
+                        cancelCall()
+                    } else if (serialAction.equals("accept")) {
+                        RingPlayHelper.stopRingTone()
+                        //Constant.CALL_STATE = Constant.CALL_CALLING
+                        VoiceUtil.acceptAudioCall(Constant.DEVICE_ID, fromId, interactionVO?.id)
+                        acceptCall()
+                        janusClient!!.connect(-1, false)
+                    } else if (serialAction.equals("handoff")) {
+                        Constant.CALL_STATE = Constant.CALL_STANDBY
+                        //VoiceUtil.handoffAudioCall(Constant.DEVICE_ID, fromId, Constant.interactionId)
+                        callEnd(true)
+                    } else if (serialAction.equals("reject")) {
+                        RingPlayHelper.stopRingTone()
+                        Constant.CALL_STATE = Constant.CALL_STANDBY
+                        VoiceUtil.rejectAudioCall(Constant.DEVICE_ID, fromId, interactionVO?.id)
+                        callEnd(false)
+                    }
+                }
+            }
+        }
+    }
+
+}

+ 216 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/fragment/TestFragment.kt

@@ -0,0 +1,216 @@
+package com.wdkl.app.ncs.callingbed2.fragment
+
+import android.hardware.Camera
+import android.view.SurfaceHolder
+import android.view.View
+import com.enation.javashop.net.engine.model.NetState
+import com.wdkl.app.ncs.callingbed2.R
+import com.wdkl.app.ncs.callingbed2.databinding.TestFragmentLayBinding
+import com.wdkl.app.ncs.callingbed2.helper.MediaPlayHelper
+import com.wdkl.app.ncs.callingbed2.helper.RecordHelper
+import com.wdkl.app.ncs.callingbed2.helper.SerialPortHelper
+import com.wdkl.app.ncs.callingbed2.helper.SoundPoolManager
+import com.wdkl.app.ncs.callingbed2.launch.Callingbed2Launch
+import com.wdkl.ncs.android.lib.base.BaseFragment
+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.callingbed2.QrCodeFragmentContract
+import com.wdkl.ncs.android.middleware.logic.presenter.callingbed2.QrCodeFragmentPresenter
+import kotlinx.android.synthetic.main.test_fragment_lay.*
+import org.greenrobot.eventbus.EventBus
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+
+class TestFragment : BaseFragment<QrCodeFragmentPresenter, TestFragmentLayBinding>(), QrCodeFragmentContract.View {
+    val TAG = "TestFragment"
+
+    var info = ""
+    var buttonTest = false
+    var testButton1 = false
+    var testButton2 = false
+    var testButton3 = false
+
+    private var mCamera: Camera? = null
+
+    override fun getLayId(): Int {
+        return R.layout.test_fragment_lay
+    }
+
+    override fun bindDagger() {
+        Callingbed2Launch.component.inject(this)
+    }
+
+    override fun init() {
+        RecordHelper.getInstance().init()
+        SoundPoolManager.getInstance().playSound(4, 1.0f, 1.0f, 0)
+
+        startCameraPreview()
+    }
+
+    override fun bindEvent() {
+        /*btn_test.setOnClickListener {
+            btn_test.isEnabled = false
+            //开始测试
+            startTest()
+        }*/
+    }
+
+    private fun startTest() {
+        Thread {
+            info += "\r\n--> 麦克风测试:\r\n"
+            showInfo(info)
+            SoundPoolManager.getInstance().playSound(3, 1.0f, 1.0f, 0)
+            Thread.sleep(2000)
+            info += "开始录音...\r\n"
+            showInfo(info)
+            RecordHelper.getInstance().recordTestStart()
+            Thread.sleep(2500)
+            RecordHelper.getInstance().recordTestStop()
+            Thread.sleep(500)
+            info += "播放录音...\r\n"
+            showInfo(info)
+            MediaPlayHelper.getInstance().playUrlMusic(RecordHelper.getInstance().audiofilePath, 1.0f, false)
+
+            Thread.sleep(3000)
+            RecordHelper.getInstance().deleteAudioFile()
+
+            info += "--> 指示灯测试\r\n"
+            showInfo(info)
+            SerialPortHelper.setCallStatus("1")
+            Thread.sleep(2000)
+            SerialPortHelper.setCallStatus("0")
+
+            info += "===测试结束!===\r\n"
+            showInfo(info)
+        }.start()
+    }
+
+    private fun showInfo(text: String) {
+        activity.runOnUiThread {
+            if (tv_test_info != null) {
+                tv_test_info.text = text
+            }
+        }
+    }
+
+    private fun startCameraPreview() {
+        val num = Camera.getNumberOfCameras()
+        if (num > 0) {
+            try {
+                mCamera = Camera.open()
+            } catch (e: Exception) {
+                tv_camera.visibility = View.VISIBLE
+                tv_camera.text = "摄像头打开失败"
+                e.printStackTrace()
+                return
+            }
+
+            camera_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(camera_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 {
+            tv_camera.visibility = View.VISIBLE
+            tv_camera.text = "没有摄像头"
+        }
+    }
+
+    override fun onStart() {
+        EventBus.getDefault().register(this)
+        super.onStart()
+    }
+
+    override fun onStop() {
+        EventBus.getDefault().unregister(this)
+        super.onStop()
+    }
+
+    override fun destory() {
+        if (mCamera != null) {
+            mCamera!!.stopPreview()
+            mCamera!!.release()
+            mCamera = null
+        }
+    }
+
+    override fun onError(message: String, type: Int) {
+        //
+    }
+
+    override fun complete(message: String, type: Int) {
+    }
+
+    override fun start() {
+    }
+
+    override fun networkMonitor(state: NetState) {
+        state.filter(onWifi = {
+
+        },onMobile = {
+
+        },offline = {
+
+        })
+    }
+
+    override fun setUrlString(url: String) {
+        //
+    }
+
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    fun onMoonEvent(messageEvent: MessageEvent) {
+        if (Constant.EVENT_SERIAL_TEST == messageEvent.type) {
+            if (!buttonTest) {
+                val message = messageEvent.message as String
+                if (message == "call1" && !testButton1) {
+                    info += " ##面板呼叫键## "
+                    testButton1 = true
+                } else if (message == "call2" && !testButton2) {
+                    info += " ##手柄按键## "
+                    testButton2 = true
+                } else if (message == "call_end" && !testButton3) {
+                    info += " ##面板挂断键## "
+                    testButton3 = true
+                }
+
+                showInfo(info)
+
+                if (testButton1 && testButton2 && testButton3) {
+                    buttonTest = true
+                    startTest()
+                }
+            }
+        }
+    }
+}

+ 135 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/fragment/VoiceMsgFragment.kt

@@ -0,0 +1,135 @@
+package com.wdkl.app.ncs.callingbed2.fragment
+
+import android.os.SystemClock
+import android.view.MotionEvent
+import com.enation.javashop.net.engine.model.NetState
+import com.wdkl.app.ncs.callingbed2.R
+import com.wdkl.app.ncs.callingbed2.databinding.VoiceMsgLayBinding
+import com.wdkl.app.ncs.callingbed2.helper.HttpHelper
+import com.wdkl.app.ncs.callingbed2.helper.MediaPlayHelper
+import com.wdkl.app.ncs.callingbed2.helper.RecordHelper
+import com.wdkl.app.ncs.callingbed2.launch.Callingbed2Launch
+import com.wdkl.ncs.android.lib.base.BaseFragment
+import com.wdkl.ncs.android.lib.utils.debugLog
+import com.wdkl.ncs.android.lib.utils.errorLog
+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.logic.contract.callingbed2.VoiceFragmentContract
+import com.wdkl.ncs.android.middleware.logic.presenter.callingbed2.VoiceFragmentPresenter
+import com.wdkl.ncs.android.middleware.tcp.TcpClient
+import com.wdkl.ncs.android.middleware.tcp.channel.ImUtil
+import kotlinx.android.synthetic.main.voice_msg_lay.*
+import java.io.File
+import javax.inject.Inject
+
+class VoiceMsgFragment @Inject constructor() : BaseFragment<VoiceFragmentPresenter, VoiceMsgLayBinding>(), VoiceFragmentContract.View {
+    val TAG = "VoiceMsgFragment"
+
+    var downTime : Long = 0
+    var upTime : Long = 0
+    var downY : Float = 0f
+    var cancel : Boolean = false
+    lateinit var voiceFile : String
+
+    private val urlManager = UrlManager.build()
+
+    override fun getLayId(): Int {
+        return R.layout.voice_msg_lay
+    }
+
+    override fun bindDagger() {
+        Callingbed2Launch.component.inject(this)
+    }
+
+    override fun init() {
+        //
+    }
+
+    override fun bindEvent() {
+        //debugLog(TAG,"bindEvent")
+        tv_voice_button.setOnTouchListener { v, event ->
+            when(event.action) {
+                MotionEvent.ACTION_DOWN -> {
+                    cancel = false
+                    downTime = System.currentTimeMillis()
+                    downY = event.getY()
+                    RecordHelper.getInstance().startRecord()
+                    tv_voice_text.text = "松开留言,上滑取消"
+                    voice_call_timer.base = SystemClock.elapsedRealtime()
+                    voice_call_timer.start()
+                    voiceFile = RecordHelper.getInstance().audiofilePath
+                }
+
+                MotionEvent.ACTION_MOVE -> {
+                    val moveY = event.getY()
+                    if (downY - moveY > 100) {
+                        cancel = true
+                    }
+                }
+
+                MotionEvent.ACTION_UP -> {
+                    upTime = System.currentTimeMillis()
+                    RecordHelper.getInstance().stopRecord()
+                    tv_voice_text.text = "按住说话"
+                    voice_call_timer.base = SystemClock.elapsedRealtime()
+                    voice_call_timer.stop()
+
+                    if (Math.abs(upTime - downTime) <= 1000) {
+                        RecordHelper.getInstance().deleteAudioFile(voiceFile)
+                        showMessage("说话时间太短")
+                    } else if(cancel) {
+                        RecordHelper.getInstance().deleteAudioFile(voiceFile)
+                        showMessage("语音留言已取消")
+                    } else {
+                        //上传语音留言
+                        val callback = object : HttpHelper.UploadCallback {
+                            override fun onFail() {
+                                activity.runOnUiThread {
+                                    showMessage("留言发送失败!")
+                                }
+                            }
+
+                            override fun onSuccess(data: String) {
+                                activity.runOnUiThread {
+                                    val tcpModel = ImUtil.imMsg(Constant.DEVICE_ID, data)
+                                    TcpClient.getInstance().sendMsg(tcpModel.toJson())
+                                    showMessage("留言发送成功!")
+                                }
+                            }
+                        }
+                        HttpHelper.upload(urlManager.base + Constant.UPLOAD_VOICE_MSG_URL, File(voiceFile), TAG, callback)
+                    }
+                }
+            }
+
+            return@setOnTouchListener false
+        }
+    }
+
+    override fun destory() {
+        debugLog(TAG,"destory")
+    }
+
+    override fun onError(message: String, type: Int) {
+        errorLog("error",message)
+        showMessage(message)
+    }
+
+    override fun complete(message: String, type: Int) {
+    }
+
+    override fun start() {
+    }
+
+    override fun networkMonitor(state: NetState) {
+        state.filter(onWifi = {
+
+        },onMobile = {
+
+        },offline = {
+
+        })
+    }
+}

+ 252 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/AnrFcExceptionUtil.java.bak

@@ -0,0 +1,252 @@
+package com.wdkl.app.ncs.callingbed2.helper;
+
+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.welcome.activity.WelcomeActivity;
+import com.wdkl.ncs.android.middleware.api.UrlManager;
+import com.wdkl.ncs.android.middleware.common.Constant;
+import com.wdkl.skywebrtc.CallSession;
+import com.wdkl.skywebrtc.EnumType;
+import com.wdkl.skywebrtc.SkyEngineKit;
+
+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.Locale;
+import java.util.Map;
+import java.util.TimeZone;
+
+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 = "MyApplication";
+    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(2000);
+            } catch (InterruptedException e) {
+                Log.e(TAG, "error : ", e);
+            }
+
+            restartApp();
+        }
+    }
+
+    private void restartApp() {
+        Constant.CALL_STATE = Constant.CALL_STANDBY;
+        CallSession session= SkyEngineKit.Instance().getCurrentSession();
+        if(session!=null&&session.getState()!= EnumType.CallState.Idle){
+            SkyEngineKit.Instance().endCall();
+        }
+
+        //重新启动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;
+        }
+        //使用Toast来显示异常信息
+        /*new Thread() {
+            @Override
+            public void run() {
+                Looper.prepare();
+//                Toast.makeText(application.getApplicationContext(), "很抱歉,程序出现异常,即将重新启动.",
+//                        Toast.LENGTH_SHORT).show();
+                Looper.loop();
+            }
+        }.start();*/
+        saveCrashInfo2File(ex);
+        return true;
+    }
+
+    /**
+     * 保存错误信息到文件中
+     *
+     * @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();
+            format.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
+            String time = format.format(new Date());
+            String fileName = "crash-" + time + "-" + timestamp + ".txt";
+            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+                String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/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;
+    }
+
+    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);
+            }
+        });
+    }
+
+    /**
+     * ===================================================崩溃异常处理===================================================
+     */
+    public void initFCException() {
+        //设置该CrashHandler为程序的默认处理器
+        AnrFcExceptionUtil catchExcep = AnrFcExceptionUtil.getInstance(application);
+        Thread.setDefaultUncaughtExceptionHandler(catchExcep);
+        mANRWatchDog = new ANRWatchDog(8000);
+        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...");
+                AppUpdateHelper.reboot(application);
+            }
+        }).start();
+
+    }
+}

+ 234 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/AppUpdateHelper.java

@@ -0,0 +1,234 @@
+package com.wdkl.app.ncs.callingbed2.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 com.wdkl.ncs.android.component.welcome.activity.WelcomeActivity;
+
+import java.io.BufferedReader;
+import java.io.File;
+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() + "/CallingBed2";
+    /**
+     * 下载的APK文件的文件名
+     */
+    public static final String FILE_APK_NAME = "CallingBed2APK.apk";
+
+    public static void updateApp(Context context, UpdateCallBack callBack) {
+        if (checkApkExit(context)) {
+            Log.d(TAG, "文件存在");
+        } else {
+            Log.d(TAG, "文件不存在");
+            if (callBack != null) {
+                callBack.onFailed();
+            }
+            return;
+        }
+
+        /*if (!checkApkAvailable(context, DownloadUtil.FILE_APK_PATH + "/" + DownloadUtil.FILE_APK_NAME)) {
+            ToastUtil.showToast("apk文件不匹配,升级失败!");
+            return;
+        }*/
+
+        String path = FILE_APK_PATH + "/" + FILE_APK_NAME;
+        //if (installApp(context.getPackageName(), path)) {
+        if (rootSilenceInstall(path)) {
+            Log.d(TAG, "安装成功");
+            if (callBack != null) {
+                callBack.onSuccess();
+            }
+        } else {
+            Log.d(TAG, "安装失败");
+            if (callBack != null) {
+                callBack.onFailed();
+            }
+        }
+
+        /*if (silentInstall(context, path)) {
+            Log.d(TAG, "app 安装成功");
+            if (callBack != null) {
+                callBack.onSuccess();
+            }
+        }*/
+    }
+
+    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 void reboot(Context context, boolean reset) {
+        if (Build.MODEL.equals("rk3128")) {
+            if (reset) {
+                SerialPortHelper.resetDevice();
+            } else {
+                try {
+                    Intent intent = new Intent(Intent.ACTION_REBOOT);
+                    intent.putExtra("nowait", 1);
+                    intent.putExtra("interval", 1);
+                    intent.putExtra("window", 0);
+                    context.sendBroadcast(intent);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+
+                SerialPortHelper.resetDevice();
+            }
+        } else if (Build.MODEL.equals("rk3288")) {
+            Process process;
+            PrintWriter printWriter;
+            try {
+                process = Runtime.getRuntime().exec("su");
+                printWriter = new PrintWriter(process.getOutputStream());
+                printWriter.println("reboot");
+                printWriter.flush();
+                printWriter.close();
+                process.waitFor();
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    public static void restartApp(Context context) {
+        //重新启动app
+        Intent mStartActivity = new Intent(context.getApplicationContext(), WelcomeActivity.class);
+        mStartActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+        int mPendingIntentId = 123456;
+        PendingIntent mPendingIntent = PendingIntent.getActivity(context.getApplicationContext(), mPendingIntentId, mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT);
+        AlarmManager mgr = (AlarmManager) context.getApplicationContext().getSystemService(Context.ALARM_SERVICE);
+        mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1500, mPendingIntent);
+
+        android.os.Process.killProcess(android.os.Process.myPid());
+        System.exit(0);
+    }
+
+    public interface UpdateCallBack {
+        void onFailed();
+        void onSuccess();
+    }
+}

+ 93 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/AppUtil.java

@@ -0,0 +1,93 @@
+package com.wdkl.app.ncs.callingbed2.helper;
+
+import android.app.AlarmManager;
+import android.content.Context;
+import android.text.TextUtils;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Calendar;
+
+public class AppUtil {
+
+    /**
+     * 设置系统时间
+     *
+     * @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";
+        }
+    }
+
+    /**
+     * 字符串按索引截取
+     *
+     * @param str
+     * @return
+     */
+    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 setSystemTime(Context context, int year, int month, int day, int hour, int minute, int mill) {
+        Calendar c = Calendar.getInstance();
+        c.set(Calendar.YEAR, year);
+        c.set(Calendar.MONTH, month);
+        c.set(Calendar.DAY_OF_MONTH, day);
+        c.set(Calendar.HOUR_OF_DAY, hour);
+        c.set(Calendar.MINUTE, minute);
+        c.set(Calendar.SECOND, mill);
+        c.set(Calendar.MILLISECOND, 0);
+        long when = c.getTimeInMillis();
+        if (when / 1000 < Integer.MAX_VALUE) {
+            ((AlarmManager) context.getSystemService(Context.ALARM_SERVICE)).setTime(when);
+        }
+    }
+
+    public static void setSystemTime(Context context, long timeMills, String timeZone) {
+        AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+        alarmManager.setTimeZone(timeZone);
+        alarmManager.setTime(timeMills);
+    }
+}

+ 189 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/AsyncPlayer.java

@@ -0,0 +1,189 @@
+package com.wdkl.app.ncs.callingbed2.helper;
+
+import android.content.Context;
+import android.media.AudioDeviceInfo;
+import android.media.AudioManager;
+import android.media.MediaPlayer;
+import android.net.Uri;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.util.Log;
+
+import java.io.IOException;
+import java.util.LinkedList;
+
+/**
+ * 响铃相关类
+ */
+public class AsyncPlayer {
+    private static final int PLAY = 1;
+    private static final int STOP = 2;
+    private AudioManager audioManager;
+
+    private static final class Command {
+        int code;
+        Context context;
+        int resId;
+        boolean looping;
+        int stream;
+        long requestTime;
+
+        public String toString() {
+            return "{ code=" + code + " looping=" + looping + " stream=" + stream + " resId=" + resId + " }";
+        }
+    }
+
+    private final LinkedList mCmdQueue = new LinkedList();
+
+    private void startSound(Command cmd) {
+
+        try {
+            //MediaPlayer player = new MediaPlayer();
+            MediaPlayer player = MediaPlayer.create(cmd.context, cmd.resId);
+            player.setAudioStreamType(cmd.stream);
+            //player.setDataSource(cmd.context, cmd.uri);
+            player.setLooping(cmd.looping);
+            player.setVolume(1.0f, 1.0f);
+            //player.prepare();
+            player.start();
+            if (mPlayer != null) {
+                mPlayer.release();
+            }
+            mPlayer = player;
+            Log.w(mTag, "start sound " + cmd.resId);
+        } catch (Exception e) {
+            Log.w(mTag, "error loading sound for " + cmd.resId, e);
+        }
+    }
+
+    private final class Thread extends java.lang.Thread {
+        Thread() {
+            super("AsyncPlayer-" + mTag);
+        }
+
+        public void run() {
+            while (true) {
+                Command cmd = null;
+
+                synchronized (mCmdQueue) {
+
+                    cmd = (Command) mCmdQueue.removeFirst();
+                }
+
+                switch (cmd.code) {
+                    case PLAY:
+                        startSound(cmd);
+                        break;
+                    case STOP:
+
+                        if (mPlayer != null) {
+                            mPlayer.stop();
+                            mPlayer.reset();
+                            mPlayer.release();
+                            mPlayer = null;
+                        } else {
+                            Log.w(mTag, "STOP command without a player");
+                        }
+                        break;
+                }
+
+                synchronized (mCmdQueue) {
+                    if (mCmdQueue.size() == 0) {
+
+                        mThread = null;
+                        releaseWakeLock();
+                        return;
+                    }
+                }
+            }
+        }
+    }
+
+    private String mTag;
+    private Thread mThread;
+    private MediaPlayer mPlayer;
+    private PowerManager.WakeLock mWakeLock;
+
+    private int mState = STOP;
+
+    public AsyncPlayer(String tag) {
+        if (tag != null) {
+            mTag = tag;
+        } else {
+            mTag = "AsyncPlayer";
+        }
+    }
+
+    public void play(Context context, int res, boolean looping, int stream) {
+        Command cmd = new Command();
+        cmd.requestTime = SystemClock.uptimeMillis();
+        cmd.code = PLAY;
+        cmd.context = context;
+        cmd.resId = res;
+        cmd.looping = looping;
+        cmd.stream = stream;
+        synchronized (mCmdQueue) {
+            enqueueLocked(cmd);
+            mState = PLAY;
+        }
+    }
+
+    public void stop() {
+        synchronized (mCmdQueue) {
+            if (mState != STOP) {
+                Command cmd = new Command();
+                cmd.requestTime = SystemClock.uptimeMillis();
+                cmd.code = STOP;
+                enqueueLocked(cmd);
+                mState = STOP;
+            }
+        }
+    }
+
+    private void enqueueLocked(Command cmd) {
+        mCmdQueue.add(cmd);
+        if (mThread == null) {
+            acquireWakeLock();
+            mThread = new Thread();
+            mThread.start();
+        }
+    }
+
+    public void setUsesWakeLock(Context context) {
+        if (mWakeLock != null || mThread != null) {
+            throw new RuntimeException("assertion failed mWakeLock=" + mWakeLock + " mThread=" + mThread);
+        }
+        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, mTag);
+    }
+
+    private void acquireWakeLock() {
+        if (mWakeLock != null) {
+            mWakeLock.acquire();
+        }
+    }
+
+    private void releaseWakeLock() {
+        if (mWakeLock != null) {
+            mWakeLock.release();
+        }
+    }
+
+    private boolean isHeadphonesPlugged(Context context) {
+        if (audioManager == null) {
+            audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        }
+        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
+            AudioDeviceInfo[] audioDevices = audioManager.getDevices(AudioManager.GET_DEVICES_ALL);
+            for (AudioDeviceInfo deviceInfo : audioDevices) {
+                if (deviceInfo.getType() == AudioDeviceInfo.TYPE_WIRED_HEADPHONES
+                        || deviceInfo.getType() == AudioDeviceInfo.TYPE_WIRED_HEADSET) {
+                    return true;
+                }
+            }
+            return false;
+        } else {
+            return audioManager.isWiredHeadsetOn();
+        }
+    }
+}

+ 87 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/CallDialogHelper.java

@@ -0,0 +1,87 @@
+package com.wdkl.app.ncs.callingbed2.helper;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.media.AudioManager;
+import android.view.Display;
+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.app.ncs.callingbed2.R;
+
+public class CallDialogHelper {
+
+    private static AlertDialog callDialog;
+
+    private static AsyncPlayer ringPlayer;
+
+    public static void showCallDialog(Activity activity, int callType, View.OnClickListener hangupCall, View.OnClickListener acceptCall, View.OnClickListener rejectCall) {
+        if (ringPlayer == null) {
+            ringPlayer = new AsyncPlayer(null);
+        }
+
+        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);
+
+        if (callType == 0) {
+            //去电
+            outCall.setVisibility(View.VISIBLE);
+            inCall.setVisibility(View.GONE);
+            ringPlayer.play(activity, R.raw.ring_back2, true, AudioManager.STREAM_MUSIC);
+        } else {
+            //来电
+            outCall.setVisibility(View.GONE);
+            inCall.setVisibility(View.VISIBLE);
+            ringPlayer.play(activity, R.raw.ring_tone, true, AudioManager.STREAM_MUSIC);
+        }
+
+        hangup.setOnClickListener(hangupCall);
+        accept.setOnClickListener(acceptCall);
+        reject.setOnClickListener(rejectCall);
+
+        callDialog = builder.create();
+        callDialog.setCanceledOnTouchOutside(false);
+        callDialog.setCancelable(false);
+        callDialog.show();
+
+        //设置dialog宽高及位置
+        try {
+            Window window = callDialog.getWindow();
+            WindowManager.LayoutParams lp = window.getAttributes();
+            lp.width = 800;
+            lp.height = 400;
+            lp.gravity = Gravity.CENTER;
+            //lp.alpha = 0.4f;
+            //window.setBackgroundDrawableResource(R.color.transparent_dialog);
+            window.setAttributes(lp);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public static void dismissCallDialog() {
+        if (callDialog != null && callDialog.isShowing()) {
+            callDialog.dismiss();
+        }
+        if (ringPlayer != null) {
+            ringPlayer.stop();
+        }
+    }
+}

+ 19 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/DoorLightHelper.java

@@ -0,0 +1,19 @@
+package com.wdkl.app.ncs.callingbed2.helper;
+
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel;
+import com.wdkl.ncs.android.middleware.tcp.enums.TcpAction;
+
+public class DoorLightHelper {
+
+    public static void handleDoorLight(TcpModel tcpModel) {
+        if (TcpAction.SideAction.CALL == tcpModel.getAction()
+            || TcpAction.SideAction.SOS_CALL == tcpModel.getAction()) {
+            //门灯红色闪烁
+            SerialPortHelper.setDoorLight(1, "200"); //红色闪烁
+        } else if (TcpAction.SideAction.ACCEPT == tcpModel.getAction()
+            || TcpAction.SideAction.CANCEL == tcpModel.getAction()
+            || TcpAction.SideAction.SOS_CANCEL == tcpModel.getAction()) {
+            SerialPortHelper.setDoorLight(1, "111"); //白色
+        }
+    }
+}

+ 190 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/HttpHelper.java

@@ -0,0 +1,190 @@
+package com.wdkl.app.ncs.callingbed2.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 okhttp3.ResponseBody;
+
+import static com.wdkl.app.ncs.callingbed2.helper.AppUpdateHelper.FILE_APK_NAME;
+import static com.wdkl.app.ncs.callingbed2.helper.AppUpdateHelper.FILE_APK_PATH;
+
+public class HttpHelper {
+    private static OkHttpClient okHttpClient = null;
+
+    /**
+     * @param url   服务器地址
+     * @param file  所要上传的文件
+     */
+    public static void upload(String url, File file, Object tag, UploadCallback callback) {
+        if (okHttpClient == null) {
+            okHttpClient = 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)
+                .tag(tag)
+                .post(requestBody)
+                .build();
+
+        okHttpClient.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("upload", "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, Object tag, final DownloadListener listener) {
+        if (okHttpClient == null) {
+            okHttpClient = new OkHttpClient();
+        }
+
+        Request request = new Request.Builder()
+                .url(url)
+                .tag(tag)
+                .build();
+
+        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==");
+                    }
+                }
+            }
+        });
+    }
+
+    public static void cancelRequestByTag(Object tag) {
+        if (okHttpClient != null && tag != null) {
+            for (Call call : okHttpClient.dispatcher().queuedCalls()) {
+                if (tag.equals(call.request().tag())) {
+                    call.cancel();
+                }
+            }
+
+            for (Call call : okHttpClient.dispatcher().runningCalls()) {
+                if (tag.equals(call.request().tag())) {
+                    call.cancel();
+                }
+            }
+        }
+    }
+
+    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();
+    }
+}

+ 140 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/LanguageSetDialogHelper.java

@@ -0,0 +1,140 @@
+package com.wdkl.app.ncs.callingbed2.helper;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.os.Handler;
+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.ArrayAdapter;
+import android.widget.Button;
+import android.widget.RadioButton;
+import android.widget.RadioGroup;
+import android.widget.Spinner;
+import android.widget.Toast;
+
+import com.wdkl.app.ncs.callingbed2.R;
+import com.wdkl.app.ncs.callingbed2.settings.SettingConfig;
+
+
+public class LanguageSetDialogHelper {
+
+    private static AlertDialog dialog;
+    private static int selectIndex;
+
+    public static void showDialog(final Activity activity) {
+        if (dialog != null && dialog.isShowing()) {
+            return;
+        }
+
+        final int originIndex = LocaleMangerUtils.getCurrentLocaleIndex();
+        selectIndex = originIndex;
+
+        View contentView = LayoutInflater.from(activity).inflate(R.layout.language_set_dialog, null);
+        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+        builder.setView(contentView);
+
+        RadioButton btnYes = contentView.findViewById(R.id.rb_language_yes);
+        RadioButton btnNo = contentView.findViewById(R.id.rb_language_no);
+        final int mode = SettingConfig.getLanguageMode(activity);
+        if (mode == 0) {
+            btnYes.setChecked(true);
+        } else {
+            btnNo.setChecked(true);
+        }
+
+        Button buttonCancel = contentView.findViewById(R.id.cancel_button);
+        Button buttonConfirm = contentView.findViewById(R.id.confirm_button);
+        Spinner spinner = contentView.findViewById(R.id.spinner_language_select);
+        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(activity,
+                R.array.language_list, R.layout.spinner_item);
+        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+        spinner.setAdapter(adapter);
+        spinner.setSelection(originIndex);
+        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+            @Override
+            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+                Log.d("languageId", "pos: " + position + ", originIndex: " + originIndex);
+                selectIndex = position;
+            }
+
+            @Override
+            public void onNothingSelected(AdapterView<?> parent) {
+
+            }
+        });
+
+        RadioGroup languageGroup = contentView.findViewById(R.id.group_language_mode);
+        languageGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
+            @Override
+            public void onCheckedChanged(RadioGroup group, int checkedId) {
+                if (checkedId == R.id.rb_language_yes) {
+                    SettingConfig.setLanguageMode(activity, 0);
+                } else {
+                    SettingConfig.setLanguageMode(activity, 1);
+                }
+            }
+        });
+
+        buttonCancel.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if (dialog != null) {
+                    dialog.dismiss();
+                }
+            }
+        });
+
+        buttonConfirm.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                SettingConfig.setLanguageId(activity, selectIndex);
+
+                if (SettingConfig.getLanguageMode(activity) == 1) {
+                    if (selectIndex != originIndex) {
+                        Toast.makeText(activity, "restart now...", Toast.LENGTH_LONG).show();
+                        new Handler().postDelayed(new Runnable() {
+                            @Override
+                            public void run() {
+                                AppUpdateHelper.restartApp(activity);
+                            }
+                        }, 3000);
+                    }
+                } else {
+                    Toast.makeText(activity, "restart now...", Toast.LENGTH_LONG).show();
+                    new Handler().postDelayed(new Runnable() {
+                        @Override
+                        public void run() {
+                            AppUpdateHelper.restartApp(activity);
+                        }
+                    }, 3000);
+                }
+
+                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 = 480;
+            lp.height = 420;
+            lp.gravity = Gravity.CENTER;
+            window.setAttributes(lp);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+}

+ 80 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/LocaleMangerUtils.java

@@ -0,0 +1,80 @@
+package com.wdkl.app.ncs.callingbed2.helper;
+
+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.app.ncs.callingbed2.R;
+import com.wdkl.app.ncs.callingbed2.settings.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);
+        }
+    }
+
+}

+ 219 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/MediaPlayHelper.java

@@ -0,0 +1,219 @@
+package com.wdkl.app.ncs.callingbed2.helper;
+
+import android.media.AudioManager;
+import android.media.MediaPlayer;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Message;
+
+import com.wdkl.ncs.android.lib.base.BaseApplication;
+
+public class MediaPlayHelper {
+
+    private static MediaPlayHelper sInstance = null;
+    private MediaPlayer mediaPlayer;
+    private HandlerThread playHandlerThread;
+    private Handler playHandler;
+
+    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();
+    }
+
+    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.isPlaying()) {
+            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();
+                    return false;
+                }
+            });
+        } catch (Exception e) {
+            //playMusicError();
+            e.printStackTrace();
+        }
+    }
+
+    //播放远程或本地存储音频资源
+    private void playUrlMusicNow() {
+        if (mediaPlayer != null && mediaPlayer.isPlaying()) {
+            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();
+                    mediaPlayer.release();
+                //}
+            } catch (IllegalStateException e) {
+                e.printStackTrace();
+            }
+        }
+        mediaPlayer = null;
+    }
+
+    private void releaseMediaNow() {
+        if (mediaPlayer != null) {
+            mediaPlayer.setOnPreparedListener(null);
+            mediaPlayer.setOnCompletionListener(null);
+            try {
+                mediaPlayer.stop();
+                mediaPlayer.release();
+            } catch (IllegalStateException e) {
+                e.printStackTrace();
+            }
+        }
+        mediaPlayer = null;
+    }
+
+    public boolean isMediaPlaying() {
+        if (mediaPlayer != null) {
+            return mediaPlayer.isPlaying();
+        }
+        return false;
+    }
+}

+ 532 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/NetHelper.java

@@ -0,0 +1,532 @@
+package com.wdkl.app.ncs.callingbed2.helper;
+
+import android.Manifest;
+import android.annotation.SuppressLint;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.net.ConnectivityManager;
+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 com.wdkl.ncs.android.middleware.common.MessageEvent;
+
+import org.greenrobot.eventbus.EventBus;
+
+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;
+
+import static com.wdkl.ncs.android.middleware.common.Constant.EVENT_INTERNETPING;
+
+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 = 30000;
+    public static boolean NetConn = false;
+
+    /**
+     * 以太网是否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);
+    }
+
+    public static void startNetCheck() {
+        if (timerNetStatus != null) {
+            timerNetStatus.purge();
+        }
+        timerNetStatus = new Timer();
+        timerNetStatus.schedule(new TimerTask() {
+            @Override
+            public void run() {
+                NetConn = ping(getLocalElement(3), 2, null);
+
+                EventBus.getDefault().post(new MessageEvent(ETHERNETSTATUS, EVENT_INTERNETPING));//循环检测SIP,以太网ping状态
+            }
+        }, 10, SCHEDULE_TIME);
+    }
+
+    /**
+     * 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;
+    }
+
+    //获取本地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;
+    }
+
+    /**
+     * 得到MAC
+     *
+     * @return String
+     */
+    public String getMacAddress() {
+        String mac = "";
+        try {
+            mac = getLocalMacAddressFromIp();
+            if (TextUtils.isEmpty(mac)) {
+                mac = getNetworkMac();
+            }
+            if (TextUtils.isEmpty(mac)) {
+                mac = tryGetWifiMac();
+            }
+        } catch (Exception e) {
+        }
+        return mac;
+    }
+
+    /**
+     * 通过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;
+    }
+
+
+    /**
+     * 根据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;
+    }
+
+    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 static boolean isBTConnected() {
+        BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
+        if (btAdapter != null) {
+            return btAdapter.getState() == BluetoothAdapter.STATE_ON;
+        }
+
+        return false;
+    }
+
+    public int getNetworkType() {
+        if (connManager != null && connManager.getActiveNetworkInfo() != null) {
+            return connManager.getActiveNetworkInfo().getType();
+        }
+
+        return -1;
+    }
+
+    public boolean networkAvailable() {
+        if (connManager != null && connManager.getActiveNetworkInfo() != null) {
+            return connManager.getActiveNetworkInfo().isConnected();
+        }
+
+        return false;
+    }
+}

+ 128 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/PasswordDialogHelper.java

@@ -0,0 +1,128 @@
+package com.wdkl.app.ncs.callingbed2.helper;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+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.GridView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.wdkl.app.ncs.callingbed2.R;
+import com.wdkl.app.ncs.callingbed2.adapter.NumAdapter;
+import com.wdkl.ncs.android.middleware.utils.StringUtil;
+
+
+public class PasswordDialogHelper {
+
+    private static AlertDialog dialog;
+    private static String pwd = "";
+
+    public static void showPasswordDialog(final Activity activity, final MyListener listener) {
+        View contentView = LayoutInflater.from(activity).inflate(R.layout.password_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);
+                }
+            }
+        });
+
+        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("pwd", "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(R.string.input_password);
+                }
+            }
+        });
+
+        cancel.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                dismissCallDialog();
+            }
+        });
+
+        confirm.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if ("888".equals(pwd)) {
+                    if (listener != null) {
+                        listener.onConfirm();
+                        dismissCallDialog();
+                    }
+                } else {
+                    Toast.makeText(activity, StringUtil.getResString(R.string.invalid_password), Toast.LENGTH_SHORT).show();
+                }
+            }
+        });
+
+
+
+
+        dialog = builder.create();
+        dialog.setCanceledOnTouchOutside(false);
+        dialog.setCancelable(false);
+        dialog.show();
+
+        //设置dialog宽高及位置
+        try {
+            Window window = dialog.getWindow();
+            window.setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
+            WindowManager.LayoutParams lp = window.getAttributes();
+            lp.width = 400;
+            lp.height = 480;
+            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 (dialog != null && dialog.isShowing()) {
+            dialog.dismiss();
+        }
+    }
+
+    public interface MyListener{
+        void onConfirm();
+    }
+}

+ 126 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/RecordHelper.java

@@ -0,0 +1,126 @@
+package com.wdkl.app.ncs.callingbed2.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;
+    }
+}

+ 22 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/RingPlayHelper.java

@@ -0,0 +1,22 @@
+package com.wdkl.app.ncs.callingbed2.helper;
+
+import android.content.Context;
+import android.media.AudioManager;
+
+public class RingPlayHelper {
+
+    private static AsyncPlayer ringPlayer;
+
+    public static void playRingTone(Context context, int res, boolean loop) {
+        if (ringPlayer == null) {
+            ringPlayer = new AsyncPlayer(null);
+        }
+        ringPlayer.play(context, res, loop, AudioManager.STREAM_MUSIC);
+    }
+
+    public static void stopRingTone() {
+        if (ringPlayer != null) {
+            ringPlayer.stop();
+        }
+    }
+}

+ 47 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/SOSHelper.java

@@ -0,0 +1,47 @@
+package com.wdkl.app.ncs.callingbed2.helper;
+
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+
+import com.wdkl.ncs.android.middleware.common.Constant;
+import com.wdkl.ncs.android.middleware.tcp.channel.OtherUtil;
+
+
+/*
+ * 紧急按钮辅助类
+ */
+public class SOSHelper {
+
+    private final static Handler handler = new Handler(Looper.getMainLooper()) {
+        @Override
+        public void handleMessage(Message msg) {
+            sosStop();
+        }
+    };
+
+    public static void sosStart() {
+        Constant.SOS_ON = true;
+        SerialPortHelper.setSosLight("2");
+        //如果该床位绑定了紧急按钮则直接通过紧急按钮设备id发送sos请求
+        if (Constant.EMERGENCY_ID != -1) {
+            OtherUtil.sendSosCall(Constant.EMERGENCY_ID);
+        } else {
+            OtherUtil.sendRoomSosCall(Constant.DEVICE_ID);
+        }
+
+        //60s之后紧急按钮灯自动复位
+        handler.removeCallbacksAndMessages(null);
+        handler.sendEmptyMessageDelayed(110, 120000);
+    }
+
+    public static void sosStop() {
+        Constant.SOS_ON = false;
+        handler.removeCallbacksAndMessages(null);
+        if (Constant.day_state == 1) {
+            SerialPortHelper.setSosLight("1");
+        } else {
+            SerialPortHelper.setSosLight("0");
+        }
+    }
+}

+ 81 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/ScreenManagerUtil.kt

@@ -0,0 +1,81 @@
+package com.wdkl.app.ncs.callingbed2.helper
+
+import android.content.Context
+import android.content.Intent
+import android.net.Uri
+import android.os.Build
+import android.provider.Settings
+import android.util.Log
+
+class ScreenManagerUtil {
+
+
+    /**
+     * @return 0--255
+     */
+    fun getScreenBrightness(context: Context): Int {
+        var screenBrightness = 150
+
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            if (!Settings.System.canWrite(context)) {
+                val intent = Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS)
+                intent.data = Uri.parse("package:" + context.packageName)
+                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+                context.startActivity(intent)
+            } else {
+                //有了权限,具体的动作
+                try {
+                    screenBrightness = Settings.System.getInt(context.contentResolver,
+                            Settings.System.SCREEN_BRIGHTNESS)
+                } catch (e: Settings.SettingNotFoundException) {
+                    e.printStackTrace()
+                }
+
+            }
+        } else {
+            try {
+                screenBrightness = Settings.System.getInt(context.contentResolver,
+                        Settings.System.SCREEN_BRIGHTNESS)
+            } catch (e: Settings.SettingNotFoundException) {
+                e.printStackTrace()
+            }
+
+        }
+
+        return screenBrightness
+    }
+
+
+    /**
+     * 保存当前的屏幕亮度值,并使之生效
+     *
+     * @param paramInt 0-255
+     */
+    fun setScreenBrightness(context: Context, paramInt: Int) {
+
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            if (!Settings.System.canWrite(context)) {
+                val intent = Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS)
+                intent.data = Uri.parse("package:" + context.packageName)
+                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+                context.startActivity(intent)
+            } else {
+                //有了权限,具体的动作
+                Settings.System.putInt(context.contentResolver,
+                        Settings.System.SCREEN_BRIGHTNESS, paramInt)
+                val uri = Settings.System
+                        .getUriFor("screen_brightness")
+                Log.w("当前亮度", "当前亮度======" + getScreenBrightness(context))
+                context.contentResolver.notifyChange(uri, null)
+            }
+        } else {
+            Settings.System.putInt(context.contentResolver,
+                    Settings.System.SCREEN_BRIGHTNESS, paramInt)
+            val uri = Settings.System
+                    .getUriFor("screen_brightness")
+            Log.w("当前亮度", "当前亮度======" + getScreenBrightness(context))
+            context.contentResolver.notifyChange(uri, null)
+        }
+
+    }
+}

+ 65 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/SerialPortHelper.java

@@ -0,0 +1,65 @@
+package com.wdkl.app.ncs.callingbed2.helper;
+
+import android.os.Build;
+
+import serialporttest.utils.SerialPortUtil;
+
+public class SerialPortHelper {
+
+    //MIC设置
+    public static void setHandsMIC(boolean isHandsMIC) {
+        if (Build.MODEL.equals("rk3128")) {
+            if (isHandsMIC) {
+                //打开手柄mic
+                SerialPortUtil.getInstance().sendCommand(SerialPortUtil.MIC, "0", "F");
+            } else {
+                //打开面板mic
+                SerialPortUtil.getInstance().sendCommand(SerialPortUtil.MIC, "1", "F");
+            }
+        }
+    }
+
+    /*
+     * 呼叫和通话状态
+     * data: 0 -- 正常,  1 -- 呼叫中, 2 -- 通话中
+     */
+    public static void setCallStatus(String data) {
+        if (Build.MODEL.equals("rk3128")) {
+            SerialPortUtil.getInstance().sendCommand(SerialPortUtil.CALL_STATUS, data, "F");
+        }
+    }
+
+    /**
+     * 设置卫生间紧急按钮灯状态: 0关闭1打开2闪烁
+     */
+    public static void setSosLight(String state) {
+        if (Build.MODEL.equals("rk3128")) {
+            SerialPortUtil.getInstance().sendCommand(SerialPortUtil.ULED, state, "F");
+        }
+    }
+
+    /**
+     * 门灯控制开关
+     *
+     * @param data  0  表示灯灭   1  表示灯亮
+     * @param color 0 表示灯灭  非0表示灯的颜色
+     */
+    public static void setDoorLight(int data, String color) {
+        if (Build.MODEL.equals("rk3128")) {
+            String command;
+            if (data == 0 || color == null) {
+                command = "000";
+            } else {
+                command = color;
+            }
+            SerialPortUtil.getInstance().sendCommand(SerialPortUtil.DOORLIGHT, command, "F");
+        }
+    }
+
+    //重置设备
+    public static void resetDevice() {
+        if (Build.MODEL.equals("rk3128")) {
+            SerialPortUtil.getInstance().sendCommand(SerialPortUtil.NET_STATUS, "1", "F");
+        }
+    }
+}

+ 160 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/ServerConfigDialogHelper.java

@@ -0,0 +1,160 @@
+package com.wdkl.app.ncs.callingbed2.helper;
+
+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.app.ncs.callingbed2.R;
+import com.wdkl.app.ncs.callingbed2.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;
+import com.wdkl.ncs.android.middleware.utils.StringUtil;
+
+
+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(R.string.input_password);
+                }
+            }
+        });
+
+        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, StringUtil.getResString(R.string.invalid_password), 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(R.string.input_empty);
+                } else {
+                    //保存配置
+                    CommonUtils.setUrl(BaseApplication.appContext, editUrl.getText().toString());
+                    CommonUtils.setUrlPort(BaseApplication.appContext, editPort.getText().toString());
+                    //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 = 400;
+            lp.height = 480;
+            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();
+        }
+    }
+}

+ 83 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/SoundPoolManager.java

@@ -0,0 +1,83 @@
+package com.wdkl.app.ncs.callingbed2.helper;
+
+import android.media.AudioAttributes;
+import android.media.AudioManager;
+import android.media.SoundPool;
+import android.os.Build;
+
+import com.wdkl.app.ncs.callingbed2.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(4);
+            //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(4, 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));
+        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();
+    }
+}

+ 51 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/Utils.java

@@ -0,0 +1,51 @@
+package com.wdkl.app.ncs.callingbed2.helper;
+
+import android.content.Context;
+import android.hardware.Camera;
+
+import com.wdkl.ncs.android.middleware.common.Constant;
+
+import java.lang.reflect.Method;
+
+public class Utils {
+
+    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
+    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
+    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
+    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;//4.2以上的整形标识
+    public static final int STATUS_BAR_DISABLE_NONE = 0x00000000;//取消StatusBar所有disable属性,即还原到最最原始状态
+
+    public static void checkCameraSupport() {
+        int num = Camera.getNumberOfCameras();
+        if (num > 0) {
+            Constant.supportCamera = true;
+        } else {
+            Constant.supportCamera = false;
+        }
+    }
+
+    public static void setStatusBarDisable(Context context, int disable_status) {//调用statusBar的disable方法
+        Object service = context.getSystemService("statusbar");
+        try {
+            Class<?> statusBarManager = Class.forName
+                    ("android.app.StatusBarManager");
+            Method expand = statusBarManager.getMethod("disable", int.class);
+            expand.invoke(service, disable_status);
+        } catch (Exception e) {
+            unBanStatusBar(context);
+            e.printStackTrace();
+        }
+    }
+
+    public static void unBanStatusBar(Context context) {//利用反射解除状态栏禁止下拉
+        Object service = context.getSystemService("statusbar");
+        try {
+            Class<?> statusBarManager = Class.forName
+                    ("android.app.StatusBarManager");
+            Method expand = statusBarManager.getMethod("disable", int.class);
+            expand.invoke(service, STATUS_BAR_DISABLE_NONE);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+}

+ 185 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/VoiceManagerUtil.java

@@ -0,0 +1,185 @@
+package com.wdkl.app.ncs.callingbed2.helper;
+
+import android.content.Context;
+import android.media.AudioManager;
+import android.util.Log;
+
+/**
+ * 类名称: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);
+    }
+
+}

+ 56 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/WarningDialogHelper.java

@@ -0,0 +1,56 @@
+package com.wdkl.app.ncs.callingbed2.helper;
+
+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.Button;
+
+import com.wdkl.app.ncs.callingbed2.R;
+
+public class WarningDialogHelper {
+    private static AlertDialog dialog;
+
+    public static void showDialog(Activity activity) {
+        if (dialog != null && dialog.isShowing()) {
+            return;
+        }
+
+        View contentView = LayoutInflater.from(activity).inflate(R.layout.warning_dialog_lay, null);
+        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+        builder.setView(contentView);
+        Button button = contentView.findViewById(R.id.cancel_button);
+        button.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                AppUpdateHelper.reboot(activity, true);
+            }
+        });
+
+        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 = 240;
+            lp.gravity = Gravity.CENTER;
+            window.setAttributes(lp);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public static void dismiss() {
+        if (dialog != null && dialog.isShowing()) {
+            dialog.dismiss();
+        }
+    }
+}

+ 242 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/helper/XCrashUtils.java

@@ -0,0 +1,242 @@
+package com.wdkl.app.ncs.callingbed2.helper;
+
+import android.app.AlarmManager;
+import android.app.Application;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Build;
+import android.util.Log;
+
+import com.wdkl.app.ncs.callingbed2.BuildConfig;
+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);
+            }
+
+            if (Build.MODEL.equals("rk3128") || Build.MODEL.equals("rk3288")) {
+                AppUpdateHelper.reboot(app, false);
+            } else {
+                AppUpdateHelper.restartApp(app);
+            }
+        }
+    };
+
+    public void init(Application application) {
+        Log.d(TAG, "xCrash SDK init: start");
+        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, TAG, 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);
+    }
+
+}

+ 20 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/launch/Callingbed2Launch.kt

@@ -0,0 +1,20 @@
+package com.wdkl.app.ncs.callingbed2.launch
+
+import com.enation.javashop.android.jrouter.external.annotation.Router
+import com.wdkl.app.ncs.callingbed2.di.Callingbed2Component
+import com.wdkl.app.ncs.callingbed2.di.DaggerCallingbed2Component
+import com.wdkl.ncs.android.lib.base.BaseLaunch
+import com.wdkl.ncs.android.middleware.di.DaggerManager
+
+@Router(path = "/callingbed2/launch")
+class Callingbed2Launch :BaseLaunch() {
+    companion object {
+        lateinit var component:Callingbed2Component
+    }
+
+    override fun moduleInit() {
+        component = DaggerCallingbed2Component.builder()
+                .applicationComponent(DaggerManager.APPLICATION_COMPONENT)
+                .build()
+    }
+}

+ 406 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/settings/SettingConfig.java

@@ -0,0 +1,406 @@
+package com.wdkl.app.ncs.callingbed2.settings;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+
+
+public class SettingConfig {
+
+
+    private static final String SP_NAME = "SP_BED_FUNCTION";
+
+    //白昼设置白天的初始时间设置
+    private static final String KEY_SP_INITIAL_DAY_TIME = "KEY_SP_INITIAL_DAY_TIME";
+    private static final String initial_day_time = "07:00";
+    private static final String KEY_SP_INITIAL_DAY_TIME_LOCATION = "KEY_SP_INITIAL_DAY_TIME_LOCATION";
+    private static final String initial_day_time_location = "12";
+
+
+    //白昼设置白天的结束时间设置
+    private static final String KEY_SP_END_OF_DAY = "KEY_SP_END_OF_DAY";
+    private static final String end_of_day = "19:00";
+    //白昼设置白天的结束时间设置
+    private static final String KEY_SP_END_OF_DAY_LOCATION = "KEY_SP_END_OF_DAY_LOCATION";
+    private static final String end_of_day_location = "38";
+
+
+    //分机白天亮度
+    private static final String KEY_SP_EXTENSION_DAYTIME_BRIGHTNESS = "KEY_SP_EXTENSION_DAYTIME_BRIGHTNESS";
+    private static final int extension_daytime_brightness = 80;
+    //分机晚上亮度
+    private static final String KEY_SP_EXTENSION_NIGHT_BRIGHTNESS = "KEY_SP_EXTENSION_NIGHT_BRIGHTNESS";
+    private static final int extension_night_brightness = 50;
+
+    //分机LED白天亮度
+    private static final String KEY_SP_EXTENSION_DAYTIME_LED_BRIGHTNESS = "KEY_SP_EXTENSION_DAYTIME_LED_BRIGHTNESS";
+    private static final int extension_daytime_led_brightness = 80;
+    //分机LED晚上亮度
+    private static final String KEY_SP_EXTENSION_NIGHT_LED_BRIGHTNESS = "KEY_SP_EXTENSION_NIGHT_LED_BRIGHTNESS";
+    private static final int extension_night_led_brightness = 50;
+
+    //分机白天系统音量
+    private static final String KEY_SP_EXTENSION_DAYTIME_SYSTEM_VOLUME = "KEY_SP_EXTENSION_DAYTIME_SYSTEM_VOLUME";
+    private static final int extension_daytime_system_volume = 100;
+    //分机晚上系统音量
+    private static final String KEY_SP_EXTENSION_NIGHT_SYSTEM_VOLUME = "KEY_SP_EXTENSION_NIGHT_SYSTEM_VOLUME";
+    private static final int extension_night_system_volume = 70;
+
+    //分机手柄录入音量
+    private static final String KEY_SP_THE_EXTENSION_HANDLR_RECORDS_THE_VOLUME = "KEY_SP_THE_EXTENSION_HANDLR_RECORDS_THE_VOLUME";
+    private static final int the_extension_handle_records_the_volume = 50;
+
+    //分机通话音量
+    private static final String KEY_SP_EXTENSION_CALL_VOLUME = "KEY_SP_EXTENSION_CALL_VOLUME";
+    private static final int extension_call_volume = 100;
+
+    //呼叫超时时间
+    private static final String KEY_SP_SIP_OVERTIME = "KEY_SP_SIP_OVERTIME";
+    private static final int sip_over_time = 30;
+
+    //息屏超时时间
+    private static final String KEY_SP_SLEEP_TIME = "KEY_SP_SLEEP_TIME";
+    private static final int sleep_time = 30;
+
+    //网络异常重启次数
+    private static final String KEY_SP_NET_ERR_RESET_COUNT = "KEY_SP_NET_ERR_RESET_COUNT";
+    //是否自动接通
+    private static final String KEY_SP_AUTO_ANSWER = "KEY_SP_AUTO_ANSWER";
+
+    private static final String KEY_SP_BROADCAST_VOLUME = "KEY_SP_BROADCAST_VOLUME";
+    private static final String KEY_SP_RECORD_ENABLE = "KEY_SP_RECORD_ENABLE";
+
+    //默认语言
+    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();
+    }
+
+    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 getExtensionDaytimeBrightness(Context context) {
+        return getSP(context).getInt(KEY_SP_EXTENSION_DAYTIME_BRIGHTNESS, extension_daytime_brightness);
+    }
+
+    /**
+     * 设置分机白天亮度
+     *
+     * @param value
+     */
+    public static void setExtensionDaytimeBrightness(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_EXTENSION_DAYTIME_BRIGHTNESS, value).apply();
+    }
+
+    /**
+     * 获取分机晚上亮度
+     *
+     * @return
+     */
+    public static int getExtensionNightBrightness(Context context) {
+        return getSP(context).getInt(KEY_SP_EXTENSION_NIGHT_BRIGHTNESS, extension_night_brightness);
+    }
+
+    /**
+     * 设置分机晚上亮度
+     *
+     * @param value
+     */
+    public static void setExtensionNightBrightness(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_EXTENSION_NIGHT_BRIGHTNESS, value).apply();
+    }
+
+    /**
+     * 获取分机LED白天亮度
+     *
+     * @return
+     */
+    public static int getExtensionDaytimeLEDBrightness(Context context) {
+        return getSP(context).getInt(KEY_SP_EXTENSION_DAYTIME_LED_BRIGHTNESS, extension_daytime_led_brightness);
+    }
+
+    /**
+     * 设置分机LED白天亮度
+     *
+     * @param value
+     */
+    public static void setExtensionDaytimeLEDBrightness(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_EXTENSION_DAYTIME_LED_BRIGHTNESS, value).apply();
+    }
+
+    /**
+     * 获取分机LED晚上亮度
+     *
+     * @return
+     */
+    public static int getExtensionNightLEDBrightness(Context context) {
+        return getSP(context).getInt(KEY_SP_EXTENSION_NIGHT_LED_BRIGHTNESS, extension_night_led_brightness);
+    }
+
+    /**
+     * 设置分机LED晚上亮度
+     *
+     * @param value
+     */
+    public static void setExtensionNightLEDBrightness(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_EXTENSION_NIGHT_LED_BRIGHTNESS, value).apply();
+    }
+
+
+    /**
+     * 获取分机白天系统音量
+     *
+     * @return
+     */
+    public static int getExtensionDaytimeSystemVolume(Context context) {
+        return getSP(context).getInt(KEY_SP_EXTENSION_DAYTIME_SYSTEM_VOLUME, extension_daytime_system_volume);
+    }
+
+    /**
+     * 设置分机白天系统音量
+     *
+     * @param value
+     */
+    public static void setExtensionDaytimeSystemVolume(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_EXTENSION_DAYTIME_SYSTEM_VOLUME, value).apply();
+    }
+
+    /**
+     * 获取分机晚上系统音量
+     *
+     * @return
+     */
+    public static int getExtensionNightSystemVolume(Context context) {
+        return getSP(context).getInt(KEY_SP_EXTENSION_NIGHT_SYSTEM_VOLUME, extension_night_system_volume);
+    }
+
+    /**
+     * 设置分机晚上系统音量
+     *
+     * @param value
+     */
+    public static void setExtensionNightSystemVolume(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_EXTENSION_NIGHT_SYSTEM_VOLUME, value).apply();
+    }
+
+
+
+    /**
+     * 获取分机手柄录入音量
+     *
+     * @return
+     */
+    public static int getTheExtensionHandleRecordsTheVolume(Context context) {
+        return getSP(context).getInt(KEY_SP_THE_EXTENSION_HANDLR_RECORDS_THE_VOLUME, the_extension_handle_records_the_volume);
+    }
+
+    /**
+     * 设置分机手柄录入音量
+     *
+     * @param value
+     */
+    public static void setTheExtensionHandleRecordsTheVolume(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_THE_EXTENSION_HANDLR_RECORDS_THE_VOLUME, 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();
+    }
+
+
+    /**
+     * 获取白昼设置白天的初始时间
+     *
+     * @return
+     */
+    public static String getInitialDayTime(Context context) {
+        return getSP(context).getString(KEY_SP_INITIAL_DAY_TIME, initial_day_time);
+    }
+
+    /**
+     * 设置白昼白天的初始时间
+     *
+     * @param value
+     */
+    public static void setInitialDayTime(Context context, String value) {
+        getEditor(context).putString(KEY_SP_INITIAL_DAY_TIME, value).apply();
+    }
+
+    /**
+     * 获取白昼设置白天的初始时间位置
+     *
+     * @return
+     */
+    public static String getInitialDayTimeLocation(Context context) {
+        return getSP(context).getString(KEY_SP_INITIAL_DAY_TIME_LOCATION, initial_day_time_location);
+    }
+
+    /**
+     * 设置白昼白天的初始时间位置
+     *
+     * @param value
+     */
+    public static void setInitialDayTimeLocation(Context context, String value) {
+        getEditor(context).putString(KEY_SP_INITIAL_DAY_TIME_LOCATION, value).apply();
+    }
+
+
+
+    /**
+     * 设置白昼白天的结束时间
+     *
+     * @param value
+     */
+    public static void setEndOfDay(Context context, String value) {
+        getEditor(context).putString(KEY_SP_END_OF_DAY, value).apply();
+    }
+
+    /**
+     * 获取白昼设置白天的结束时间
+     *
+     * @return
+     */
+    public static String getEndOfDay(Context context) {
+        return getSP(context).getString(KEY_SP_END_OF_DAY, end_of_day);
+    }
+
+    /**
+     * 设置白昼白天的结束时间位置
+     *
+     * @param value
+     */
+    public static void setEndOfDayLocation(Context context, String value) {
+        getEditor(context).putString(KEY_SP_END_OF_DAY_LOCATION, value).apply();
+    }
+
+    /**
+     * 获取白昼设置白天的结束时间位置
+     *
+     * @return
+     */
+    public static String getEndOfDayLocation(Context context) {
+        return getSP(context).getString(KEY_SP_END_OF_DAY_LOCATION, end_of_day_location);
+    }
+
+    /**
+     * 设置呼叫超时时间
+     *
+     * @param value
+     */
+    public static void setSipOverTime(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_SIP_OVERTIME, value).apply();
+    }
+
+    /**
+     * 获取呼叫超时时间
+     *
+     * @return
+     */
+    public static int getSipOverTime(Context context) {
+        return getSP(context).getInt(KEY_SP_SIP_OVERTIME, sip_over_time);
+    }
+
+    /**
+     * 设置息屏时间
+     *
+     * @param value
+     */
+    public static void setSleepTime(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_SLEEP_TIME, value).apply();
+    }
+
+    /**
+     * 获取息屏时间
+     *
+     * @return
+     */
+    public static int getSleepTime(Context context) {
+        return getSP(context).getInt(KEY_SP_SLEEP_TIME, sleep_time);
+    }
+
+    /**
+     * 获取网络异常重启次数
+     *
+     * @return
+     */
+    public static int getNetErrResetCount(Context context) {
+        return getSP(context).getInt(KEY_SP_NET_ERR_RESET_COUNT, 0);
+    }
+
+    /**
+     * 设置网络异常重启次数
+     *
+     * @param value
+     */
+    public static void setNetErrResetCount(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_NET_ERR_RESET_COUNT, value).apply();
+    }
+
+    public static int getBroadcastVol(Context context) {
+        return getSP(context).getInt(KEY_SP_BROADCAST_VOLUME, 100);
+    }
+
+    public static void setBroadcastVol(Context context, int vol) {
+        getEditor(context).putInt(KEY_SP_BROADCAST_VOLUME, vol).apply();
+    }
+
+    public static boolean getAutoAnswer(Context context) {
+        return getSP(context).getBoolean(KEY_SP_AUTO_ANSWER, false);
+    }
+
+    public static void setAutoAnswer(Context context, boolean value) {
+        getEditor(context).putBoolean(KEY_SP_AUTO_ANSWER, value).apply();
+    }
+
+    public static boolean getRecordEnable(Context context) {
+        return getSP(context).getBoolean(KEY_SP_RECORD_ENABLE, false);
+    }
+
+    public static void setRecordEnable(Context context, boolean enable) {
+        getEditor(context).putBoolean(KEY_SP_RECORD_ENABLE, enable).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();
+    }
+
+
+}

+ 579 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/sip/SipHelper.java.bak

@@ -0,0 +1,579 @@
+package com.wdkl.app.ncs.callingbed2.sip;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.CountDownTimer;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.util.Log;
+
+import com.vvsip.ansip.IVvsipService;
+import com.vvsip.ansip.IVvsipServiceListener;
+import com.vvsip.ansip.VvsipCall;
+import com.vvsip.ansip.VvsipService;
+import com.vvsip.ansip.VvsipServiceBinder;
+import com.vvsip.ansip.VvsipTask;
+import com.wdkl.app.ncs.callingbed2.common.MessageEvent;
+import com.wdkl.app.ncs.callingbed2.helper.NetHelper;
+
+
+import org.greenrobot.eventbus.EventBus;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.wdkl.app.ncs.callingbed2.common.Constant.EVENT_SIP_REGISTER_STATUS;
+import static com.wdkl.app.ncs.callingbed2.sip.SipStatus.REGISTERCOM;
+import static com.wdkl.app.ncs.callingbed2.sip.SipStatus.REGISTERFAIL;
+import static com.wdkl.app.ncs.callingbed2.sip.SipStatus.REGISTERING;
+import static com.vvsip.ansip.VvsipTask.EXOSIP_CALL_CLOSED;
+
+
+public class SipHelper {
+
+    private final static String SIP_IP_END = ":5060";
+
+    private static String sipIP = "";
+    private static String sipID = "";
+    private static String sipPWD = "";
+
+    /**
+     * Sip启动注册.
+     */
+    protected int mSipRegisterTime = 5000;
+    private Handler sipRegisterHandler = null;
+    private Runnable sipRegisterRunnable = null;
+
+    /**
+     * SIP信息
+     */
+    public static final String SipInfoTag = "SipInfo";
+    /**
+     * 电话呼叫对象
+     */
+    private List<VvsipCall> mVvsipCalls = null;
+
+
+    private static SipHelper sipHelper;
+
+    public Handler getSipRegisterHandler() {
+        return sipRegisterHandler;
+    }
+
+    public Runnable getSipRegisterRunnable() {
+        return sipRegisterRunnable;
+    }
+
+    public List<VvsipCall> getmVvsipCalls() {
+        return mVvsipCalls;
+    }
+
+    private IVvsipServiceListener sipListner;
+
+
+    private Context mContext;
+
+    public static SipHelper getInstance() {
+        if (sipHelper == null) {
+            synchronized (SipHelper.class) {
+                if (sipHelper == null) {
+                    sipHelper = new SipHelper();
+                }
+            }
+        }
+        return sipHelper;
+    }
+
+    /**
+     * Instantiates a new Sip register util.
+     */
+    private SipHelper() {
+        if (mVvsipCalls == null) {
+            mVvsipCalls = new ArrayList<VvsipCall>();
+        }
+
+        // Runnable exiting the splash screen and launching the menu
+        sipRegisterRunnable = new Runnable() {
+            public void run() {
+                isSuccessRegisterSip();
+            }
+        };
+
+        // Run the exitRunnable in in mSipRegisterTime ms
+        sipRegisterHandler = new Handler();
+
+        IVvsipService sipservice = VvsipService.getService();
+        if (sipservice != null) {
+            sipRegisterHandler.postDelayed(sipRegisterRunnable, 3000);
+            return;
+        }
+        sipRegisterHandler.postDelayed(sipRegisterRunnable, mSipRegisterTime);
+    }
+
+    public void initSip(Context context, String ip, String id, String pwd) {
+        mContext = context;
+        sipIP = ip;
+        sipID = id;
+        sipPWD = pwd;
+    }
+
+    public void setSipListner(IVvsipServiceListener listner) {
+        sipListner = listner;
+    }
+
+    /*public void addSipListner(IVvsipServiceListener listner) {
+        IVvsipService sipService = VvsipService.getService();
+        if (sipService != null && listner != null) {
+            sipService.addListener(listner);
+            Log.d("sip", "add sip listner");
+        }
+    }
+
+    public void removeSipListner(IVvsipServiceListener listner) {
+        IVvsipService sipService = VvsipService.getService();
+        if (sipService != null && listner != null) {
+            sipService.removeListener(listner);
+            Log.d("sip", "remove sip listner");
+        }
+    }*/
+
+    /**
+     * 检测Sip服务是否注册成功
+     */
+    public void isSuccessRegisterSip() {
+        VvsipTask vvsipTask = VvsipTask.getVvsipTask();
+        if (vvsipTask != null && VvsipTask.global_failure != 0) {
+            /**
+             * ==================================sip服务启动失败 ================================
+             */
+        }
+    }
+
+    /**
+     * 注销Sip服务
+     */
+    public void unRegisterSip() {
+        //LogUtil.i(SipInfoTag, "lifecycle // onDestroy");
+
+        IVvsipService sipservice = VvsipService.getService();
+        if (sipservice != null && sipListner != null) {
+            sipservice.removeListener(sipListner);
+        }
+
+        getSipServiceStartHandler().removeCallbacks(getSipServiceStartRunnable());
+        sipRegisterHandler.removeCallbacks(sipRegisterRunnable);
+        if (getSipServiceConnection() != null && isRegister) {
+            try {
+                mContext.unbindService(getSipServiceConnection());
+                setSipServiceConnection(null);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+        if (mVvsipCalls != null) {
+            mVvsipCalls.clear();
+            mVvsipCalls = null;
+        }
+
+        //Log.i(SipInfoTag, "lifecycle // onDestroy");
+    }
+
+    public static String sipStatus = "";
+
+    /**
+     * Sip信息获取
+     */
+    public void obtainSipInfo() {
+        if (sipStatus.equals(REGISTERCOM) && NetHelper.NetConn) {//sip注册成功并且以太网连上
+            return;
+        }
+        IVvsipService sipService = VvsipService.getService();
+        if (sipService != null && sipListner != null) {
+            //sipService.addListener(sipListner);
+            sipService.setMessageHandler(messageHandler);
+        } else {
+            //LogUtil.i(SipInfoTag, "lifecycle // _service==null");
+        }
+        sipRegister();
+        failUiRefreshSip();
+    }
+
+    private void failUiRefreshSip() {
+        if (!NetHelper.NetConn) {
+            sipStatus = REGISTERFAIL;
+            EventBus.getDefault().post(new MessageEvent(REGISTERFAIL, EVENT_SIP_REGISTER_STATUS));
+            if (mSipThread != null) {
+                mSipThread.interrupt();
+                mSipThread = null;
+            }
+            //LogUtil.e(SipInfoTag, "以太网断开,SIP UI状态刷新为失败");
+        }
+    }
+
+
+    /**
+     * Sip信息
+     */
+    private String sipinfo = "";
+    private static int handleCount = 0;
+    //Sip註冊次數
+    private CountDownTimer mCountDownAutoTimer;
+    @SuppressLint("HandlerLeak")
+    private Handler messageHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            //LogUtil.i("QASE", "handleMessage==" + " msg.obj==" + msg.obj.toString() + " msg.what==" + msg.what);
+            //LogUtil.i(SipInfoTag, "#" + msg.obj);
+            sipinfo = "" + msg.obj + sipinfo;
+            //LogUtil.i(SipInfoTag, "Sip信息" + sipinfo);
+
+            if (msg.what == 22) {//释放资源
+                //EventBus.getDefault().post(new MessageEvent(msg.what, EVENT_SIP_REGISTER_STATUS));
+            }
+
+            if (sipinfo.contains("200 OK")) {//注册成功
+                sipStatus = REGISTERCOM;
+                EventBus.getDefault().post(new MessageEvent(REGISTERCOM, EVENT_SIP_REGISTER_STATUS));
+                if (mSipThread != null) {
+                    mSipThread.interrupt();
+                    mSipThread = null;
+                }
+                if (msg.obj.toString().contains("408")) {//超时
+                    sipStatus = REGISTERFAIL;
+                    EventBus.getDefault().post(new MessageEvent(REGISTERFAIL, EVENT_SIP_REGISTER_STATUS));
+                    sipRegister();
+                }
+            } else {//注册失败
+                sipStatus = REGISTERFAIL;
+                EventBus.getDefault().post(new MessageEvent(REGISTERFAIL, EVENT_SIP_REGISTER_STATUS));
+                if (mSipThread != null) {
+                    mSipThread.interrupt();
+                    mSipThread = null;
+                }
+                sipRegister();
+            }
+            failUiRefreshSip();
+
+            if (msg.obj.toString().contains("autocall")) {
+                VvsipCall pCall = null;
+                //LogUtil.e(SipInfoTag, "onClick1");
+                for (VvsipCall _pCall : mVvsipCalls) {
+                    if (_pCall.cid > 0)
+                        //LogUtil.e(SipInfoTag, "state#" + _pCall.mState);
+                        if (_pCall.cid > 0 && _pCall.mState <= 2) {
+                            pCall = _pCall;
+                            break;
+                        }
+                }
+                //LogUtil.e(SipInfoTag, "onClick2");
+                if (pCall == null)
+                    return;
+                //LogUtil.e(SipInfoTag, "onClick3#" + pCall.mState);
+                IVvsipService _service = VvsipService.getService();
+                if (_service == null)
+                    return;
+                VvsipTask _vvsipTask = _service.getVvsipTask();
+                if (_vvsipTask == null)
+                    return;
+                pCall.stop();
+                _service.setSpeakerModeOff();
+            }
+        }
+    };
+
+    /**
+     * ====================Sip注册======================
+     */
+    private Thread mSipThread;
+
+    private static class SipThread extends Thread {
+        WeakReference<Activity> mThreadCallingBedActivity;
+
+        private SipThread(Activity activity) {
+            mThreadCallingBedActivity = new WeakReference<Activity>(activity);
+        }
+
+        @Override
+        public void run() {
+            super.run();
+            if (mThreadCallingBedActivity == null)
+                return;
+            if (mThreadCallingBedActivity.get() != null) {
+                IVvsipService sipService = VvsipService.getService();
+                try {
+                    if (sipService != null && !SipHelper.getInstance().sipinfo.contains("200 OK") && NetHelper.NetConn) {
+                        sipStatus = REGISTERING;
+                        EventBus.getDefault().post(new MessageEvent(REGISTERING, EVENT_SIP_REGISTER_STATUS));
+                        sipService.register(sipIP + SIP_IP_END, sipID, sipPWD);
+                        handleCount++;
+                        Log.e(SipInfoTag, "以太网连接,SIP UI状态刷新为注册中");
+                    } else if (sipService != null && SipHelper.getInstance().sipinfo.contains("200 OK")) {
+                        sipStatus = REGISTERCOM;
+                        EventBus.getDefault().post(new MessageEvent(REGISTERCOM, EVENT_SIP_REGISTER_STATUS));
+                    }
+                } catch (NullPointerException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    private void sipRegister() {
+        synchronized (this) {
+            mSipThread = new SipThread((Activity) mContext);
+            if (handleCount < 3) {
+                if (mCountDownAutoTimer == null) {
+                    mCountDownAutoTimer = new CountDownTimer(10000, 1000) {
+                        @Override
+                        public void onTick(long l) {
+                        }
+
+                        @Override
+                        public void onFinish() {
+                            handleCount = 0;
+                            if (mSipThread != null) {
+                                mSipThread.start();
+                            }
+                            if (mCountDownAutoTimer != null) {
+                                mCountDownAutoTimer.cancel();
+                                mCountDownAutoTimer = null;
+                            }
+                        }
+                    };
+                    mCountDownAutoTimer.start();
+                }
+                return;
+            } else {
+                if (mCountDownAutoTimer != null) {
+                    mCountDownAutoTimer.cancel();
+                    mCountDownAutoTimer = null;
+                }
+            }
+            if (handleCount == 0) {
+                mSipThread.start();
+            }
+        }
+    }
+
+
+    public void setmSipThread(Thread mSipThread) {
+        this.mSipThread = mSipThread;
+    }
+
+    public Thread getmSipThread() {
+        return mSipThread;
+    }
+
+    /**
+     * 开始通话
+     */
+    public void startCall(String sipUseName) {
+        IVvsipService sipService = VvsipService.getService();
+        if (sipService == null) return;
+        //----------------------------------------------携带呼叫列表转接床头机的Mac地址--------------------------------------------------//
+        sipService.initiateOutgoingCall(sipUseName, "");
+    }
+
+    /**
+     * 结束通话
+     */
+    public void endCall() {
+        VvsipCall call = null;
+        for (VvsipCall pCall : mVvsipCalls) {
+            if (pCall.cid > 0 && pCall.mState <= 2) {
+                call = pCall;
+                break;
+            }
+        }
+        if (call == null) return;
+        IVvsipService sipService = VvsipService.getService();
+        if (sipService == null) return;
+        VvsipTask sipTask = sipService.getVvsipTask();
+        if (sipTask == null) return;
+        VvsipService.getService().mainEndCall(EXOSIP_CALL_CLOSED);
+        call.stop();
+        sipService.setSpeakerModeOff();
+        sipService.stopPlayer();
+        sipService.setAudioNormalMode();
+    }
+
+    /**
+     * 添加一个电话呼叫对象
+     *
+     * @param call
+     */
+    public void addCallObject(final VvsipCall call) {
+        try {
+            if (call == null) {
+                return;
+            }
+
+            if (mVvsipCalls == null)
+                return;
+            mVvsipCalls.add(call);
+        } catch (Exception e) {
+            //LogUtil.e(SipInfoTag, "onNewVvsipCallEvent: " + e);
+        }
+    }
+
+    /**
+     * 移除一个电话呼叫对象
+     *
+     * @param call
+     */
+    public void removeCallObject(final VvsipCall call) {
+        try {
+            if (call == null) {
+                return;
+            }
+
+            // 4 crash detected here for 4.0.9 with mVvsipCalls=NULL
+            if (mVvsipCalls == null)
+                return;
+            mVvsipCalls.remove(call);
+        } catch (Exception e) {
+            //Log.e(SipInfoTag, "onRemoveVvsipCallEvent: " + e);
+        }
+    }
+
+    /**
+     * 自动接电话
+     */
+    public void autoTalking() {
+        if (mVvsipCalls == null) {
+            mVvsipCalls = new ArrayList<VvsipCall>();
+        }
+        for (VvsipCall _pCall : mVvsipCalls) {
+            if (_pCall.cid > 0 && _pCall.mState < 2 && _pCall.mIncomingCall) {
+                // ANSWER EXISTING CALL
+                int i = _pCall.answer(200, 1);
+              //LogUtil.d(SipInfoTag, "ANSWER EXISTING CALL");
+                IVvsipService _service = VvsipService.getService();
+                if (_service != null) {
+                    if (i >= 0) {
+                        _service.stopPlayer();
+                        _service.setSpeakerModeOff();
+                        _service.setAudioInCallMode();
+                    }
+                }
+                break;
+            }
+        }
+    }
+
+    public static boolean isServiceRunning(Context context, String className) {
+        boolean isRunning = false;
+        ActivityManager activityManager = (ActivityManager) context
+                .getSystemService(Context.ACTIVITY_SERVICE);
+        List<ActivityManager.RunningServiceInfo> serviceList = activityManager
+                .getRunningServices(30);
+
+        if (!(serviceList.size() > 0)) {
+            return false;
+        }
+
+        for (int i = 0; i < serviceList.size(); i++) {
+            if (serviceList.get(i).service.getClassName().equals(className) == true) {
+                isRunning = true;
+                break;
+            }
+        }
+        return isRunning;
+    }
+
+    /**
+     * #############################
+     * <p>
+     * Sip启动服务.
+     * <p>
+     * #############################
+     */
+    private static Handler sipServiceStartHandler = null;
+    private static Runnable sipServiceStartRunnable = null;
+    private static ServiceConnection sipServiceConnection;
+
+    public static Runnable getSipServiceStartRunnable() {
+        return sipServiceStartRunnable;
+    }
+
+    public static Handler getSipServiceStartHandler() {
+        return sipServiceStartHandler;
+    }
+
+    public static ServiceConnection getSipServiceConnection() {
+        return sipServiceConnection;
+    }
+
+    public static void setSipServiceConnection(ServiceConnection sipServiceConnections) {
+        sipServiceConnection = sipServiceConnections;
+    }
+
+    /**
+     * 启动服务
+     */
+    public static Boolean isRegister = false;//是否注册
+
+    public void sipStartService() {
+        sipServiceStartHandler = new Handler();
+
+        sipServiceStartRunnable = new Runnable() {
+            public void run() {
+                if (mContext == null) {
+                    sipServiceStartHandler.postDelayed(sipServiceStartRunnable, 1000);
+                    return;
+                }
+                Intent intent = new Intent(mContext.getApplicationContext(), VvsipService.class);
+                mContext.startService(intent);
+
+                sipServiceConnection = new ServiceConnection() {
+                    public void onServiceConnected(ComponentName name, IBinder service) {
+                        IVvsipService sipservice = ((VvsipServiceBinder) service).getService();
+                        if (sipservice != null && sipListner != null) {
+                            //LogUtil.i(SipInfoTag, "Connected!");
+                            sipservice.addListener(sipListner);
+                            SipHelper.getInstance().obtainSipInfo();//Sip信息获取
+                        }
+                    }
+
+                    public void onServiceDisconnected(ComponentName name) {
+                        //LogUtil.i(SipInfoTag, "Disconnected!");
+                    }
+                };
+
+                isRegister = mContext.bindService(intent, sipServiceConnection, Context.BIND_AUTO_CREATE);
+            }
+        };
+
+        sipServiceStartHandler.postDelayed(sipServiceStartRunnable, 0);
+    }
+
+    /**
+     * 用来解析错误代码
+     */
+    public static String analyseErrorCode(String errorCode) {
+        switch (errorCode) {
+            case "200":
+                return "成功";
+            case "408":
+                return "请求超时";
+            case "400":
+                return "服务器不支持请求的语法";
+            case "401":
+                return "未授权";
+            case "403":
+                return "服务器禁止请求";
+            case "404":
+                return "服务器找不到";
+            default:
+                return "未知错误";
+        }
+    }
+
+}

+ 17 - 0
android_bed/src/main/h7_3128/java/com/wdkl/app/ncs/callingbed2/sip/SipStatus.java.bak

@@ -0,0 +1,17 @@
+package com.wdkl.app.ncs.callingbed2.sip;
+
+public class SipStatus {
+    /**
+     * 注册中
+     */
+    public static final String REGISTERING = "register_ing";
+    /**
+     * 注册失败
+     */
+    public static final String REGISTERFAIL = "register_fail";
+    /**
+     * 注册完成
+     */
+    public static final String REGISTERCOM = "register_com";
+
+}

+ 7 - 0
android_bed/src/main/h7_3128/res/anim/slide_down_in.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+    <translate
+        android:fromYDelta="100%p"
+        android:toYDelta="0%p"
+        android:duration="300"/>
+</set>

+ 7 - 0
android_bed/src/main/h7_3128/res/anim/slide_left_in.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+    <translate
+        android:fromXDelta="-100%p"
+        android:toXDelta="0%p"
+        android:duration="300"/>
+</set>

+ 7 - 0
android_bed/src/main/h7_3128/res/anim/slide_right_out.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+    <translate
+        android:fromXDelta="0%p"
+        android:toXDelta="100%p"
+        android:duration="300"/>
+</set>

+ 7 - 0
android_bed/src/main/h7_3128/res/anim/slide_up_out.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+    <translate
+        android:fromYDelta="0%p"
+        android:toYDelta="-100%p"
+        android:duration="300"/>
+</set>

Dosya farkı çok büyük olduğundan ihmal edildi
+ 34 - 0
android_bed/src/main/h7_3128/res/drawable-v24/ic_launcher_foreground.xml


BIN
android_bed/src/main/h7_3128/res/drawable/ic_answer.png


BIN
android_bed/src/main/h7_3128/res/drawable/ic_answer_normal.png


BIN
android_bed/src/main/h7_3128/res/drawable/ic_answer_press.png


+ 5 - 0
android_bed/src/main/h7_3128/res/drawable/ic_baseline_backspace.xml

@@ -0,0 +1,5 @@
+<vector android:height="64dp" android:tint="#FF0000"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="64dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M22,3L7,3c-0.69,0 -1.23,0.35 -1.59,0.88L0,12l5.41,8.11c0.36,0.53 0.9,0.89 1.59,0.89h15c1.1,0 2,-0.9 2,-2L24,5c0,-1.1 -0.9,-2 -2,-2zM19,15.59L17.59,17 14,13.41 10.41,17 9,15.59 12.59,12 9,8.41 10.41,7 14,10.59 17.59,7 19,8.41 15.41,12 19,15.59z"/>
+</vector>

+ 5 - 0
android_bed/src/main/h7_3128/res/drawable/ic_baseline_cancel.xml

@@ -0,0 +1,5 @@
+<vector android:height="64dp" android:tint="#FF0000"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="64dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M12,2C6.47,2 2,6.47 2,12s4.47,10 10,10 10,-4.47 10,-10S17.53,2 12,2zM17,15.59L15.59,17 12,13.41 8.41,17 7,15.59 10.59,12 7,8.41 8.41,7 12,10.59 15.59,7 17,8.41 13.41,12 17,15.59z"/>
+</vector>

+ 5 - 0
android_bed/src/main/h7_3128/res/drawable/ic_baseline_pause.xml

@@ -0,0 +1,5 @@
+<vector android:height="64dp" android:tint="#E84C02"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="64dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM11,16L9,16L9,8h2v8zM15,16h-2L13,8h2v8z"/>
+</vector>

+ 5 - 0
android_bed/src/main/h7_3128/res/drawable/ic_baseline_play.xml

@@ -0,0 +1,5 @@
+<vector android:height="64dp" android:tint="#E84C02"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="64dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM10,16.5v-9l6,4.5 -6,4.5z"/>
+</vector>

BIN
android_bed/src/main/h7_3128/res/drawable/ic_hangup.png


BIN
android_bed/src/main/h7_3128/res/drawable/ic_hangup_normal.png


BIN
android_bed/src/main/h7_3128/res/drawable/ic_hangup_press.png


+ 170 - 0
android_bed/src/main/h7_3128/res/drawable/ic_launcher_background.xml

@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="108dp"
+    android:height="108dp"
+    android:viewportWidth="108"
+    android:viewportHeight="108">
+    <path
+        android:fillColor="#008577"
+        android:pathData="M0,0h108v108h-108z" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M9,0L9,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,0L19,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M29,0L29,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M39,0L39,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M49,0L49,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M59,0L59,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M69,0L69,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M79,0L79,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M89,0L89,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M99,0L99,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,9L108,9"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,19L108,19"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,29L108,29"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,39L108,39"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,49L108,49"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,59L108,59"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,69L108,69"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,79L108,79"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,89L108,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,99L108,99"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,29L89,29"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,39L89,39"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,49L89,49"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,59L89,59"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,69L89,69"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,79L89,79"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M29,19L29,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M39,19L39,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M49,19L49,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M59,19L59,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M69,19L69,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M79,19L79,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+</vector>

BIN
android_bed/src/main/h7_3128/res/drawable/ic_nurse.png


BIN
android_bed/src/main/h7_3128/res/drawable/ic_nurse_call.png


+ 22 - 0
android_bed/src/main/h7_3128/res/drawable/po_seekbar.xml

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@android:id/background">
+        <shape>
+            <solid android:color="#BFBFBF" />
+        </shape>
+    </item>
+    <item android:id="@android:id/secondaryProgress">
+        <clip>
+            <shape>
+                <solid android:color="#BFBFBF" />
+            </shape>
+        </clip>
+    </item>
+    <item android:id="@android:id/progress">
+        <clip>
+            <shape>
+                <solid android:color="#609dff" />
+            </shape>
+        </clip>
+    </item>
+</layer-list>

BIN
android_bed/src/main/h7_3128/res/drawable/seek_bar.png


+ 9 - 0
android_bed/src/main/h7_3128/res/drawable/seekbar_thumb.xml

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

+ 5 - 0
android_bed/src/main/h7_3128/res/drawable/selector_action_button_bg.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="@mipmap/bg_action_button_p" android:state_pressed="true"/>
+    <item android:drawable="@mipmap/bg_action_button_n"/>
+</selector>

+ 5 - 0
android_bed/src/main/h7_3128/res/drawable/selector_action_button_text_color.xml

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

+ 5 - 0
android_bed/src/main/h7_3128/res/drawable/selector_bottom_btn_text_color.xml

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

+ 5 - 0
android_bed/src/main/h7_3128/res/drawable/selector_call_answer.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="@drawable/ic_answer_press" android:state_pressed="true"/>
+    <item android:drawable="@drawable/ic_answer_normal"/>
+</selector>

+ 5 - 0
android_bed/src/main/h7_3128/res/drawable/selector_call_end.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="@drawable/ic_hangup_press" android:state_pressed="true"/>
+    <item android:drawable="@drawable/ic_hangup_normal"/>
+</selector>

+ 5 - 0
android_bed/src/main/h7_3128/res/drawable/selector_call_hangup.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="@drawable/ic_hangup_press" android:state_pressed="true"/>
+    <item android:drawable="@drawable/ic_hangup_normal"/>
+</selector>

+ 5 - 0
android_bed/src/main/h7_3128/res/drawable/selector_main.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/right_item_select" android:state_pressed="true"/>
+    <item android:drawable="@color/right_item_bg"/>
+</selector>

+ 5 - 0
android_bed/src/main/h7_3128/res/drawable/selector_record_btn.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="@mipmap/ic_record_press" android:state_pressed="true"/>
+    <item android:drawable="@mipmap/ic_record_normal"/>
+</selector>

+ 7 - 0
android_bed/src/main/h7_3128/res/drawable/shape_frame_bg.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="#FBE5E8"/>
+    <corners
+        android:topLeftRadius="10dp"
+        android:topRightRadius="10dp"/>
+</shape>

+ 137 - 0
android_bed/src/main/h7_3128/res/layout/adapter_call_records_item.xml

@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout>
+
+    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="74dp"
+        android:background="#ffffff"
+        android:layout_marginTop="6px">
+
+        <LinearLayout
+            android:id="@+id/tab_linyout"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_marginLeft="9px"
+            android:gravity="center_vertical"
+            android:orientation="vertical">
+
+            <ImageView
+                android:id="@+id/tab_imagev"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_centerVertical="true"
+                android:src="@mipmap/ic_customer" />
+
+            <ImageView
+                android:id="@+id/call_status_imagev"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_centerVertical="true"
+                android:layout_marginTop="2px" />
+        </LinearLayout>
+
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_marginTop="4px"
+            android:layout_marginRight="9px"
+            android:layout_toRightOf="@+id/tab_linyout">
+
+            <RelativeLayout
+                android:id="@+id/room_name_linlyout"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="6px">
+
+                <TextView
+                    android:id="@+id/sickbed_tv"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="--"
+                    android:textSize="14px" />
+
+                <TextView
+                    android:id="@+id/call_time_tv"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_alignParentRight="true"
+                    android:text="--:--"
+                    android:textSize="12px" />
+
+            </RelativeLayout>
+
+            <RelativeLayout
+                android:id="@+id/nursing_project_relalyout"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_below="@+id/room_name_linlyout"
+                android:layout_marginLeft="6px"
+                android:layout_marginTop="4px"
+                android:orientation="vertical">
+
+                <TextView
+                    android:id="@+id/name_tv"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="--"
+                    android:textSize="14px" />
+
+                <LinearLayout
+                    android:id="@+id/incident_linlyou"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_alignParentRight="true"
+                    android:orientation="horizontal">
+
+                    <ImageView
+                        android:id="@+id/treatment_state_imagev"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:layout_gravity="center"
+                        android:layout_marginRight="6px" />
+
+
+                    <TextView
+                        android:id="@+id/project_tv"
+                        android:layout_width="wrap_content"
+                        android:layout_height="20px"
+                        android:gravity="center"
+                        android:text="--"
+                        android:textSize="12px" />
+
+                    <ImageView
+                        android:id="@+id/play_tv"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:gravity="center"
+                        android:visibility="gone"/>
+
+                </LinearLayout>
+            </RelativeLayout>
+
+            <LinearLayout
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_below="@+id/nursing_project_relalyout"
+                android:layout_alignParentRight="true"
+                android:layout_marginTop="4px"
+                android:orientation="horizontal">
+
+                <TextView
+                    android:id="@+id/conductor_name_tv"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_marginRight="10px"
+                    android:text="--"
+                    android:textSize="12px" />
+
+                <TextView
+                    android:id="@+id/processing_time_tv"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="--:--"
+                    android:textSize="12px" />
+            </LinearLayout>
+        </RelativeLayout>
+    </RelativeLayout>
+</layout>

+ 27 - 0
android_bed/src/main/h7_3128/res/layout/advice_view_lay.xml

@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout>
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:bind="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <com.scwang.smartrefresh.layout.SmartRefreshLayout
+        android:id="@+id/advice_refresh"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        bind:srlEnableLoadMore="true"
+        bind:srlEnableRefresh="true">
+
+        <android.support.v7.widget.RecyclerView
+            android:id="@+id/rv_advice_main_view"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_marginBottom="6dp"
+            android:scrollbars="vertical"
+            android:fadeScrollbars="true"
+            android:scrollbarStyle="insideOverlay"/>
+
+    </com.scwang.smartrefresh.layout.SmartRefreshLayout>
+</LinearLayout>
+</layout>

+ 67 - 0
android_bed/src/main/h7_3128/res/layout/call_dialog_lay.xml

@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <!--拨出按钮显示-->
+    <LinearLayout
+        android:id="@+id/ll_call_outgoing"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:gravity="center"
+        android:orientation="vertical">
+
+        <TextView
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:gravity="center"
+            android:text="@string/call_in_calling"
+            android:textSize="28sp"/>
+
+        <ImageView
+            android:id="@+id/iv_hangup_call"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="60dp"
+            android:src="@drawable/selector_call_hangup" />
+    </LinearLayout>
+
+
+    <!--接听按钮显示-->
+    <RelativeLayout
+        android:id="@+id/rl_call_incoming"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:gravity="center"
+        android:visibility="gone">
+
+        <TextView
+            android:id="@+id/tv_incoming_call_text"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:gravity="center"
+            android:text="@string/call_incoming"
+            android:textSize="28sp"/>
+
+        <ImageView
+            android:id="@+id/iv_accept_call"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_below="@id/tv_incoming_call_text"
+            android:layout_alignParentLeft="true"
+            android:layout_marginLeft="160dp"
+            android:layout_marginTop="60dp"
+            android:src="@drawable/selector_call_answer"/>
+
+        <ImageView
+            android:id="@+id/iv_reject_call"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_below="@id/tv_incoming_call_text"
+            android:layout_alignParentRight="true"
+            android:layout_marginRight="160dp"
+            android:layout_marginTop="60dp"
+            android:src="@drawable/selector_call_end"/>
+    </RelativeLayout>
+
+</RelativeLayout>

+ 286 - 0
android_bed/src/main/h7_3128/res/layout/callingbed2_main_lay.xml

@@ -0,0 +1,286 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:bind="http://schemas.android.com/apk/res-auto">
+    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="@color/main_bg">
+
+        <include
+            android:id="@+id/activity_calling_bed_layout_title"
+            layout="@layout/view_title_layout"/>
+
+        <!--底部按钮区域-->
+        <RelativeLayout
+            android:id="@+id/ll_bottom"
+            android:layout_width="match_parent"
+            android:layout_height="80dp"
+            android:layout_alignParentBottom="true"
+            android:background="@color/main_color"
+            android:gravity="center_vertical"
+            android:paddingLeft="20dp"
+            android:paddingRight="20dp">
+
+            <TextView
+                android:id="@+id/tv_btn_home"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:paddingLeft="28dp"
+                android:paddingRight="28dp"
+                android:paddingTop="10dp"
+                android:paddingBottom="10dp"
+                android:background="@mipmap/bg_bottom_btn"
+                android:drawableLeft="@mipmap/ic_home"
+                android:drawablePadding="10dp"
+                android:text="@string/str_home"
+                android:textColor="@drawable/selector_bottom_btn_text_color"
+                android:textSize="24sp"/>
+
+            <TextView
+                android:id="@+id/tv_btn_more"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_toRightOf="@id/tv_btn_home"
+                android:paddingLeft="28dp"
+                android:paddingRight="28dp"
+                android:paddingTop="10dp"
+                android:paddingBottom="10dp"
+                android:layout_marginLeft="20dp"
+                android:background="@mipmap/bg_bottom_btn"
+                android:drawableLeft="@mipmap/ic_more"
+                android:drawablePadding="10dp"
+                android:text="@string/str_more"
+                android:textColor="@drawable/selector_bottom_btn_text_color"
+                android:textSize="24sp"/>
+
+            <TextView
+                android:id="@+id/tv_btn_advice"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_toRightOf="@id/tv_btn_more"
+                android:paddingLeft="28dp"
+                android:paddingRight="28dp"
+                android:paddingTop="10dp"
+                android:paddingBottom="10dp"
+                android:layout_marginLeft="20dp"
+                android:background="@mipmap/bg_bottom_btn"
+                android:drawableLeft="@mipmap/ic_cost"
+                android:drawablePadding="10dp"
+                android:text="@string/str_advice"
+                android:textColor="@drawable/selector_bottom_btn_text_color"
+                android:textSize="24sp"/>
+
+            <TextView
+                android:id="@+id/tv_btn_cost"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_toRightOf="@id/tv_btn_advice"
+                android:paddingLeft="28dp"
+                android:paddingRight="28dp"
+                android:paddingTop="10dp"
+                android:paddingBottom="10dp"
+                android:layout_marginLeft="20dp"
+                android:background="@mipmap/bg_bottom_btn"
+                android:drawableLeft="@mipmap/ic_cost"
+                android:drawablePadding="10dp"
+                android:text="@string/str_fees"
+                android:textColor="@drawable/selector_bottom_btn_text_color"
+                android:textSize="24sp"/>
+
+            <TextView
+                android:id="@+id/tv_btn_voice_call"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_alignParentRight="true"
+                android:paddingLeft="28dp"
+                android:paddingRight="28dp"
+                android:paddingTop="10dp"
+                android:paddingBottom="10dp"
+                android:background="@mipmap/bg_bottom_btn"
+                android:drawableLeft="@mipmap/ic_call"
+                android:drawablePadding="10dp"
+                android:text="@string/str_call"
+                android:textColor="@drawable/selector_bottom_btn_text_color"
+                android:textSize="24sp"/>
+
+            <TextView
+                android:id="@+id/tv_btn_support"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_toLeftOf="@id/tv_btn_voice_call"
+                android:paddingLeft="28dp"
+                android:paddingRight="28dp"
+                android:paddingTop="10dp"
+                android:paddingBottom="10dp"
+                android:layout_marginRight="20dp"
+                android:background="@mipmap/bg_bottom_btn"
+                android:drawableLeft="@mipmap/ic_support"
+                android:drawablePadding="10dp"
+                android:text="@string/str_support"
+                android:textColor="@drawable/selector_bottom_btn_text_color"
+                android:textSize="24sp"/>
+        </RelativeLayout>
+
+        <LinearLayout
+            android:id="@+id/rl_left_view"
+            android:layout_width="220dp"
+            android:layout_height="match_parent"
+            android:layout_above="@id/ll_bottom"
+            android:layout_below="@id/activity_calling_bed_layout_title"
+            android:layout_marginTop="4dp"
+            android:paddingLeft="10dp"
+            android:paddingRight="10dp">
+
+            <!--左侧护理列表-->
+            <android.support.v7.widget.RecyclerView
+                android:id="@+id/rv_left_list"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent" />
+
+        </LinearLayout>
+
+        <!--右侧fragment区域-->
+        <FrameLayout
+            android:id="@+id/callingbed2_main_frame"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_marginTop="10dp"
+            android:layout_marginBottom="10dp"
+            android:layout_marginRight="10dp"
+            android:layout_toRightOf="@id/rl_left_view"
+            android:layout_above="@id/ll_bottom"
+            android:layout_below="@id/activity_calling_bed_layout_title" />
+
+        <LinearLayout
+            android:id="@+id/ll_broadcast_view"
+            android:layout_width="match_parent"
+            android:layout_height="80dp"
+            android:layout_above="@id/ll_bottom"
+            android:layout_toRightOf="@id/rl_left_view"
+            android:layout_marginBottom="20dp"
+            android:layout_marginLeft="10dp"
+            android:layout_marginRight="210dp"
+            android:gravity="center"
+            android:background="@color/trans_bg_color"
+            android:visibility="gone">
+
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/str_volume"
+                android:textSize="20sp"
+                android:textColor="@color/title_text"/>
+
+            <SeekBar
+                android:id="@+id/seekbar_bc_volume"
+                android:layout_width="180dp"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_vertical"
+                android:max="100"
+                android:progress="0"
+                android:maxHeight="5dp"
+                android:progressDrawable="@drawable/po_seekbar"
+                android:thumb="@drawable/seekbar_thumb"/>
+
+            <TextView
+                android:id="@+id/tv_broadcast_state"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10dp"
+                android:layout_marginRight="10dp"
+                android:background="@drawable/ic_baseline_pause"/>
+
+            <com.wdkl.ncs.android.lib.widget.MarqueeTextView
+                android:id="@+id/tv_broadcast_text"
+                android:layout_width="160dp"
+                android:layout_height="wrap_content"
+                android:ellipsize="marquee"
+                android:focusable="true"
+                android:focusableInTouchMode="true"
+                android:marqueeRepeatLimit="-1"
+                android:singleLine="true"
+                android:text="@string/broadcast_playing"
+                android:textSize="32sp"
+                android:textColor="@color/title_text"/>
+
+            <TextView
+                android:id="@+id/tv_broadcast_stop"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10dp"
+                android:layout_marginRight="10dp"
+                android:background="@drawable/ic_baseline_cancel"/>
+
+        </LinearLayout>
+
+        <!--通话界面-->
+        <FrameLayout
+            android:id="@+id/call_frame"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent" />
+
+
+
+
+        <!--呼叫状态显示-->
+        <LinearLayout
+            android:id="@+id/ll_call_view"
+            android:layout_width="match_parent"
+            android:layout_height="86dp"
+            android:layout_marginTop="10dp"
+            android:layout_marginBottom="10dp"
+            android:layout_marginRight="10dp"
+            android:layout_toRightOf="@id/rl_left_view"
+            android:layout_below="@id/activity_calling_bed_layout_title"
+            android:background="#37C127"
+            android:gravity="center_vertical"
+            android:visibility="gone">
+
+            <com.wdkl.ncs.android.lib.widget.MarqueeTextView
+                android:id="@+id/tv_call_bed_name"
+                android:layout_width="260dp"
+                android:layout_height="match_parent"
+                android:gravity="center"
+                android:ellipsize="marquee"
+                android:focusable="true"
+                android:focusableInTouchMode="true"
+                android:marqueeRepeatLimit="-1"
+                android:singleLine="true"
+                android:textColor="@color/white"
+                android:textSize="54sp"/>
+
+            <com.wdkl.ncs.android.lib.widget.MarqueeTextView
+                android:id="@+id/tv_call_state"
+                android:layout_width="320dp"
+                android:layout_height="match_parent"
+                android:paddingLeft="10dp"
+                android:paddingRight="10dp"
+                android:gravity="center"
+                android:ellipsize="marquee"
+                android:focusable="true"
+                android:focusableInTouchMode="true"
+                android:marqueeRepeatLimit="-1"
+                android:singleLine="true"
+                android:textColor="@color/red_color"
+                android:textSize="32sp" />
+
+            <Chronometer
+                android:id="@+id/voice_call_timer_view"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:layout_marginLeft="20dp"
+                android:gravity="center"
+                android:text="00:00"
+                android:textColor="@color/white"
+                android:textSize="24sp" />
+
+            <ImageView
+                android:id="@+id/iv_call_end"
+                android:layout_width="60dp"
+                android:layout_height="60dp"
+                android:layout_marginLeft="20dp"
+                android:src="@drawable/selector_call_end"
+                android:scaleType="centerInside"/>
+        </LinearLayout>
+
+    </RelativeLayout>
+</layout>

+ 27 - 0
android_bed/src/main/h7_3128/res/layout/cost_view_lay.xml

@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout>
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:bind="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <com.scwang.smartrefresh.layout.SmartRefreshLayout
+        android:id="@+id/cost_refresh"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        bind:srlEnableLoadMore="true"
+        bind:srlEnableRefresh="true">
+
+        <android.support.v7.widget.RecyclerView
+            android:id="@+id/rv_cost_main_view"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_marginBottom="6dp"
+            android:scrollbars="vertical"
+            android:fadeScrollbars="true"
+            android:scrollbarStyle="insideOverlay"/>
+
+    </com.scwang.smartrefresh.layout.SmartRefreshLayout>
+</LinearLayout>
+</layout>

+ 17 - 0
android_bed/src/main/h7_3128/res/layout/digital_item.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <TextView
+        android:id="@+id/tv_number"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="@color/color_gray"
+        android:layout_margin="4dp"
+        android:padding="10dp"
+        android:gravity="center"
+        android:textSize="32sp"
+        android:textColor="@color/main_color"/>
+
+</LinearLayout>

+ 33 - 0
android_bed/src/main/h7_3128/res/layout/item_action_view.xml

@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:paddingTop="4dp"
+    android:paddingLeft="4dp"
+    android:paddingRight="4dp">
+
+    <LinearLayout
+        android:id="@+id/ll_action_view"
+        android:layout_width="match_parent"
+        android:layout_height="62dp"
+        android:background="@mipmap/bg_action_item"
+        android:gravity="center_vertical">
+
+        <ImageView
+            android:id="@+id/iv_action"
+            android:layout_width="40dp"
+            android:layout_height="40dp"
+            android:layout_marginLeft="10dp"
+            android:scaleType="centerInside"/>
+
+        <TextView
+            android:id="@+id/tv_action"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_marginLeft="10dp"
+            android:gravity="left|center_vertical"
+            android:text=""
+            android:textSize="28sp"
+            android:textColor="@drawable/selector_action_button_text_color"/>
+    </LinearLayout>
+</LinearLayout>

+ 64 - 0
android_bed/src/main/h7_3128/res/layout/item_advice.xml

@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:padding="20dp"
+    android:layout_marginBottom="10dp"
+    android:background="@color/white">
+
+    <TextView
+        android:id="@+id/tv_item_advice_type"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textSize="24sp"
+        android:textColor="@color/main_color"/>
+
+    <TextView
+        android:id="@+id/tv_item_advice_status"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="8dp"
+        android:layout_below="@id/tv_item_advice_type"
+        android:textSize="20sp"
+        android:textColor="#A4A4A4"/>
+
+    <TextView
+        android:id="@+id/tv_item_advice_start_time"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentRight="true"
+        android:text="--:--"
+        android:textSize="20sp"
+        android:textColor="#A4A4A4"/>
+
+    <TextView
+        android:id="@+id/tv_item_advice_end_time"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="8dp"
+        android:layout_below="@id/tv_item_advice_start_time"
+        android:layout_alignParentRight="true"
+        android:text="--:--"
+        android:textSize="20sp"
+        android:textColor="#A4A4A4"/>
+
+    <TextView
+        android:id="@+id/tv_item_advice_content"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="8dp"
+        android:layout_below="@id/tv_item_advice_status"
+        android:textSize="20sp"
+        android:textColor="@color/black"/>
+
+    <TextView
+        android:id="@+id/tv_item_advice_detail"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/tv_item_advice_content"
+        android:layout_marginTop="8dp"
+        android:textSize="20sp"
+        android:textColor="#A4A4A4"/>
+
+</RelativeLayout>

+ 39 - 0
android_bed/src/main/h7_3128/res/layout/item_cost_detail.xml

@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_marginTop="10dp">
+
+    <TextView
+        android:id="@+id/tv_item_cost_name"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textSize="20sp"
+        android:textColor="@color/black"/>
+    <TextView
+        android:id="@+id/tv_item_cost_value"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentRight="true"
+        android:textSize="20sp"
+        android:textColor="@color/black"/>
+    <TextView
+        android:id="@+id/tv_item_cost_id"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/tv_item_cost_name"
+        android:layout_marginTop="8dp"
+        android:textSize="20sp"
+        android:textColor="#A4A4A4"/>
+    <TextView
+        android:id="@+id/tv_item_cost_unit"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentRight="true"
+        android:layout_below="@id/tv_item_cost_value"
+        android:layout_marginTop="8dp"
+        android:textSize="20sp"
+        android:textColor="#A4A4A4"/>
+
+</RelativeLayout>

+ 52 - 0
android_bed/src/main/h7_3128/res/layout/item_cost_detail2.xml

@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:padding="20dp"
+    android:layout_marginBottom="10dp"
+    android:background="@color/white">
+    <TextView
+        android:id="@+id/tv_item_cost_group_name"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textSize="24sp"
+        android:textColor="@color/main_color"/>
+
+    <TextView
+        android:id="@+id/tv_item_cost_time"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentRight="true"
+        android:textSize="20sp"
+        android:textColor="#A4A4A4"/>
+
+    <TextView
+        android:id="@+id/tv_item_cost_name"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="8dp"
+        android:layout_below="@id/tv_item_cost_group_name"
+        android:textSize="20sp"
+        android:textColor="@color/black"/>
+
+    <TextView
+        android:id="@+id/tv_item_cost_value"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="8dp"
+        android:layout_alignParentRight="true"
+        android:layout_below="@id/tv_item_cost_group_name"
+        android:textSize="20sp"
+        android:textColor="@color/black"/>
+
+    <TextView
+        android:id="@+id/tv_item_cost_detail"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/tv_item_cost_name"
+        android:layout_marginTop="8dp"
+        android:textSize="20sp"
+        android:textColor="#A4A4A4"/>
+
+</RelativeLayout>

+ 38 - 0
android_bed/src/main/h7_3128/res/layout/item_cost_main_view.xml

@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:padding="16dp"
+    android:layout_marginBottom="10dp"
+    android:orientation="vertical"
+    android:background="@color/white">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+        <TextView
+            android:id="@+id/tv_cost_group_name"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:text=""
+            android:textColor="@color/main_color"
+            android:textSize="24sp"/>
+        <TextView
+            android:id="@+id/tv_cost_group_total"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:gravity="right"
+            android:text=""
+            android:textColor="@color/main_color"
+            android:textSize="24sp"/>
+    </LinearLayout>
+
+    <android.support.v7.widget.RecyclerView
+        android:id="@+id/rv_cost_detail"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"/>
+
+</LinearLayout>

+ 70 - 0
android_bed/src/main/h7_3128/res/layout/item_event_history.xml

@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="80dp"
+    android:padding="10dp">
+
+    <ImageView
+        android:id="@+id/iv_custom"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerVertical="true"
+        android:src="@mipmap/ic_customer"/>
+
+    <ImageView
+        android:id="@+id/iv_call_state"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/iv_custom"
+        android:src="@mipmap/ic_call_undo"/>
+
+    <LinearLayout
+        android:id="@+id/ll_room_name"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_toRightOf="@id/iv_custom"
+        android:layout_marginLeft="8dp"
+        android:orientation="vertical">
+        <TextView
+            android:id="@+id/tv_room_name"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textColor="@color/black"
+            android:textSize="20sp"
+            android:text="--"/>
+        <TextView
+            android:id="@+id/tv_customer_name"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textSize="20sp"
+            android:text="--"/>
+
+    </LinearLayout>
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentRight="true"
+        android:orientation="vertical">
+        <TextView
+            android:id="@+id/tv_action_time"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:gravity="end"
+            android:text="--:--"/>
+        <TextView
+            android:id="@+id/tv_action_name"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:gravity="end"
+            android:text="--"/>
+        <TextView
+            android:id="@+id/tv_action_state"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:gravity="end"
+            android:text="--"/>
+    </LinearLayout>
+
+</RelativeLayout>

+ 44 - 0
android_bed/src/main/h7_3128/res/layout/item_nurse_config.xml

@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/ll_nurse_item"
+    android:layout_width="match_parent"
+    android:layout_height="86dp"
+    android:layout_marginTop="6dp"
+    android:background="#E7E7E7"
+    android:orientation="vertical">
+
+    <!--<TextView
+        android:id="@+id/tv_nurse_color"
+        android:layout_width="8dp"
+        android:layout_height="match_parent"
+        android:background="@color/main_color"/>-->
+
+    <TextView
+        android:id="@+id/tv_nurse_config_name"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        android:paddingLeft="6dp"
+        android:paddingTop="6dp"
+        android:singleLine="true"
+        android:ellipsize="end"
+        android:text="@string/default_nurse_config_name"
+        android:textSize="20sp"
+        android:textColor="@color/white"/>
+
+    <TextView
+        android:id="@+id/tv_nurse_config_value"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        android:paddingRight="6dp"
+        android:paddingBottom="6dp"
+        android:singleLine="true"
+        android:ellipsize="end"
+        android:gravity="right|bottom"
+        android:text="@string/str_empty"
+        android:textSize="22sp"
+        android:textColor="@color/white"/>
+
+</LinearLayout>

+ 83 - 0
android_bed/src/main/h7_3128/res/layout/language_set_dialog.xml

@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:padding="20dp"
+    android:gravity="center"
+    android:orientation="vertical">
+
+    <TextView
+        android:id="@+id/tv_language_title"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="10dp"
+        android:text="@string/language_set_mode"
+        android:textSize="24sp" />
+
+    <RadioGroup
+        android:id="@+id/group_language_mode"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="10dp"
+        android:orientation="horizontal">
+        <RadioButton
+            android:id="@+id/rb_language_yes"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/str_yes"/>
+        <RadioButton
+            android:id="@+id/rb_language_no"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="4dp"
+            android:text="@string/str_no"/>
+    </RadioGroup>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="20dp"
+        android:orientation="vertical">
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:gravity="center"
+            android:text="@string/language_set_title"
+            android:textSize="24sp" />
+
+        <Spinner
+            android:id="@+id/spinner_language_select"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="10dp"/>
+    </LinearLayout>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="60dp"
+        android:gravity="center_horizontal">
+        <Button
+            android:id="@+id/confirm_button"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:background="@mipmap/bg_bottom_btn"
+            android:padding="8dp"
+            android:text="@string/str_confirm"
+            android:textSize="20sp"
+            android:textColor="@drawable/selector_bottom_btn_text_color"/>
+
+        <Button
+            android:id="@+id/cancel_button"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="80dp"
+            android:background="@mipmap/bg_bottom_btn"
+            android:padding="8dp"
+            android:text="@string/str_cancel"
+            android:textSize="20sp"
+            android:textColor="@drawable/selector_bottom_btn_text_color"/>
+    </LinearLayout>
+
+</LinearLayout>

+ 0 - 0
android_bed/src/main/h7_3128/res/layout/main_view2_layout.xml


Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor