Browse Source

月子中心版主机增加普通电话呼叫功能,呼叫号码匹配通讯录。暂时去掉sip,切换了sip版本,还需调试

weizhengliang 1 year ago
parent
commit
9f0c77c26e
41 changed files with 1260 additions and 183 deletions
  1. 23 2
      android_host/src/main/h10_z3128_ke_2h/AndroidManifest.xml
  2. 36 22
      android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/activity/NurseHomeActivity.kt
  3. 80 35
      android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/activity/RegisterActivity.kt
  4. 4 8
      android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/activity/SipAudioCallActivity.kt
  5. 1 1
      android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/adapter/BroadcastAdapter.kt
  6. 4 2
      android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/adapter/CallRecordsItemAdapter.kt
  7. 1 1
      android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/adapter/DoctorHostAdapter.kt
  8. 1 1
      android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/adapter/FamilyMembersAdapter.kt
  9. 1 1
      android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/adapter/FrameBedVosAdapter.kt
  10. 1 1
      android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/adapter/FrameBedVosConfinementAdapter.kt
  11. 1 1
      android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/adapter/FramePartItemAdapter.kt
  12. 1 1
      android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/adapter/InpatientWardAdapter.kt
  13. 1 1
      android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/adapter/NurseMoveAdapter.kt
  14. 1 1
      android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/adapter/OtherHostAdapter.kt
  15. 1 1
      android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/adapter/ResponsibilityBedAdapter.kt
  16. 1 1
      android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/adapter/SickbedAdapter.kt
  17. 1 1
      android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/adapter/VisitManagementAdapter.kt
  18. 2 3
      android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/fragment/CallRecordsFragment.kt
  19. 47 8
      android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/fragment/FramePartFragment.kt
  20. 1 3
      android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/fragment/SystemSettingsFragment.kt
  21. 44 3
      android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/helper/HttpHelper.java
  22. 114 0
      android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/receiver/PhoneStateReceiver.java
  23. 68 0
      android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/service/APPService.kt
  24. 139 0
      android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/util/PhoneCallUtil.java
  25. 1 1
      android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/util/XCrashUtils.java
  26. 2 2
      android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/window/IncidentWindow.kt
  27. 0 81
      android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/window/VoiceCall.kt
  28. 7 0
      common/build.gradle
  29. 7 0
      common/src/main/aidl/com/android/internal/telephony/ITelephony.aidl
  30. 1 1
      middleware/src/main/code/com/wdkl/ncs/android/middleware/api/ApiManager.kt
  31. 3 0
      middleware/src/main/code/com/wdkl/ncs/android/middleware/api/NurseHomeApi.kt
  32. 24 0
      middleware/src/main/code/com/wdkl/ncs/android/middleware/common/Constants.kt
  33. 6 0
      middleware/src/main/code/com/wdkl/ncs/android/middleware/logic/contract/nursehome/NurseHomeActivityContract.kt
  34. 43 0
      middleware/src/main/code/com/wdkl/ncs/android/middleware/logic/presenter/nursehome/NurseHomeActivityPresenter.kt
  35. 102 0
      middleware/src/main/code/com/wdkl/ncs/android/middleware/model/vo/PhoneInteractionVO.java
  36. 6 0
      middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/channel/DeviceChannel.java
  37. 6 0
      middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/channel/DeviceUtil.java
  38. 57 0
      middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/channel/PhoneUtil.java
  39. 10 0
      middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/dto/DeviceConnectDTO.java
  40. 63 0
      middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/enums/CommunicationEnum.java
  41. 348 0
      middleware/src/main/code/com/wdkl/ncs/android/middleware/utils/ContactHelper.java

+ 23 - 2
android_host/src/main/h10_z3128_ke_2h/AndroidManifest.xml

@@ -7,6 +7,27 @@
     <!-- Android8.0未知来源权限 -->
     <!-- Android8.0未知来源权限 -->
     <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
     <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
     <uses-permission android:name="android.permission.INSTALL_PACKAGES" />
     <uses-permission android:name="android.permission.INSTALL_PACKAGES" />
+    <uses-permission android:name="android.permission.WRITE_CALL_LOG" />
+    <uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" />
+    <uses-permission android:name="android.permission.CAMERA" />
+    <uses-permission android:name="android.permission.RECORD_AUDIO"/>
+    <uses-permission android:name="android.permission.CALL_PHONE" />
+    <uses-permission android:name="android.permission.READ_CALL_LOG" />
+    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+    <uses-permission android:name="android.permission.READ_PHONE_NUMBERS" />
+
+    <!-- 读写通讯录权限-->
+    <uses-permission android:name="android.permission.READ_CONTACTS"/>
+    <uses-permission android:name="android.permission.WRITE_CONTACTS"/>
+    <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
+    <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
+    <uses-permission android:name="android.permission.READ_SMS"/>
+    <uses-permission android:name="android.permission.READ_PHONE_NUMBERS"/>
+
+    <!--  亮屏和解锁权限   -->
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+
     <!-- silentUpdate -->
     <!-- silentUpdate -->
     <uses-permission
     <uses-permission
         android:name="android.permission."
         android:name="android.permission."
@@ -155,9 +176,9 @@
         <activity android:name="com.wdkl.ncs.host.activity.SipTestActivity" />
         <activity android:name="com.wdkl.ncs.host.activity.SipTestActivity" />
         <activity android:name="com.wdkl.ncs.host.activity.CallActivity" />
         <activity android:name="com.wdkl.ncs.host.activity.CallActivity" />
 
 
-        <service
+        <!--<service
             android:name="com.wdkl.ncs.host.service.WdklSipService"
             android:name="com.wdkl.ncs.host.service.WdklSipService"
-            android:label="@string/app_name" />
+            android:label="@string/app_name" />-->
     </application>
     </application>
 
 
 </manifest>
 </manifest>

+ 36 - 22
android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/activity/NurseHomeActivity.kt

@@ -23,7 +23,6 @@ import com.alibaba.fastjson.JSON
 import com.enation.javashop.android.jrouter.external.annotation.Router
 import com.enation.javashop.android.jrouter.external.annotation.Router
 import com.enation.javashop.net.engine.model.NetState
 import com.enation.javashop.net.engine.model.NetState
 import com.wdkl.ncs.android.component.home.agreement.NurseHomeAgreement
 import com.wdkl.ncs.android.component.home.agreement.NurseHomeAgreement
-import com.wdkl.ncs.android.component.nursehome.BuildConfig
 import com.wdkl.ncs.android.component.nursehome.R
 import com.wdkl.ncs.android.component.nursehome.R
 import com.wdkl.ncs.android.middleware.common.Constants
 import com.wdkl.ncs.android.middleware.common.Constants
 import com.wdkl.ncs.android.component.nursehome.databinding.ActivityNurseHomeBinding
 import com.wdkl.ncs.android.component.nursehome.databinding.ActivityNurseHomeBinding
@@ -41,6 +40,7 @@ import com.wdkl.ncs.android.lib.utils.AppTool
 import com.wdkl.ncs.android.lib.utils.NetReceiver
 import com.wdkl.ncs.android.lib.utils.NetReceiver
 import com.wdkl.ncs.android.lib.utils.push
 import com.wdkl.ncs.android.lib.utils.push
 import com.wdkl.ncs.android.lib.utils.showMessage
 import com.wdkl.ncs.android.lib.utils.showMessage
+import com.wdkl.ncs.android.middleware.BuildConfig
 import com.wdkl.ncs.android.middleware.logic.contract.nursehome.NurseHomeActivityContract
 import com.wdkl.ncs.android.middleware.logic.contract.nursehome.NurseHomeActivityContract
 import com.wdkl.ncs.android.middleware.logic.presenter.nursehome.NurseHomeActivityPresenter
 import com.wdkl.ncs.android.middleware.logic.presenter.nursehome.NurseHomeActivityPresenter
 import com.wdkl.ncs.android.middleware.model.ServerInfo
 import com.wdkl.ncs.android.middleware.model.ServerInfo
@@ -53,7 +53,6 @@ import com.wdkl.ncs.android.middleware.model.vo.HostDevicePartSettingVO
 import com.wdkl.ncs.android.middleware.model.vo.InteractionVO
 import com.wdkl.ncs.android.middleware.model.vo.InteractionVO
 import com.wdkl.ncs.android.middleware.model.vo.NurseDeviceInfoVO
 import com.wdkl.ncs.android.middleware.model.vo.NurseDeviceInfoVO
 import com.wdkl.ncs.android.middleware.tcp.TcpClient
 import com.wdkl.ncs.android.middleware.tcp.TcpClient
-import com.wdkl.ncs.android.middleware.tcp.TcpClientHandler
 import com.wdkl.ncs.android.middleware.tcp.channel.DeviceChannel
 import com.wdkl.ncs.android.middleware.tcp.channel.DeviceChannel
 import com.wdkl.ncs.android.middleware.tcp.channel.EntraceGuardUtil
 import com.wdkl.ncs.android.middleware.tcp.channel.EntraceGuardUtil
 import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel
 import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel
@@ -61,7 +60,7 @@ import com.wdkl.ncs.android.middleware.tcp.enums.DeviceTypeEnum
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpAction
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpAction
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpType
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpType
 import com.wdkl.ncs.android.middleware.utils.MessageEvent
 import com.wdkl.ncs.android.middleware.utils.MessageEvent
-import com.wdkl.ncs.host.service.WdklSipService
+//import com.wdkl.ncs.host.service.WdklSipService
 import com.wdkl.ncs.janus.util.JanusConstant
 import com.wdkl.ncs.janus.util.JanusConstant
 import kotlinx.android.synthetic.main.activity_nurse_home.*
 import kotlinx.android.synthetic.main.activity_nurse_home.*
 import org.greenrobot.eventbus.EventBus
 import org.greenrobot.eventbus.EventBus
@@ -144,10 +143,6 @@ class NurseHomeActivity : BaseActivity<NurseHomeActivityPresenter, ActivityNurse
             SerialPortHelper.setHandsMIC(true)
             SerialPortHelper.setHandsMIC(true)
         }
         }
 
 
-        //空间结构Fragment
-        fragment = FramePartFragment()
-        currentFragment = fragment
-        supportFragmentManager.beginTransaction().add(R.id.middle_fralyout, fragment, "").commitAllowingStateLoss()
         //记录Fragment
         //记录Fragment
         callRecordsFragment = CallRecordsFragment()
         callRecordsFragment = CallRecordsFragment()
         currentFragmentThree = callRecordsFragment
         currentFragmentThree = callRecordsFragment
@@ -155,13 +150,13 @@ class NurseHomeActivity : BaseActivity<NurseHomeActivityPresenter, ActivityNurse
 
 
         if (SettingConfig.getSipEnabled(activity)) {
         if (SettingConfig.getSipEnabled(activity)) {
             //启动sip服务
             //启动sip服务
-            val serviceIntent = Intent(BaseApplication.appContext, WdklSipService::class.java)
+            /*val serviceIntent = Intent(BaseApplication.appContext, WdklSipService::class.java)
             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                 //android8.0以上通过startForegroundService启动service
                 //android8.0以上通过startForegroundService启动service
                 startForegroundService(serviceIntent)
                 startForegroundService(serviceIntent)
             } else {
             } else {
                 startService(serviceIntent)
                 startService(serviceIntent)
-            }
+            }*/
             sip_state_tv.text = "sip"
             sip_state_tv.text = "sip"
         } else {
         } else {
             sip_state_tv.text = "rtc"
             sip_state_tv.text = "rtc"
@@ -191,7 +186,7 @@ class NurseHomeActivity : BaseActivity<NurseHomeActivityPresenter, ActivityNurse
         }.start()
         }.start()
 
 
         name_of_organization_tv.text = Constants.partDisplay
         name_of_organization_tv.text = Constants.partDisplay
-        Log.i(TAG, Constants.partDisplay)
+        Log.i(TAG, "" + Constants.partDisplay)
 
 
         //Constants.NET_AVAILABLE = NetHelper.getInstance().netAvailable
         //Constants.NET_AVAILABLE = NetHelper.getInstance().netAvailable
         home_radio_bt.isChecked = true
         home_radio_bt.isChecked = true
@@ -483,6 +478,9 @@ class NurseHomeActivity : BaseActivity<NurseHomeActivityPresenter, ActivityNurse
             //加载科室设置
             //加载科室设置
             presenter.getSettingData(Constants.part_id)
             presenter.getSettingData(Constants.part_id)
         }
         }
+
+        //加载电话号码白名单
+        presenter.getPhoneNumberWhiteList(Constants.ids)
     }
     }
 
 
     /**
     /**
@@ -496,7 +494,7 @@ class NurseHomeActivity : BaseActivity<NurseHomeActivityPresenter, ActivityNurse
 
 
         if (SettingConfig.getSipEnabled(activity)) {
         if (SettingConfig.getSipEnabled(activity)) {
             //配置sip账户
             //配置sip账户
-            if (WdklSipService.getCore() != null) {
+            /*if (WdklSipService.getCore() != null) {
                 mAccountCreator = WdklSipService.getCore().createAccountCreator(null)
                 mAccountCreator = WdklSipService.getCore().createAccountCreator(null)
                 // 以下三项必须
                 // 以下三项必须
                 if (!TextUtils.isEmpty(Constants.sip_id) && !TextUtils.isEmpty(Constants.sip_ip)) {
                 if (!TextUtils.isEmpty(Constants.sip_id) && !TextUtils.isEmpty(Constants.sip_ip)) {
@@ -511,18 +509,10 @@ class NurseHomeActivity : BaseActivity<NurseHomeActivityPresenter, ActivityNurse
                     val cfg = mAccountCreator!!.createProxyConfig()
                     val cfg = mAccountCreator!!.createProxyConfig()
                     // 确保新创建的是最新
                     // 确保新创建的是最新
                     WdklSipService.getCore().defaultProxyConfig = cfg
                     WdklSipService.getCore().defaultProxyConfig = cfg
-
-                    /*if (Constants.sip_port != null) {
-                        var transports = WdklSipService.getCore().transports
-                        transports.udpPort = Constants.sip_port!!
-                        transports.tcpPort = Constants.sip_port!!
-                        transports.tlsPort = -1
-                        WdklSipService.getCore().transports = transports
-                    }*/
                 } else {
                 } else {
                     showMessage("SIP empty")
                     showMessage("SIP empty")
                 }
                 }
-            }
+            }*/
         }
         }
 
 
         //默认白天夜晚起始时间
         //默认白天夜晚起始时间
@@ -530,6 +520,13 @@ class NurseHomeActivity : BaseActivity<NurseHomeActivityPresenter, ActivityNurse
         val endTime = "18:00:00"
         val endTime = "18:00:00"
         if (data != null) {
         if (data != null) {
             try {
             try {
+                //设置通话方式
+                if (data.communicationModeNurse != null) {
+                    Constants.phoneType = data.communicationModeNurse
+                }
+
+                showHome()
+
                 SettingConfiguration.getInstance().id = data.id
                 SettingConfiguration.getInstance().id = data.id
                 SettingConfiguration.getInstance().unionId = data.unionId
                 SettingConfiguration.getInstance().unionId = data.unionId
                 SettingConfiguration.getInstance().createTime = data.createTime
                 SettingConfiguration.getInstance().createTime = data.createTime
@@ -662,6 +659,12 @@ class NurseHomeActivity : BaseActivity<NurseHomeActivityPresenter, ActivityNurse
         }
         }
     }
     }
 
 
+    override fun setPhoneNumberWhiteList(phoneList: ArrayList<String>) {
+        //保存手机号码白名单
+        Constants.phoneWhiteList.clear()
+        Constants.phoneWhiteList.addAll(phoneList)
+    }
+
     override fun showDeviceData(data: NurseDeviceInfoVO) {
     override fun showDeviceData(data: NurseDeviceInfoVO) {
         //
         //
     }
     }
@@ -688,14 +691,20 @@ class NurseHomeActivity : BaseActivity<NurseHomeActivityPresenter, ActivityNurse
 
 
 
 
     fun showHome() {
     fun showHome() {
-        showMiddleFragment(FramePartFragment())
+        //空间结构Fragment
+        if (fragment == null) {
+            fragment = FramePartFragment()
+            currentFragment = fragment
+            supportFragmentManager.beginTransaction().add(R.id.middle_fralyout, fragment, "").commitAllowingStateLoss()
+        } else {
+            showMiddleFragment(FramePartFragment())
+        }
     }
     }
 
 
     override fun onClick(p0: View) {
     override fun onClick(p0: View) {
 
 
         when (p0.id) {
         when (p0.id) {
             R.id.home_radio_bt -> {
             R.id.home_radio_bt -> {
-                //showLeftFragment(CallRecordsFragment())
                 showMiddleFragment(FramePartFragment())
                 showMiddleFragment(FramePartFragment())
             }
             }
             R.id.broadcast_radio_bt -> {
             R.id.broadcast_radio_bt -> {
@@ -980,6 +989,11 @@ class NurseHomeActivity : BaseActivity<NurseHomeActivityPresenter, ActivityNurse
                             EntraceGuardUtil.rejectStranger(tcpModel)
                             EntraceGuardUtil.rejectStranger(tcpModel)
                         }
                         }
                     }
                     }
+                } else if (tcpModel.type == TcpType.DATA) {
+                    if (tcpModel.action == TcpAction.DataAction.REFRESH) {
+                        //刷新通讯录及白名单
+                        presenter.getPhoneNumberWhiteList(Constants.ids)
+                    }
                 }
                 }
 
 
             }
             }

+ 80 - 35
android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/activity/RegisterActivity.kt

@@ -15,7 +15,6 @@ import android.util.Log
 import com.enation.javashop.android.jrouter.external.annotation.Router
 import com.enation.javashop.android.jrouter.external.annotation.Router
 import com.enation.javashop.net.engine.model.NetState
 import com.enation.javashop.net.engine.model.NetState
 import com.enation.javashop.net.engine.plugin.permission.RxPermissions
 import com.enation.javashop.net.engine.plugin.permission.RxPermissions
-import com.wdkl.ncs.android.component.nursehome.BuildConfig
 import com.wdkl.ncs.android.component.nursehome.R
 import com.wdkl.ncs.android.component.nursehome.R
 import com.wdkl.ncs.android.middleware.common.Constants
 import com.wdkl.ncs.android.middleware.common.Constants
 import com.wdkl.ncs.android.component.nursehome.databinding.ActivityRegisterBinding
 import com.wdkl.ncs.android.component.nursehome.databinding.ActivityRegisterBinding
@@ -31,6 +30,7 @@ import com.wdkl.ncs.android.lib.utils.AppTool
 import com.wdkl.ncs.android.lib.utils.EcodeHelper
 import com.wdkl.ncs.android.lib.utils.EcodeHelper
 import com.wdkl.ncs.android.lib.utils.joinManager
 import com.wdkl.ncs.android.lib.utils.joinManager
 import com.wdkl.ncs.android.lib.utils.showMessage
 import com.wdkl.ncs.android.lib.utils.showMessage
+import com.wdkl.ncs.android.middleware.BuildConfig
 import com.wdkl.ncs.android.middleware.api.UrlManager
 import com.wdkl.ncs.android.middleware.api.UrlManager
 import com.wdkl.ncs.android.middleware.logic.contract.nursehome.DeviceContract
 import com.wdkl.ncs.android.middleware.logic.contract.nursehome.DeviceContract
 import com.wdkl.ncs.android.middleware.logic.presenter.nursehome.DevicePresenter
 import com.wdkl.ncs.android.middleware.logic.presenter.nursehome.DevicePresenter
@@ -123,47 +123,90 @@ class RegisterActivity : BaseActivity<DevicePresenter, ActivityRegisterBinding>(
     }
     }
 
 
     private fun requestPermissions(){
     private fun requestPermissions(){
-        Observable.just("").compose(RxPermissions(this).ensure(Manifest.permission.CAMERA,
-                Manifest.permission.READ_EXTERNAL_STORAGE,
-                Manifest.permission.WRITE_EXTERNAL_STORAGE,
-                Manifest.permission.ACCESS_WIFI_STATE,
-                Manifest.permission.RECORD_AUDIO,
-                Manifest.permission.READ_PHONE_STATE)
-                ).subscribe {
-            if (it){
-                Log.i(TAG,"拿到APP所有权限")
-                if ("YUNPAI_H6".equals(Build.MODEL) || "YUNPAI_H6B".equals(Build.MODEL)) {
-                    Constants.device_serial_id = NetHelper.getInstance().imei
-                    if ("YUNPAI_H6".equals(Build.MODEL)) {
-                        startYunpaiPlugin()
-                    }
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            Observable.just("").compose(
+                RxPermissions(this).ensure(
+                    Manifest.permission.CAMERA,
+                    Manifest.permission.READ_EXTERNAL_STORAGE,
+                    Manifest.permission.WRITE_EXTERNAL_STORAGE,
+                    Manifest.permission.ACCESS_WIFI_STATE,
+                    Manifest.permission.BLUETOOTH,
+                    Manifest.permission.RECORD_AUDIO,
+                    Manifest.permission.CALL_PHONE,
+                    Manifest.permission.READ_PHONE_STATE,
+                    Manifest.permission.READ_CALL_LOG,
+                    Manifest.permission.ANSWER_PHONE_CALLS,
+                    Manifest.permission.WRITE_CALL_LOG,
+                    Manifest.permission.READ_CONTACTS,
+                    Manifest.permission.WRITE_CONTACTS,
+                    Manifest.permission.READ_SMS,
+                    Manifest.permission.READ_PHONE_NUMBERS
+                )
+            ).subscribe {
+                if (it) {
+                    permissionGrant()
+                } else {
+                    showMessage("请重新授权,进入App")
+                    requestPermissions()
+                }
+            }.joinManager(disposableManager)
+        } else {
+            Observable.just("").compose(
+                RxPermissions(this).ensure(
+                    Manifest.permission.CAMERA,
+                    Manifest.permission.READ_EXTERNAL_STORAGE,
+                    Manifest.permission.WRITE_EXTERNAL_STORAGE,
+                    Manifest.permission.ACCESS_WIFI_STATE,
+                    Manifest.permission.BLUETOOTH,
+                    Manifest.permission.RECORD_AUDIO,
+                    Manifest.permission.CALL_PHONE,
+                    Manifest.permission.READ_PHONE_STATE,
+                    Manifest.permission.READ_CALL_LOG,
+                    Manifest.permission.WRITE_CALL_LOG,
+                    Manifest.permission.READ_CONTACTS,
+                    Manifest.permission.WRITE_CONTACTS,
+                    Manifest.permission.READ_SMS
+                )
+            ).subscribe {
+                if (it) {
+                    permissionGrant()
                 } else {
                 } else {
-                    Constants.device_serial_id = NetHelper.getInstance().macAddress
+                    showMessage("请重新授权,进入App")
+                    requestPermissions()
                 }
                 }
+            }.joinManager(disposableManager)
+        }
+    }
+
+    private fun permissionGrant() {
+        Log.i(TAG,"拿到APP所有权限")
+        if ("YUNPAI_H6".equals(Build.MODEL) || "YUNPAI_H6B".equals(Build.MODEL)) {
+            Constants.device_serial_id = NetHelper.getInstance().imei
+            if ("YUNPAI_H6".equals(Build.MODEL)) {
+                startYunpaiPlugin()
+            }
+        } else {
+            Constants.device_serial_id = NetHelper.getInstance().macAddress
+        }
 
 
-                Log.i(TAG,"device_serial_id: "+ Constants.device_serial_id)
+        Log.i(TAG,"device_serial_id: "+ Constants.device_serial_id)
 
 
-                showQRCode()
+        showQRCode()
 
 
-                val str_ip = CommonUtils.getUrl(BaseApplication.appContext)
+        val str_ip = CommonUtils.getUrl(BaseApplication.appContext)
 
 
-                device_info_tv.setText(
-                "App名称: ${getString(R.string.wdkl_app_name)}"+
-                        "\r\n服务器地址: " + str_ip +
-                        "\r\n当前设备MAC: ${Constants.device_serial_id}"+
-                        "\r\n当前设备IP: ${NetHelper.getInstance().localIP}"+
-                        "\r\nAPP版本号: V${BuildConfig.VERSION_NAME}_${BuildConfig.VERSION_CODE}"+
-                        "\r\n发布日期:${BuildConfig.BUILD_TIME}"+
-                        "\r\nSDK版本: ${Build.VERSION.SDK_INT}_${Build.MODEL}"
-                )
+        device_info_tv.setText(
+            "App名称: ${getString(R.string.wdkl_app_name)}"+
+                    "\r\n服务器地址: " + str_ip +
+                    "\r\n当前设备MAC: ${Constants.device_serial_id}"+
+                    "\r\n当前设备IP: ${NetHelper.getInstance().localIP}"+
+                    "\r\nAPP版本号: V${BuildConfig.VERSION_NAME}_${BuildConfig.VERSION_CODE}"+
+                    "\r\n发布日期:${BuildConfig.BUILD_TIME}"+
+                    "\r\nSDK版本: ${Build.VERSION.SDK_INT}_${Build.MODEL}"
+        )
 
 
-                //检查服务器地址接口是否可用,可用则进入下一步获取设备信息,不可用则稍后再次尝试
-                checkServer()
-            }else{
-                showMessage("请重新授权,进入App")
-                requestPermissions()
-            }
-        }.joinManager(disposableManager)
+        //检查服务器地址接口是否可用,可用则进入下一步获取设备信息,不可用则稍后再次尝试
+        checkServer()
     }
     }
 
 
     private fun startYunpaiPlugin() {
     private fun startYunpaiPlugin() {
@@ -438,6 +481,8 @@ class RegisterActivity : BaseActivity<DevicePresenter, ActivityRegisterBinding>(
             Constants.DEVICE_NAME = data.name
             Constants.DEVICE_NAME = data.name
         }
         }
 
 
+        Constants.PHONE_NUMBER = data.phoneNumber
+
         startMyService()
         startMyService()
 
 
         if(data.id!=null) {
         if(data.id!=null) {

+ 4 - 8
android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/activity/SipAudioCallActivity.kt

@@ -18,14 +18,10 @@ import com.wdkl.ncs.android.middleware.tcp.TcpClient
 import com.wdkl.ncs.android.middleware.tcp.channel.DeviceChannel
 import com.wdkl.ncs.android.middleware.tcp.channel.DeviceChannel
 import com.wdkl.ncs.android.middleware.tcp.channel.VoiceUtil
 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.dto.TcpModel
-import com.wdkl.ncs.android.middleware.tcp.enums.DeviceTypeEnum
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpAction
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpAction
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpType
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpType
 import com.wdkl.ncs.android.middleware.utils.MessageEvent
 import com.wdkl.ncs.android.middleware.utils.MessageEvent
-import com.wdkl.ncs.host.service.WdklSipService
 import com.wdkl.ncs.host.util.AudioRouteUtils
 import com.wdkl.ncs.host.util.AudioRouteUtils
-import com.wdkl.ncs.janus.rtc.WebRTCEngine
-import com.wdkl.ncs.janus.util.EnumType
 import kotlinx.android.synthetic.main.activity_web_rtc_voip_audio.*
 import kotlinx.android.synthetic.main.activity_web_rtc_voip_audio.*
 import org.greenrobot.eventbus.EventBus
 import org.greenrobot.eventbus.EventBus
 import org.greenrobot.eventbus.Subscribe
 import org.greenrobot.eventbus.Subscribe
@@ -123,12 +119,12 @@ class SipAudioCallActivity : Activity(), View.OnClickListener {
     }
     }
 
 
     fun init(){
     fun init(){
-        sipCore = WdklSipService.getCore()
+        /*sipCore = WdklSipService.getCore()
         if (sipCore == null) {
         if (sipCore == null) {
             showMessage("sip core is null...")
             showMessage("sip core is null...")
             finish()
             finish()
         }
         }
-        sipCore?.isMicEnabled = true
+        sipCore?.isMicEnabled = true*/
 
 
         bao_mother_age_tv.visibility = View.GONE
         bao_mother_age_tv.visibility = View.GONE
         voice_hang_up_imagev.setOnClickListener(this)
         voice_hang_up_imagev.setOnClickListener(this)
@@ -228,7 +224,7 @@ class SipAudioCallActivity : Activity(), View.OnClickListener {
                         voice_time_tv.visibility = View.VISIBLE
                         voice_time_tv.visibility = View.VISIBLE
                         voice_time_tv.text = "连接中...."
                         voice_time_tv.text = "连接中...."
 
 
-                        if (sipCore == null || TextUtils.isEmpty(curIt.toSipId)) {
+                        /*if (sipCore == null || TextUtils.isEmpty(curIt.toSipId)) {
                             //通话失败,重置并返回主界面
                             //通话失败,重置并返回主界面
                             showMessage("Core targetSipId empty!")
                             showMessage("Core targetSipId empty!")
 
 
@@ -245,7 +241,7 @@ class SipAudioCallActivity : Activity(), View.OnClickListener {
                                 sipCore!!.inviteAddressWithParams(addressToCall, params!!)
                                 sipCore!!.inviteAddressWithParams(addressToCall, params!!)
                                 Log.d(TAG, ">>>>>>>>>>> invite address: " + addressToCall.asString())
                                 Log.d(TAG, ">>>>>>>>>>> invite address: " + addressToCall.asString())
                             }
                             }
-                        }
+                        }*/
                     } else if (tcpModel.getAction() == TcpAction.VoiceAction.REJECT) {//对方拒绝
                     } else if (tcpModel.getAction() == TcpAction.VoiceAction.REJECT) {//对方拒绝
                         showMessage("对方拒绝")
                         showMessage("对方拒绝")
                         //MediaPlayHelper.getInstance().stopMusic()
                         //MediaPlayHelper.getInstance().stopMusic()

+ 1 - 1
android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/adapter/BroadcastAdapter.kt

@@ -46,7 +46,7 @@ class BroadcastAdapter(var context: BroadcastFragment, val data: ArrayList<Strin
     /**
     /**
      * 创建ViewHolder
      * 创建ViewHolder
      */
      */
-    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): BaseRecyclerViewHolder<AdapterBroadcastBinding> {
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseRecyclerViewHolder<AdapterBroadcastBinding> {
         return BaseRecyclerViewHolder.build(parent, R.layout.adapter_broadcast)
         return BaseRecyclerViewHolder.build(parent, R.layout.adapter_broadcast)
     }
     }
 
 

+ 4 - 2
android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/adapter/CallRecordsItemAdapter.kt

@@ -65,7 +65,7 @@ class CallRecordsItemAdapter(val data: ArrayList<InteractionVO>, val context: Ca
     /**
     /**
      * 创建ViewHolder
      * 创建ViewHolder
      */
      */
-    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): BaseRecyclerViewHolder<AdapterCallRecordsItemBinding> {
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseRecyclerViewHolder<AdapterCallRecordsItemBinding> {
         return BaseRecyclerViewHolder.build(parent, R.layout.adapter_call_records_item)
         return BaseRecyclerViewHolder.build(parent, R.layout.adapter_call_records_item)
     }
     }
 
 
@@ -210,7 +210,9 @@ class CallRecordsItemAdapter(val data: ArrayList<InteractionVO>, val context: Ca
                     binding.playTv.setBackgroundResource(R.drawable.wei_bo_fang)
                     binding.playTv.setBackgroundResource(R.drawable.wei_bo_fang)
                     //binding.processingTimeTv.text = "未播放"
                     //binding.processingTimeTv.text = "未播放"
                 }
                 }
-            } else if (itemData.actionType == TcpType.VOICE.name || itemData.actionType == TcpType.VIDEO.name) {
+            } else if (itemData.actionType == TcpType.VOICE.name
+                || itemData.actionType == TcpType.VIDEO.name
+                || itemData.actionType == TcpType.PHONE.name) {
                 binding.conductorNameTv.visibility = View.INVISIBLE
                 binding.conductorNameTv.visibility = View.INVISIBLE
                 if (itemData.actionAccept != null) {
                 if (itemData.actionAccept != null) {
                     //已接听
                     //已接听

+ 1 - 1
android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/adapter/DoctorHostAdapter.kt

@@ -58,7 +58,7 @@ class DoctorHostAdapter(val data:ArrayList<String>) : BaseDelegateAdapter<BaseRe
     /**
     /**
      * 创建ViewHolder
      * 创建ViewHolder
      */
      */
-    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): BaseRecyclerViewHolder<AdapterDoctorHostBinding> {
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseRecyclerViewHolder<AdapterDoctorHostBinding> {
         return BaseRecyclerViewHolder.build(parent, R.layout.adapter_doctor_host)
         return BaseRecyclerViewHolder.build(parent, R.layout.adapter_doctor_host)
     }
     }
 
 

+ 1 - 1
android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/adapter/FamilyMembersAdapter.kt

@@ -42,7 +42,7 @@ class FamilyMembersAdapter (val data: ArrayList<MemberDO>) : BaseDelegateAdapter
     /**
     /**
      * 创建ViewHolder
      * 创建ViewHolder
      */
      */
-    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): BaseRecyclerViewHolder<AdapterFamilyMembersBinding> {
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseRecyclerViewHolder<AdapterFamilyMembersBinding> {
         return BaseRecyclerViewHolder.build(parent, R.layout.adapter_family_members)
         return BaseRecyclerViewHolder.build(parent, R.layout.adapter_family_members)
     }
     }
 
 

+ 1 - 1
android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/adapter/FrameBedVosAdapter.kt

@@ -44,7 +44,7 @@ class FrameBedVosAdapter(val data:ArrayList<FrameBedVO>) : BaseDelegateAdapter<B
     /**
     /**
      * 创建ViewHolder
      * 创建ViewHolder
      */
      */
-    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): BaseRecyclerViewHolder<AdapterFrameBedVosBinding> {
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseRecyclerViewHolder<AdapterFrameBedVosBinding> {
         return BaseRecyclerViewHolder.build(parent, R.layout.adapter_frame_bed_vos)
         return BaseRecyclerViewHolder.build(parent, R.layout.adapter_frame_bed_vos)
     }
     }
     /**
     /**

+ 1 - 1
android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/adapter/FrameBedVosConfinementAdapter.kt

@@ -63,7 +63,7 @@ class FrameBedVosConfinementAdapter(val data: ArrayList<FrameBedVO>) : BaseDeleg
     /**
     /**
      * 创建ViewHolder
      * 创建ViewHolder
      */
      */
-    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): BaseRecyclerViewHolder<AdapterYueZiZhongXinFramePartBinding> {
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseRecyclerViewHolder<AdapterYueZiZhongXinFramePartBinding> {
         return BaseRecyclerViewHolder.build(parent, R.layout.adapter_yue_zi_zhong_xin_frame_part)
         return BaseRecyclerViewHolder.build(parent, R.layout.adapter_yue_zi_zhong_xin_frame_part)
     }
     }
 
 

+ 1 - 1
android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/adapter/FramePartItemAdapter.kt

@@ -58,7 +58,7 @@ var TAG = FramePartItemAdapter::class.java.getSimpleName()
     /**
     /**
      * 创建ViewHolder
      * 创建ViewHolder
      */
      */
-    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): BaseRecyclerViewHolder<AdapterFramePartItemBinding> {
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseRecyclerViewHolder<AdapterFramePartItemBinding> {
         return BaseRecyclerViewHolder.build(parent, R.layout.adapter_frame_part_item)
         return BaseRecyclerViewHolder.build(parent, R.layout.adapter_frame_part_item)
     }
     }
 
 

+ 1 - 1
android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/adapter/InpatientWardAdapter.kt

@@ -27,7 +27,7 @@ class InpatientWardAdapter(val data:ArrayList<String>) : BaseDelegateAdapter<Bas
         return LinearLayoutHelper(0,data.size)
         return LinearLayoutHelper(0,data.size)
     }
     }
 
 
-    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): BaseRecyclerViewHolder<AdapterInpatientWardBinding> {
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseRecyclerViewHolder<AdapterInpatientWardBinding> {
         return BaseRecyclerViewHolder.build(parent, R.layout.adapter_inpatient_ward)
         return BaseRecyclerViewHolder.build(parent, R.layout.adapter_inpatient_ward)
     }
     }
 
 

+ 1 - 1
android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/adapter/NurseMoveAdapter.kt

@@ -54,7 +54,7 @@ class NurseMoveAdapter(val data:ArrayList<String>) : BaseDelegateAdapter<BaseRec
     /**
     /**
      * 创建ViewHolder
      * 创建ViewHolder
      */
      */
-    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): BaseRecyclerViewHolder<AdapterDoctorHostBinding> {
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseRecyclerViewHolder<AdapterDoctorHostBinding> {
         return BaseRecyclerViewHolder.build(parent, R.layout.adapter_doctor_host)
         return BaseRecyclerViewHolder.build(parent, R.layout.adapter_doctor_host)
     }
     }
 
 

+ 1 - 1
android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/adapter/OtherHostAdapter.kt

@@ -57,7 +57,7 @@ class OtherHostAdapter (val data:ArrayList<String>) : BaseDelegateAdapter<BaseRe
     /**
     /**
      * 创建ViewHolder
      * 创建ViewHolder
      */
      */
-    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): BaseRecyclerViewHolder<AdapterDoctorHostBinding> {
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseRecyclerViewHolder<AdapterDoctorHostBinding> {
         return BaseRecyclerViewHolder.build(parent, R.layout.adapter_doctor_host)
         return BaseRecyclerViewHolder.build(parent, R.layout.adapter_doctor_host)
     }
     }
 
 

+ 1 - 1
android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/adapter/ResponsibilityBedAdapter.kt

@@ -52,7 +52,7 @@ class ResponsibilityBedAdapter(val data:ArrayList<String>) : BaseDelegateAdapter
     /**
     /**
      * 创建ViewHolder
      * 创建ViewHolder
      */
      */
-    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): BaseRecyclerViewHolder<AdapterResponsibilityBedBinding> {
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseRecyclerViewHolder<AdapterResponsibilityBedBinding> {
         return BaseRecyclerViewHolder.build(parent, R.layout.adapter_responsibility_bed)
         return BaseRecyclerViewHolder.build(parent, R.layout.adapter_responsibility_bed)
     }
     }
 
 

+ 1 - 1
android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/adapter/SickbedAdapter.kt

@@ -35,7 +35,7 @@ class SickbedAdapter(var context: Context, var mListener: FramePartFragment.OnIt
     /**
     /**
      * 创建ViewHolder
      * 创建ViewHolder
      */
      */
-    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): BaseRecyclerViewHolder<AdapterSickbedBinding> {
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseRecyclerViewHolder<AdapterSickbedBinding> {
         return BaseRecyclerViewHolder.build(parent, R.layout.adapter_sickbed)
         return BaseRecyclerViewHolder.build(parent, R.layout.adapter_sickbed)
     }
     }
 
 

+ 1 - 1
android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/adapter/VisitManagementAdapter.kt

@@ -54,7 +54,7 @@ class VisitManagementAdapter(val data:ArrayList<String>) : BaseDelegateAdapter<B
     /**
     /**
      * 创建ViewHolder
      * 创建ViewHolder
      */
      */
-    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): BaseRecyclerViewHolder<AdapterDoctorHostBinding> {
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseRecyclerViewHolder<AdapterDoctorHostBinding> {
         return BaseRecyclerViewHolder.build(parent, R.layout.adapter_doctor_host)
         return BaseRecyclerViewHolder.build(parent, R.layout.adapter_doctor_host)
     }
     }
 
 

+ 2 - 3
android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/fragment/CallRecordsFragment.kt

@@ -304,7 +304,7 @@ class CallRecordsFragment : BaseFragment<CallRecordsFragmentPresenter, FragmentC
             adapter.data.clear()
             adapter.data.clear()
             if (data.size > 0) {
             if (data.size > 0) {
                 for (item in data) {
                 for (item in data) {
-                    if (TcpType.VIDEO.name == item.actionType || TcpType.VOICE.name == item.actionType
+                    if (TcpType.VIDEO.name == item.actionType || TcpType.VOICE.name == item.actionType || TcpType.PHONE.name == item.actionType
                         || TcpType.ENTRACEGUARD.name == item.actionType || TcpType.SOS.name == item.actionType
                         || TcpType.ENTRACEGUARD.name == item.actionType || TcpType.SOS.name == item.actionType
                         || TcpType.EVENT.name == item.actionType || TcpType.IM.name == item.actionType) {
                         || TcpType.EVENT.name == item.actionType || TcpType.IM.name == item.actionType) {
                         adapter.data.add(item)
                         adapter.data.add(item)
@@ -316,7 +316,7 @@ class CallRecordsFragment : BaseFragment<CallRecordsFragmentPresenter, FragmentC
         } else {
         } else {
             if (data.size > 0) {
             if (data.size > 0) {
                 for (item in data) {
                 for (item in data) {
-                    if (TcpType.VIDEO.name == item.actionType || TcpType.VOICE.name == item.actionType
+                    if (TcpType.VIDEO.name == item.actionType || TcpType.VOICE.name == item.actionType || TcpType.PHONE.name == item.actionType
                         || TcpType.ENTRACEGUARD.name == item.actionType || TcpType.SOS.name == item.actionType
                         || TcpType.ENTRACEGUARD.name == item.actionType || TcpType.SOS.name == item.actionType
                         || TcpType.EVENT.name == item.actionType || TcpType.IM.name == item.actionType) {
                         || TcpType.EVENT.name == item.actionType || TcpType.IM.name == item.actionType) {
                         adapter.data.add(item)
                         adapter.data.add(item)
@@ -367,7 +367,6 @@ class CallRecordsFragment : BaseFragment<CallRecordsFragmentPresenter, FragmentC
         //下拉刷新
         //下拉刷新
         mViewDataBinding.refresh.setOnRefreshListener {
         mViewDataBinding.refresh.setOnRefreshListener {
             page = 1
             page = 1
-            //todo 这里需要改一下
             presenter.loadFloor(page_no, page_size, part_id, choice, event_name)
             presenter.loadFloor(page_no, page_size, part_id, choice, event_name)
         }
         }
         //上拉加载更多
         //上拉加载更多

+ 47 - 8
android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/fragment/FramePartFragment.kt

@@ -1,6 +1,7 @@
 package com.wdkl.ncs.android.component.nursehome.fragment
 package com.wdkl.ncs.android.component.nursehome.fragment
 
 
 import android.content.Intent
 import android.content.Intent
+import android.net.Uri
 import android.text.TextUtils
 import android.text.TextUtils
 import android.util.Log
 import android.util.Log
 import android.view.View
 import android.view.View
@@ -14,7 +15,6 @@ import com.wdkl.ncs.android.component.nursehome.activity.SipAudioCallActivity
 import com.wdkl.ncs.android.component.nursehome.activity.WebRCTVoipAudioActivity
 import com.wdkl.ncs.android.component.nursehome.activity.WebRCTVoipAudioActivity
 import com.wdkl.ncs.android.component.nursehome.adapter.FamilyMembersAdapter
 import com.wdkl.ncs.android.component.nursehome.adapter.FamilyMembersAdapter
 import com.wdkl.ncs.android.component.nursehome.adapter.FrameBedVosConfinementAdapter
 import com.wdkl.ncs.android.component.nursehome.adapter.FrameBedVosConfinementAdapter
-import com.wdkl.ncs.android.middleware.common.Constants
 import com.wdkl.ncs.android.component.nursehome.databinding.FragmentFramePartBinding
 import com.wdkl.ncs.android.component.nursehome.databinding.FragmentFramePartBinding
 import com.wdkl.ncs.android.component.nursehome.launch.NurseHomeLaunch
 import com.wdkl.ncs.android.component.nursehome.launch.NurseHomeLaunch
 import com.wdkl.ncs.android.component.nursehome.settingconfig.SettingConfig
 import com.wdkl.ncs.android.component.nursehome.settingconfig.SettingConfig
@@ -25,24 +25,26 @@ import com.wdkl.ncs.android.lib.base.BaseFragment
 import com.wdkl.ncs.android.lib.utils.debugLog
 import com.wdkl.ncs.android.lib.utils.debugLog
 import com.wdkl.ncs.android.lib.utils.showMessage
 import com.wdkl.ncs.android.lib.utils.showMessage
 import com.wdkl.ncs.android.lib.vo.filter
 import com.wdkl.ncs.android.lib.vo.filter
+import com.wdkl.ncs.android.middleware.common.Constants
 import com.wdkl.ncs.android.middleware.logic.contract.nursehome.FramePartContract
 import com.wdkl.ncs.android.middleware.logic.contract.nursehome.FramePartContract
 import com.wdkl.ncs.android.middleware.logic.presenter.nursehome.FramePartPresenter
 import com.wdkl.ncs.android.middleware.logic.presenter.nursehome.FramePartPresenter
 import com.wdkl.ncs.android.middleware.model.dos.RemarkDO
 import com.wdkl.ncs.android.middleware.model.dos.RemarkDO
 import com.wdkl.ncs.android.middleware.model.vo.*
 import com.wdkl.ncs.android.middleware.model.vo.*
 import com.wdkl.ncs.android.middleware.tcp.TcpClient
 import com.wdkl.ncs.android.middleware.tcp.TcpClient
-import com.wdkl.ncs.android.middleware.tcp.TcpClientHandler
 import com.wdkl.ncs.android.middleware.tcp.channel.DeviceChannel
 import com.wdkl.ncs.android.middleware.tcp.channel.DeviceChannel
+import com.wdkl.ncs.android.middleware.tcp.channel.PhoneUtil
 import com.wdkl.ncs.android.middleware.tcp.channel.VoiceUtil
 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.dto.TcpModel
+import com.wdkl.ncs.android.middleware.tcp.enums.CommunicationEnum
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpAction
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpAction
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpType
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpType
+import com.wdkl.ncs.android.middleware.utils.ContactHelper
 import com.wdkl.ncs.android.middleware.utils.MessageEvent
 import com.wdkl.ncs.android.middleware.utils.MessageEvent
+import com.wdkl.ncs.janus.rtc.WebRTCEngine
 import kotlinx.android.synthetic.main.fragment_frame_part.*
 import kotlinx.android.synthetic.main.fragment_frame_part.*
 import kotlinx.android.synthetic.main.right_basic_information.*
 import kotlinx.android.synthetic.main.right_basic_information.*
-import kotlinx.android.synthetic.main.right_incident.*
 import org.greenrobot.eventbus.Subscribe
 import org.greenrobot.eventbus.Subscribe
 import org.greenrobot.eventbus.ThreadMode
 import org.greenrobot.eventbus.ThreadMode
-import kotlin.collections.ArrayList
 
 
 /**
 /**
  * 首页病房病床Fragment
  * 首页病房病床Fragment
@@ -137,7 +139,7 @@ class FramePartFragment : BaseFragment<FramePartPresenter, FragmentFramePartBind
             presenter.loadData(Constants.part_id)
             presenter.loadData(Constants.part_id)
         }
         }
 
 
-        if (!Constants.supportCamera) {
+        if (!Constants.supportCamera || Constants.phoneType != CommunicationEnum.NET_WORK.value()) {
             call_the_video_tv.visibility = View.GONE
             call_the_video_tv.visibility = View.GONE
         }
         }
     }
     }
@@ -165,6 +167,7 @@ class FramePartFragment : BaseFragment<FramePartPresenter, FragmentFramePartBind
                 } else {
                 } else {
                     time_tv.text = "无"
                     time_tv.text = "无"
                 }
                 }
+                mobile_tv.text = data.bedDevicePhoneNumber
             } else {
             } else {
                 name_tv.text = "空床位"
                 name_tv.text = "空床位"
                 age_tv.text = "无"
                 age_tv.text = "无"
@@ -250,6 +253,15 @@ class FramePartFragment : BaseFragment<FramePartPresenter, FragmentFramePartBind
                             emptyFrameBedVOs.add(bedVO)
                             emptyFrameBedVOs.add(bedVO)
                         } else {
                         } else {
                             frameBedVO.add(bedVO)
                             frameBedVO.add(bedVO)
+                            if (Constants.phoneType == CommunicationEnum.MOBILE_PHONE.value()) {
+                                if (!TextUtils.isEmpty(bedVO.bedDevicePhoneNumber)) {
+                                    ContactHelper.setContact(
+                                        activity,
+                                        bedVO.customerName,
+                                        bedVO.bedDevicePhoneNumber
+                                    )
+                                }
+                            }
                         }
                         }
                     }
                     }
                 }
                 }
@@ -364,9 +376,36 @@ class FramePartFragment : BaseFragment<FramePartPresenter, FragmentFramePartBind
                 return
                 return
             }
             }
 
 
-            onlyAudio = true
-            val voiceUtilTcpModel = VoiceUtil.voiceCall(Constants.ids, frameBed.bedDeviceId)
-            TcpClient.getInstance().sendMsg(voiceUtilTcpModel.toJson())
+            if (Constants.phoneType == CommunicationEnum.MOBILE_PHONE.value()) {
+                try {
+                    if (!TextUtils.isEmpty(frameBed.bedDevicePhoneNumber)) {
+                        val intent = Intent(Intent.ACTION_CALL, Uri.parse("tel:" + frameBed.bedDevicePhoneNumber))
+                        context.startActivity(intent)
+
+                        if (Constants.hookOn) {
+                            //手柄放下,外放模式
+                            WebRTCEngine.getInstance().toggleSpeaker(true)
+                        } else {
+                            //手柄拿起,听筒模式
+                            WebRTCEngine.getInstance().toggleSpeaker(false)
+                        }
+
+                        if (!Constants.uploadCalllog) {
+                            //发送tcp
+                            val tcpModel = PhoneUtil.phoneCall(Constants.ids, frameBed.bedDeviceId)
+                            TcpClient.getInstance().sendMsg(tcpModel.toJson())
+                        }
+                    } else {
+                        showMessage("没有手机号")
+                    }
+                } catch (e: Exception) {
+                    showMessage("呼叫失败,请检查手机号")
+                }
+            } else {
+                onlyAudio = true
+                val voiceUtilTcpModel = VoiceUtil.voiceCall(Constants.ids, frameBed.bedDeviceId)
+                TcpClient.getInstance().sendMsg(voiceUtilTcpModel.toJson())
+            }
         }
         }
 
 
         //视频呼叫
         //视频呼叫

+ 1 - 3
android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/fragment/SystemSettingsFragment.kt

@@ -10,22 +10,20 @@ import android.util.Log
 import android.view.View
 import android.view.View
 import android.widget.SeekBar
 import android.widget.SeekBar
 import com.enation.javashop.net.engine.model.NetState
 import com.enation.javashop.net.engine.model.NetState
-import com.wdkl.ncs.android.component.nursehome.BuildConfig
 import com.wdkl.ncs.android.component.nursehome.R
 import com.wdkl.ncs.android.component.nursehome.R
 import com.wdkl.ncs.android.component.nursehome.activity.NurseHomeActivity
 import com.wdkl.ncs.android.component.nursehome.activity.NurseHomeActivity
 import com.wdkl.ncs.android.middleware.common.Constants
 import com.wdkl.ncs.android.middleware.common.Constants
 import com.wdkl.ncs.android.component.nursehome.databinding.FragmentSystemSettingsBinding
 import com.wdkl.ncs.android.component.nursehome.databinding.FragmentSystemSettingsBinding
-import com.wdkl.ncs.android.component.nursehome.helper.SerialPortHelper
 import com.wdkl.ncs.android.component.nursehome.launch.NurseHomeLaunch
 import com.wdkl.ncs.android.component.nursehome.launch.NurseHomeLaunch
 import com.wdkl.ncs.android.component.nursehome.settingconfig.SettingConfig
 import com.wdkl.ncs.android.component.nursehome.settingconfig.SettingConfig
 import com.wdkl.ncs.android.component.nursehome.util.*
 import com.wdkl.ncs.android.component.nursehome.util.*
 import com.wdkl.ncs.android.lib.base.BaseFragment
 import com.wdkl.ncs.android.lib.base.BaseFragment
 import com.wdkl.ncs.android.lib.utils.showMessage
 import com.wdkl.ncs.android.lib.utils.showMessage
+import com.wdkl.ncs.android.middleware.BuildConfig
 import com.wdkl.ncs.android.middleware.logic.contract.nursehome.SystemSettingsContract
 import com.wdkl.ncs.android.middleware.logic.contract.nursehome.SystemSettingsContract
 import com.wdkl.ncs.android.middleware.logic.presenter.nursehome.SystemSettingsPresenter
 import com.wdkl.ncs.android.middleware.logic.presenter.nursehome.SystemSettingsPresenter
 import com.wdkl.ncs.android.middleware.model.bean.SettingConfiguration
 import com.wdkl.ncs.android.middleware.model.bean.SettingConfiguration
 import com.wdkl.ncs.android.middleware.model.dos.PartSettingDO
 import com.wdkl.ncs.android.middleware.model.dos.PartSettingDO
-import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel
 import com.wdkl.ncs.android.middleware.utils.MessageEvent
 import com.wdkl.ncs.android.middleware.utils.MessageEvent
 import com.wdkl.ncs.host.activity.SipTestActivity
 import com.wdkl.ncs.host.activity.SipTestActivity
 import kotlinx.android.synthetic.main.fragment_system_settings.*
 import kotlinx.android.synthetic.main.fragment_system_settings.*

+ 44 - 3
android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/helper/HttpHelper.java

@@ -21,13 +21,52 @@ import static com.wdkl.ncs.android.component.nursehome.helper.AppUpdateHelper.FI
 
 
 
 
 public class HttpHelper {
 public class HttpHelper {
+    private static OkHttpClient okHttpClient;
+
+    public static void postData(String url, String jsonData, final UploadCallback callback) {
+        if (okHttpClient == null) {
+            okHttpClient = new OkHttpClient();
+        }
+
+        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), jsonData);
+        Request request = new Request.Builder()
+                .url(url)
+                .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("HttpHelper", "post response: " + response.toString());
+                if( response.code()==200) {
+                    if (callback != null) {
+                        callback.onSuccess("success");
+                    }
+                } else {
+                    if (callback != null) {
+                        callback.onFail();
+                    }
+                }
+            }
+        });
+    }
 
 
     /**
     /**
      * @param url   服务器地址
      * @param url   服务器地址
      * @param file  所要上传的文件
      * @param file  所要上传的文件
      */
      */
     public static void upload(String url, File file, final UploadCallback callback) {
     public static void upload(String url, File file, final UploadCallback callback) {
-        OkHttpClient client = new OkHttpClient();
+        if (okHttpClient == null) {
+            okHttpClient = new OkHttpClient();
+        }
+
         RequestBody requestBody = new MultipartBody.Builder()
         RequestBody requestBody = new MultipartBody.Builder()
                 .setType(MultipartBody.FORM)
                 .setType(MultipartBody.FORM)
                 .addFormDataPart("file", file.getName(), RequestBody.create(MediaType.parse("multipart/form-data"), file))
                 .addFormDataPart("file", file.getName(), RequestBody.create(MediaType.parse("multipart/form-data"), file))
@@ -37,7 +76,7 @@ public class HttpHelper {
                 .post(requestBody)
                 .post(requestBody)
                 .build();
                 .build();
 
 
-        client.newCall(request).enqueue(new Callback() {
+        okHttpClient.newCall(request).enqueue(new Callback() {
             @Override
             @Override
             public void onFailure(Call call, IOException e) {
             public void onFailure(Call call, IOException e) {
                 if (callback != null) {
                 if (callback != null) {
@@ -65,7 +104,9 @@ public class HttpHelper {
 
 
     public static void download(String url, final DownloadListener listener) {
     public static void download(String url, final DownloadListener listener) {
         Request request = new Request.Builder().url(url).build();
         Request request = new Request.Builder().url(url).build();
-        OkHttpClient okHttpClient = new OkHttpClient();
+        if (okHttpClient == null) {
+            okHttpClient = new OkHttpClient();
+        }
         okHttpClient.newCall(request).enqueue(new Callback() {
         okHttpClient.newCall(request).enqueue(new Callback() {
             @Override
             @Override
             public void onFailure(Call call, IOException e) {
             public void onFailure(Call call, IOException e) {

+ 114 - 0
android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/receiver/PhoneStateReceiver.java

@@ -0,0 +1,114 @@
+package com.wdkl.ncs.android.component.nursehome.receiver;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Build;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+
+import com.wdkl.ncs.android.component.nursehome.util.PhoneCallUtil;
+import com.wdkl.ncs.android.middleware.common.Constants;
+import com.wdkl.ncs.android.middleware.tcp.TcpClient;
+import com.wdkl.ncs.android.middleware.tcp.channel.DeviceChannel;
+import com.wdkl.ncs.android.middleware.tcp.channel.PhoneUtil;
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel;
+import com.wdkl.ncs.android.middleware.utils.MessageEvent;
+
+import org.greenrobot.eventbus.EventBus;
+
+import static com.wdkl.ncs.android.lib.utils.ExtendMethodsKt.showMessage;
+
+public class PhoneStateReceiver extends BroadcastReceiver {
+    private static final String TAG = "PhoneStateReceiver";
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        String action = intent.getAction();
+        Log.d(TAG, "PhoneStateReceiver action: " + action);
+
+        if (action.equals(Intent.ACTION_NEW_OUTGOING_CALL)) {
+            String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
+            DeviceChannel.calling = true;
+            Log.d(TAG, "PhoneStateReceiver EXTRA_PHONE_NUMBER: " + phoneNumber);
+        } else {
+            String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
+            String extraIncomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
+            Log.d(TAG, "PhoneStateReceiver onReceive state: " + state + ", extraIncomingNumber: " + extraIncomingNumber);
+
+            if (state.equalsIgnoreCase(TelephonyManager.EXTRA_STATE_IDLE)) {
+                //待机中
+                //Log.d(TAG, "PhoneStateReceiver idle");
+                if (Constants.Companion.getPhoneState() != Constants.PHONE_IDLE) {
+                    if (!Constants.uploadCalllog) {
+                        //发送tcp
+                        if (Constants.Companion.getPhoneDataVO() != null) {
+                            TcpModel tcpModel = PhoneUtil.phoneHandoff(Constants.Companion.getIds(), Constants.Companion.getPhoneTid(), Constants.Companion.getPhoneDataVO());
+                            TcpClient.getInstance().sendMsg(tcpModel.toJson());
+                            Constants.Companion.setPhoneDataVO(null);
+                        }
+                    } else {
+                        //通话结束,上传通话记录
+                        EventBus.getDefault().post(new MessageEvent("call_end", Constants.EVENT_CALL_END));
+                    }
+                }
+
+                DeviceChannel.calling = false;
+                Constants.Companion.setPhoneState(Constants.PHONE_IDLE);
+            } else if (state.equalsIgnoreCase(TelephonyManager.EXTRA_STATE_RINGING) && extraIncomingNumber != null) {
+                //非白名单号码拦截并删除记录
+                if (Constants.Companion.getPhoneWhiteList() != null) {
+                    for (String s : Constants.Companion.getPhoneWhiteList()) {
+                        if (s.contains(extraIncomingNumber)) { //号码在白名单内修改通话状态,并退出方法
+                            //Log.d(TAG, "PhoneStateReceiver incoming call: " + extraIncomingNumber);
+                            DeviceChannel.calling = true;
+                            Constants.Companion.setPhoneState(Constants.PHONE_INCOMING);
+                            return;
+                        }
+                    }
+                    //循环结束,说明来电号码不在白名单内,挂断来电
+                    showMessage("非法号码:" + extraIncomingNumber);
+                    //卡尔话机特殊处理
+                    if ("KT8001-2F".equals(Build.MODEL)) {
+                        PhoneCallUtil.endCallByKaer(context);
+                        Log.d(TAG, "end call 11111111");
+                    } else {
+                        boolean res = PhoneCallUtil.endCall(context);
+                        Log.d(TAG, "end call result: " + res);
+                    }
+                    PhoneCallUtil.deleteCallLog(context, extraIncomingNumber);
+                }
+            } else if (state.equalsIgnoreCase(TelephonyManager.EXTRA_STATE_OFFHOOK) && extraIncomingNumber != null) {
+                //通话中
+                //Log.d(TAG, "PhoneStateReceiver in call: " + extraIncomingNumber);
+                DeviceChannel.calling = true;
+                if (Constants.Companion.getPhoneState() == Constants.PHONE_INCOMING) {
+                    //发送tcp
+                    if (!Constants.uploadCalllog) {
+                        if (Constants.Companion.getPhoneDataVO() != null) {
+                            TcpModel tcpModel = PhoneUtil.phoneAccept(Constants.Companion.getIds(), Constants.Companion.getPhoneTid(), Constants.Companion.getPhoneDataVO());
+                            TcpClient.getInstance().sendMsg(tcpModel.toJson());
+                        }
+                    }
+                } else if (Constants.Companion.getPhoneState() == Constants.PHONE_IDLE) {
+                    Constants.Companion.setPhoneState(Constants.PHONE_OUTGOING);
+                } else {
+                    Constants.Companion.setPhoneState(Constants.PHONE_CALLING);
+                }
+
+                //非白名单号码拦截并删除记录
+                if (!Constants.Companion.getPhoneWhiteList().contains(extraIncomingNumber)) {
+                    showMessage("非法号码!");
+                    Constants.Companion.setPhoneState(Constants.PHONE_IDLE);
+                    if ("KT8001-2F".equals(Build.MODEL)) {
+                        PhoneCallUtil.endCallByKaer(context);
+                    } else {
+                        boolean res = PhoneCallUtil.endCall(context);
+                        Log.d(TAG, "end call result22222: " + res);
+                    }
+                    PhoneCallUtil.deleteCallLog(context, extraIncomingNumber);
+                }
+            }
+        }
+    }
+}

+ 68 - 0
android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/service/APPService.kt

@@ -3,6 +3,7 @@ package com.wdkl.ncs.android.component.nursehome.service
 import android.app.*
 import android.app.*
 import android.content.Context
 import android.content.Context
 import android.content.Intent
 import android.content.Intent
+import android.content.IntentFilter
 import android.net.ConnectivityManager
 import android.net.ConnectivityManager
 import android.net.Network
 import android.net.Network
 import android.net.NetworkCapabilities
 import android.net.NetworkCapabilities
@@ -15,9 +16,13 @@ import android.util.Log
 import com.alibaba.fastjson.JSON
 import com.alibaba.fastjson.JSON
 import com.alibaba.fastjson.JSONObject
 import com.alibaba.fastjson.JSONObject
 import com.enation.javashop.utils.logger.LoggerFactory
 import com.enation.javashop.utils.logger.LoggerFactory
+import com.google.gson.FieldNamingPolicy
 import com.google.gson.Gson
 import com.google.gson.Gson
+import com.google.gson.GsonBuilder
 import com.wdkl.ncs.android.component.nursehome.R
 import com.wdkl.ncs.android.component.nursehome.R
 import com.wdkl.ncs.android.component.nursehome.helper.AppUpdateHelper
 import com.wdkl.ncs.android.component.nursehome.helper.AppUpdateHelper
+import com.wdkl.ncs.android.component.nursehome.helper.HttpHelper
+import com.wdkl.ncs.android.component.nursehome.receiver.PhoneStateReceiver
 import com.wdkl.ncs.android.component.nursehome.settingconfig.SettingConfig
 import com.wdkl.ncs.android.component.nursehome.settingconfig.SettingConfig
 import com.wdkl.ncs.android.middleware.common.Constants
 import com.wdkl.ncs.android.middleware.common.Constants
 import com.wdkl.ncs.android.component.nursehome.util.AppUtil
 import com.wdkl.ncs.android.component.nursehome.util.AppUtil
@@ -27,6 +32,7 @@ import com.wdkl.ncs.android.lib.base.BaseApplication
 import com.wdkl.ncs.android.lib.utils.AppTool
 import com.wdkl.ncs.android.lib.utils.AppTool
 import com.wdkl.ncs.android.lib.utils.TimeHandle
 import com.wdkl.ncs.android.lib.utils.TimeHandle
 import com.wdkl.ncs.android.lib.utils.showMessage
 import com.wdkl.ncs.android.lib.utils.showMessage
+import com.wdkl.ncs.android.middleware.api.ApiManager
 import com.wdkl.ncs.android.middleware.model.vo.InteractionVO
 import com.wdkl.ncs.android.middleware.model.vo.InteractionVO
 import com.wdkl.ncs.android.middleware.tcp.TcpClient
 import com.wdkl.ncs.android.middleware.tcp.TcpClient
 import com.wdkl.ncs.android.middleware.tcp.TcpClientHandler
 import com.wdkl.ncs.android.middleware.tcp.TcpClientHandler
@@ -35,6 +41,7 @@ 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.TcpAction
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpType
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpType
 import com.wdkl.ncs.android.middleware.utils.CommonUtils
 import com.wdkl.ncs.android.middleware.utils.CommonUtils
+import com.wdkl.ncs.android.middleware.utils.ContactHelper
 import com.wdkl.ncs.android.middleware.utils.MessageEvent
 import com.wdkl.ncs.android.middleware.utils.MessageEvent
 import org.greenrobot.eventbus.EventBus
 import org.greenrobot.eventbus.EventBus
 import org.greenrobot.eventbus.Subscribe
 import org.greenrobot.eventbus.Subscribe
@@ -49,6 +56,8 @@ class APPService : Service() {
     private var notificationId: String = "channelId"
     private var notificationId: String = "channelId"
     private var notificationName: String = "channelName"
     private var notificationName: String = "channelName"
 
 
+    private lateinit var receiver: PhoneStateReceiver
+
     /**
     /**
      * 监听网络状态变化回调
      * 监听网络状态变化回调
      */
      */
@@ -90,6 +99,20 @@ class APPService : Service() {
 
 
     }
     }
 
 
+    fun registerCallListener() {
+        val intentFilter = IntentFilter()
+        intentFilter.addAction("android.intent.action.NEW_OUTGOING_CALL")
+        intentFilter.addAction("android.intent.action.PHONE_STATE")
+        receiver = PhoneStateReceiver()
+        registerReceiver(receiver, intentFilter)
+    }
+
+    fun unRegisterCallListener() {
+        if (receiver != null) {
+            unregisterReceiver(receiver)
+        }
+    }
+
     private fun getNotification(): Notification {
     private fun getNotification(): Notification {
         val builder: Notification.Builder = Notification.Builder(this)
         val builder: Notification.Builder = Notification.Builder(this)
             .setSmallIcon(R.mipmap.ic_launcher)
             .setSmallIcon(R.mipmap.ic_launcher)
@@ -122,6 +145,8 @@ class APPService : Service() {
             stopForeground(true)// 停止前台服务--参数:表示是否移除之前的通知
             stopForeground(true)// 停止前台服务--参数:表示是否移除之前的通知
         }
         }
         EventBus.getDefault().unregister(this)
         EventBus.getDefault().unregister(this)
+
+        unRegisterCallListener()
     }
     }
 
 
     inner class ServiceBinder : Binder() {
     inner class ServiceBinder : Binder() {
@@ -227,7 +252,50 @@ class APPService : Service() {
                     AppUpdateHelper.rebootRoot()
                     AppUpdateHelper.rebootRoot()
                 }
                 }
             }
             }
+
+            Constants.EVENT_PHONE_DATA -> {
+                val tcpModel = messageEvent.getMessage() as TcpModel
+                if (tcpModel.data != null) {
+                    Constants.phoneDataVO = Gson().fromJson(tcpModel.data.toString(), InteractionVO::class.java)
+                    Constants.phoneTid = tcpModel.tid
+                }
+            }
+
+            Constants.EVENT_CALL_END -> {
+                //通话结束,上传这条通话记录
+                Thread {
+                    //等待1s再上传
+                    try {
+                        Thread.sleep(1500)
+
+                        val callLog = ContactHelper.getLatestCallLog(BaseApplication.appContext)
+                        val gson = GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create()
+                        val data = gson.toJson(callLog)
+                        uploadCallLog(data, 0)
+                    } catch (e: Exception) {
+                        //
+                    }
+                }.start()
+            }
+        }
+    }
+
+    private fun uploadCallLog(jsonData: String, count: Int) {
+        if (count > 2) {
+            return
         }
         }
+
+        Log.i(TAG, "upload call log: $jsonData")
+        HttpHelper.postData(ApiManager.urlManager.base + "interaction/set_phone_interaction", jsonData, object: HttpHelper.UploadCallback{
+            override fun onFail() {
+                Log.e(TAG, "call log upload failed")
+                uploadCallLog(jsonData, count+1)
+            }
+
+            override fun onSuccess(data: String?) {
+                Log.d(TAG, "call log upload success")
+            }
+        })
     }
     }
 
 
 }
 }

+ 139 - 0
android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/util/PhoneCallUtil.java

@@ -0,0 +1,139 @@
+package com.wdkl.ncs.android.component.nursehome.util;
+
+
+import android.Manifest;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.IBinder;
+import android.support.v4.app.ActivityCompat;
+import android.telecom.TelecomManager;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+import android.view.KeyEvent;
+
+import com.android.internal.telephony.ITelephony;
+import com.android.internal.telephony.ITelephony.Stub;
+
+import java.lang.reflect.Method;
+
+//import cn.kaer.callmodule.factory.CallTypeFactory;
+//import cn.kaer.callmodule.properties.CallTypeProperties;
+
+public class PhoneCallUtil {
+    private static final String TAG = "PhoneUtil";
+
+    /**
+     * 挂断电话
+     *
+     * @param context
+     * @return
+     */
+    public static boolean endCall(Context context) {
+        boolean callSuccess = false;
+        try {
+            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) {
+                // >=Android 9,需打开 Manifest.permission.ANSWER_PHONE_CALLS 权限
+                TelecomManager telecomManager = (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
+                if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ANSWER_PHONE_CALLS) != PackageManager.PERMISSION_GRANTED) {
+                    // TODO: Consider calling
+                    //    ActivityCompat#requestPermissions
+                    // here to request the missing permissions, and then overriding
+                    //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
+                    //                                          int[] grantResults)
+                    // to handle the case where the user grants the permission. See the documentation
+                    // for ActivityCompat#requestPermissions for more details.
+                    return false;
+                }
+                telecomManager.endCall();
+                callSuccess = true;
+                Log.d(TAG, "telecomManager.endCall() finish");
+            } else {
+                // 1.获取TelephonyManager
+                // 2.获取TelephonyManager.class
+                // 3.反射调用TelephonyManager的 getITelephony方法获取ITelephony
+                // 4.挂断电话ITelephony.endCall
+                TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+                Class c = Class.forName(tm.getClass().getName());
+                Method m = c.getDeclaredMethod("getITelephony");
+                m.setAccessible(true);
+                ITelephony telephonyService = (ITelephony) m.invoke(tm);
+                if (telephonyService != null) {
+                    callSuccess = telephonyService.endCall();
+                    Log.d(TAG, " telephonyService.endCall finish");
+                }
+            }
+        } catch (Exception e) {
+            Log.d(TAG, "Exception   error: " + e.getMessage());
+            callSuccess = disconnectCall();
+            e.printStackTrace();
+        }
+        return callSuccess;
+    }
+
+    public static void endCallByKaer(Context context) {
+        //卡尔话机挂断电话
+        //CallTypeFactory.create().createCall(CallTypeProperties.WIRELESS).rejectComingCall();
+
+        Intent endCallIntent = new Intent();
+        endCallIntent.setAction("kaer.intent.action.END_WIRELESS_CALL");
+        endCallIntent.putExtra("isSecondCall", true);
+        context.sendBroadcast(endCallIntent);
+    }
+
+    public static synchronized void endCall4G() {
+        try {
+            Class<?> clazz = Class.forName("android.os.ServiceManager");
+            Method method = clazz.getMethod("getService", String.class);
+            IBinder ibinder = (IBinder)method.invoke((Object)null, "phone");
+            ITelephony iTelephony = Stub.asInterface(ibinder);
+            iTelephony.endCall();
+        } catch (Exception var4) {
+            var4.printStackTrace();
+        }
+
+    }
+
+    // 删除通话记录
+    public static void deleteCallLog(Context context, final String incomingNumber) {
+        // 1.获取内容解析者
+        final ContentResolver resolver = context.getContentResolver();
+        // 2.获取内容提供者地址 call_log calls表的地址:calls
+        // 3.获取执行操作路径
+        final Uri uri = Uri.parse("content://call_log/calls");
+        // 4.删除操作
+        // 通过内容观察者观察内容提供者内容,如果变化,就去执行删除操作
+        // notifyForDescendents : 匹配规则,true : 精确匹配 false:模糊匹配
+        resolver.registerContentObserver(uri, false, new ContentObserver(new Handler()) {
+            // 内容提供者内容变化的时候调用
+            @Override
+            public void onChange(boolean selfChange) {
+                super.onChange(selfChange);
+                try {
+                    // 删除通话记录
+                    resolver.delete(uri, "number=?", new String[]{incomingNumber});
+                    // 注销内容观察者
+                    resolver.unregisterContentObserver(this);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        });
+    }
+
+    private static boolean disconnectCall() {
+        try {
+            Log.d(TAG, "input keyevent " + KeyEvent.KEYCODE_ENDCALL);
+            Runtime.getRuntime().exec("input keyevent " + KeyEvent.KEYCODE_ENDCALL); //KEYCODE_HEADSETHOOK
+        } catch (Exception exc) {
+            Log.d(TAG, "exc.printStackTrace");
+            exc.printStackTrace();
+            return false;
+        }
+        return true;
+    }
+}

+ 1 - 1
android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/util/XCrashUtils.java

@@ -7,10 +7,10 @@ import android.content.Context;
 import android.content.Intent;
 import android.content.Intent;
 import android.util.Log;
 import android.util.Log;
 
 
-import com.wdkl.ncs.android.component.nursehome.BuildConfig;
 import com.wdkl.ncs.android.component.nursehome.activity.RegisterActivity;
 import com.wdkl.ncs.android.component.nursehome.activity.RegisterActivity;
 import com.wdkl.ncs.android.component.nursehome.helper.AppUpdateHelper;
 import com.wdkl.ncs.android.component.nursehome.helper.AppUpdateHelper;
 import com.wdkl.ncs.android.component.nursehome.helper.HttpHelper;
 import com.wdkl.ncs.android.component.nursehome.helper.HttpHelper;
+import com.wdkl.ncs.android.middleware.BuildConfig;
 import com.wdkl.ncs.android.middleware.api.UrlManager;
 import com.wdkl.ncs.android.middleware.api.UrlManager;
 
 
 import org.json.JSONObject;
 import org.json.JSONObject;

+ 2 - 2
android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/window/IncidentWindow.kt

@@ -92,7 +92,7 @@ class IncidentWindow(var activity: Activity) {
             delegateAdapter = DelegateAdapter(virtualLayoutManager)
             delegateAdapter = DelegateAdapter(virtualLayoutManager)
             delegateAdapter.addAdapter(adapter)
             delegateAdapter.addAdapter(adapter)
 
 
-            val windowIncidentBinding: WindowIncidentBinding = DataBindingUtil.bind(view)
+            val windowIncidentBinding: WindowIncidentBinding = DataBindingUtil.bind(view!!)!!
 
 
             windowIncidentBinding.rvEventList.layoutManager = virtualLayoutManager
             windowIncidentBinding.rvEventList.layoutManager = virtualLayoutManager
             windowIncidentBinding.rvEventList.adapter = delegateAdapter
             windowIncidentBinding.rvEventList.adapter = delegateAdapter
@@ -275,7 +275,7 @@ class IncidentWindow(var activity: Activity) {
         }
         }
 
 
         override fun onCreateViewHolder(
         override fun onCreateViewHolder(
-            p0: ViewGroup?,
+            p0: ViewGroup,
             p1: Int
             p1: Int
         ): BaseRecyclerViewHolder<AdapterEventListItemBinding> {
         ): BaseRecyclerViewHolder<AdapterEventListItemBinding> {
             return BaseRecyclerViewHolder.build(p0, R.layout.adapter_event_list_item)
             return BaseRecyclerViewHolder.build(p0, R.layout.adapter_event_list_item)

+ 0 - 81
android_host/src/main/h10_z3128_ke_2h/java/com/wdkl/ncs/android/component/nursehome/window/VoiceCall.kt

@@ -1,81 +0,0 @@
-package com.wdkl.ncs.android.component.nursehome.window
-
-import android.content.Context
-import android.R.attr.gravity
-import android.databinding.DataBindingUtil
-import android.graphics.PixelFormat
-import android.view.Gravity
-import android.view.WindowManager
-import android.view.LayoutInflater
-import android.view.View
-import android.widget.TextView
-import com.umeng.socialize.utils.DeviceConfig.context
-import com.wdkl.ncs.android.component.nursehome.R
-import com.wdkl.ncs.android.component.nursehome.databinding.WindowMakeAVoiceCallBinding
-import com.wdkl.ncs.android.lib.utils.showMessage
-
-
-class VoiceCall(var contexts: Context) {
-
-    var mWindowManager: WindowManager? = null
-    var view: View? = null
-
-    //创建悬浮按钮
-    fun createFloatView() {
-//    var mWindowManager = (WindowManager)getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
-        val wmParams = WindowManager.LayoutParams()
-        //获取的是WindowManagerImpl.CompatModeWrapper
-        mWindowManager = contexts.getSystemService(Context.WINDOW_SERVICE) as WindowManager
-        //设置window type
-        wmParams.type = WindowManager.LayoutParams.TYPE_PHONE
-        //设置图片格式,效果为背景透明
-//        wmParams.format = PixelFormat.RGBA_8888
-        //设置浮动窗口不可聚焦(实现操作除浮动窗口外的其他可见窗口的操作)
-        wmParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
-        //调整悬浮窗显示的停靠位置为左侧置顶
-//        wmParams.gravity = Gravity.RIGHT or Gravity.TOP
-        wmParams.gravity =Gravity.CENTER_HORIZONTAL;
-        // 以屏幕左上角为原点,设置x、y初始值,相对于gravity
-        wmParams.x = 0
-        wmParams.y = 0
-        //设置悬浮窗口长宽数据
-        wmParams.width = WindowManager.LayoutParams.WRAP_CONTENT
-        wmParams.height = WindowManager.LayoutParams.WRAP_CONTENT
-
-        //获取浮动窗口视图所在布局
-        view = LayoutInflater.from(contexts).inflate(R.layout.window_make_a_voice_call, null)
-        //添加mFloatLayout
-        mWindowManager!!.addView(view, wmParams)
-
-        lateinit var windowMakeAVoiceCallBinding:WindowMakeAVoiceCallBinding
-        windowMakeAVoiceCallBinding = DataBindingUtil.bind(view)
-
-//        windowMakeAVoiceCallBinding.baoMotherHeadImagev.
-        windowMakeAVoiceCallBinding.baoMotherNameTv.text = "张翠花"
-        windowMakeAVoiceCallBinding.baoMotherAgeTv.text = "23岁"
-//        windowMakeAVoiceCallBinding.theVoiceAnsweredImagev.setOnClickListener{
-//            showMessage("点击了接听")
-//
-//        }
-        windowMakeAVoiceCallBinding.voiceHangUpImagev.setOnClickListener {
-            showMessage("点击了挂断")
-            release()
-
-
-        }
-
-
-    }
-
-    /**
-     * 删除窗口
-     */
-    fun release() {
-        if (view != null) {
-            //移除悬浮窗口
-            mWindowManager?.removeView(view)
-        }
-    }
-
-
-}

+ 7 - 0
common/build.gradle

@@ -29,6 +29,13 @@ android {
 
 
     sourceSets {
     sourceSets {
         main.java.srcDirs += 'src/main/code'
         main.java.srcDirs += 'src/main/code'
+        main.java.srcDirs += 'src/main/aidl'
+
+        /*main {
+            java.srcDirs = ['src/main/code', 'src/main/aidl']
+            resources.srcDirs = ['src/main/code', 'src/main/aidl']
+            aidl.srcDirs = ['src/main/aidl']
+        }*/
     }
     }
 }
 }
 
 

+ 7 - 0
common/src/main/aidl/com/android/internal/telephony/ITelephony.aidl

@@ -0,0 +1,7 @@
+package com.android.internal.telephony;
+
+interface ITelephony {
+    boolean endCall();
+    void answerRingingCall();
+    void silenceRinger();
+}

+ 1 - 1
middleware/src/main/code/com/wdkl/ncs/android/middleware/api/ApiManager.kt

@@ -26,7 +26,7 @@ object ApiManager {
          * @Type  UrlManager
          * @Type  UrlManager
          * @Note  服务器URL控制器
          * @Note  服务器URL控制器
          */
          */
-        private val urlManager = UrlManager.build()
+        val urlManager = UrlManager.build()
 
 
         /** 全局分页条数 */
         /** 全局分页条数 */
         val PAGE_SIZE = 10
         val PAGE_SIZE = 10

+ 3 - 0
middleware/src/main/code/com/wdkl/ncs/android/middleware/api/NurseHomeApi.kt

@@ -22,4 +22,7 @@ interface NurseHomeApi{
     //获取LED点阵屏列表
     //获取LED点阵屏列表
     @GET("/deviceNurse/getLedScreenByNurseDeviceId/{deviceId}/{partId}")
     @GET("/deviceNurse/getLedScreenByNurseDeviceId/{deviceId}/{partId}")
     fun getLedInfo(@Path("deviceId") deviceId:Int, @Path("partId") partId:Int): Observable<ResponseBody>
     fun getLedInfo(@Path("deviceId") deviceId:Int, @Path("partId") partId:Int): Observable<ResponseBody>
+
+    @GET("/deviceNurse/getPhoneNumberWhiteList/{deviceId}")
+    fun getPhoneWhiteList(@Path("deviceId") deviceId:Int): Observable<ResponseBody>
 }
 }

+ 24 - 0
middleware/src/main/code/com/wdkl/ncs/android/middleware/common/Constants.kt

@@ -3,6 +3,7 @@ package com.wdkl.ncs.android.middleware.common
 import android.os.Environment
 import android.os.Environment
 import com.wdkl.ncs.android.middleware.entity.CallingItem
 import com.wdkl.ncs.android.middleware.entity.CallingItem
 import com.wdkl.ncs.android.middleware.model.vo.InteractionVO
 import com.wdkl.ncs.android.middleware.model.vo.InteractionVO
+import com.wdkl.ncs.android.middleware.tcp.enums.CommunicationEnum
 import com.wdkl.ncs.android.middleware.tcp.enums.DeviceTypeEnum
 import com.wdkl.ncs.android.middleware.tcp.enums.DeviceTypeEnum
 import java.util.ArrayList
 import java.util.ArrayList
 
 
@@ -142,6 +143,8 @@ class Constants {
         //是否有未接到的呼叫
         //是否有未接到的呼叫
         var newMissedCall = false
         var newMissedCall = false
 
 
+        var PHONE_NUMBER: String? = ""
+
         /**
         /**
          * TCP消息
          * TCP消息
          */
          */
@@ -209,6 +212,27 @@ class Constants {
         //巡房
         //巡房
         const val EVENT_ROUND_HOUSE = 0x28
         const val EVENT_ROUND_HOUSE = 0x28
 
 
+        const val EVENT_PHONE_DATA = 0x29
+
+        const val EVENT_CALL_END = 0x30
+
+        //电话状态
+        const val PHONE_IDLE = 0
+        const val PHONE_INCOMING = 1
+        const val PHONE_CALLING = 2
+        const val PHONE_OUTGOING = 3
+        var phoneState = PHONE_IDLE
+
+        //通话方式: 默认网络
+        var phoneType = CommunicationEnum.NET_WORK.value()
+        var phoneDataVO: InteractionVO? = null
+        var phoneTid: String? = null
+
+        //电话号码白名单
+        var phoneWhiteList = ArrayList<String>()
+
+        const val uploadCalllog = false
+
         //手柄拿起
         //手柄拿起
         const val HOOK_OFF = "com.android.PhoneWinowManager.HOOK_OFF"
         const val HOOK_OFF = "com.android.PhoneWinowManager.HOOK_OFF"
         //手柄放下
         //手柄放下

+ 6 - 0
middleware/src/main/code/com/wdkl/ncs/android/middleware/logic/contract/nursehome/NurseHomeActivityContract.kt

@@ -41,6 +41,9 @@ interface NurseHomeActivityContract{
          */
          */
         fun showDeviceData(data: NurseDeviceInfoVO)
         fun showDeviceData(data: NurseDeviceInfoVO)
 
 
+        //手机号码白名单
+        fun setPhoneNumberWhiteList(phoneList: ArrayList<String>)
+
         fun onNoneNet()
         fun onNoneNet()
     }
     }
 
 
@@ -71,5 +74,8 @@ interface NurseHomeActivityContract{
         fun loadDeviceData(ethMac: String)
         fun loadDeviceData(ethMac: String)
 
 
         fun cancelTransfer(deviceId: Int)
         fun cancelTransfer(deviceId: Int)
+
+        //获取手机号码白名单
+        fun getPhoneNumberWhiteList(deviceId: Int)
     }
     }
 }
 }

+ 43 - 0
middleware/src/main/code/com/wdkl/ncs/android/middleware/logic/presenter/nursehome/NurseHomeActivityPresenter.kt

@@ -125,6 +125,36 @@ class NurseHomeActivityPresenter @Inject constructor() :RxPresenter<NurseHomeAct
 
 
     }
     }
 
 
+    private val observable3 = object : ConnectionObserver<Any>() {
+        override fun onStartWithConnection() {
+            providerView()
+        }
+
+        override fun onNextWithConnection(result: Any, connectionQuality: ConnectionQuality) {
+            providerView().complete()
+
+            when (result) {
+                is ArrayList<*> -> {
+                    providerView().setPhoneNumberWhiteList(result as ArrayList<String>)
+                }
+            }
+        }
+
+        override fun onErrorWithConnection(error: ExceptionHandle.ResponeThrowable, connectionQuality: ConnectionQuality) {
+            providerView().onError(error.customMessage)
+        }
+
+        override fun attachSubscribe(var1: Disposable) {
+            addDisposable(var1)
+        }
+
+        override fun onNoneNet() {
+            super.onNoneNet()
+            providerView().onNoneNet()
+        }
+
+    }
+
     override fun getAppVersion(partId: Int, deviceType: Int) {
     override fun getAppVersion(partId: Int, deviceType: Int) {
         nurseHomeApi.getAppVersion(partId, deviceType)
         nurseHomeApi.getAppVersion(partId, deviceType)
                 .map {
                 .map {
@@ -200,4 +230,17 @@ class NurseHomeActivityPresenter @Inject constructor() :RxPresenter<NurseHomeAct
             .compose(ThreadFromUtils.defaultSchedulers())
             .compose(ThreadFromUtils.defaultSchedulers())
             .subscribe(observable2)
             .subscribe(observable2)
     }
     }
+
+    override fun getPhoneNumberWhiteList(deviceId: Int) {
+        nurseHomeApi.getPhoneWhiteList(deviceId)
+            .map {
+                val data = it.getJsonString()
+                val gson = GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create()
+                val phoneList: List<String> = gson.fromJson(data, object : TypeToken<List<String>>() {}.type)
+
+                return@map phoneList
+            }
+            .compose(ThreadFromUtils.defaultSchedulers())
+            .subscribe(observable3)
+    }
 }
 }

+ 102 - 0
middleware/src/main/code/com/wdkl/ncs/android/middleware/model/vo/PhoneInteractionVO.java

@@ -0,0 +1,102 @@
+package com.wdkl.ncs.android.middleware.model.vo;
+
+/**
+ * @author
+ * @title: Vothin
+ * @projectName nc
+ * @date 2022/9/2218:25
+ */
+public class PhoneInteractionVO {
+
+    // 发起方的设备id
+    private Integer fromId;
+    // 接收方的设备id
+    private Integer toId;
+    // 发起通话的人
+    private String fromDevicePhoneNumber;
+    // 接收通话的人
+    private String toDevicePhoneNumber;
+    // 发起通话的时间
+    private Long actionStart;
+    // 接收通话的时间
+    private Long actionAccept;
+    // 结束通话的时间
+    private Long actionEnd;
+    // 通话时长
+    private Integer actionCallTime;
+    // 通话类型
+    private Integer actionStatus;
+
+    public Integer getFromId() {
+        return fromId;
+    }
+
+    public void setFromId(Integer fromId) {
+        this.fromId = fromId;
+    }
+
+    public Integer getToId() {
+        return toId;
+    }
+
+    public void setToId(Integer toId) {
+        this.toId = toId;
+    }
+
+    public String getFromDevicePhoneNumber() {
+        return fromDevicePhoneNumber;
+    }
+
+    public void setFromDevicePhoneNumber(String fromDevicePhoneNumber) {
+        this.fromDevicePhoneNumber = fromDevicePhoneNumber;
+    }
+
+    public String getToDevicePhoneNumber() {
+        return toDevicePhoneNumber;
+    }
+
+    public void setToDevicePhoneNumber(String toDevicePhoneNumber) {
+        this.toDevicePhoneNumber = toDevicePhoneNumber;
+    }
+
+    public Long getActionStart() {
+        return actionStart;
+    }
+
+    public void setActionStart(Long actionStart) {
+        this.actionStart = actionStart;
+    }
+
+    public Long getActionAccept() {
+        return actionAccept;
+    }
+
+    public void setActionAccept(Long actionAccept) {
+        this.actionAccept = actionAccept;
+    }
+
+    public Long getActionEnd() {
+        return actionEnd;
+    }
+
+    public void setActionEnd(Long actionEnd) {
+        this.actionEnd = actionEnd;
+    }
+
+    public Integer getActionCallTime() {
+        return actionCallTime;
+    }
+
+    public void setActionCallTime(Integer actionCallTime) {
+        this.actionCallTime = actionCallTime;
+    }
+
+
+    public Integer getActionStatus() {
+        return actionStatus;
+    }
+
+    public void setActionStatus(Integer actionStatus) {
+        this.actionStatus = actionStatus;
+    }
+}

+ 6 - 0
middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/channel/DeviceChannel.java

@@ -153,6 +153,12 @@ public class DeviceChannel {
                 }
                 }
                 EventBus.getDefault().post(new MessageEvent(tcpModel, Constants.EVENT_TCP_MSG));
                 EventBus.getDefault().post(new MessageEvent(tcpModel, Constants.EVENT_TCP_MSG));
                 break;
                 break;
+            case PHONE:
+                //普通电话
+                if (tcpModel.getAction() == TcpAction.PhoneAction.DATA) {
+                    EventBus.getDefault().post(new MessageEvent(tcpModel, Constants.EVENT_PHONE_DATA));
+                }
+                break;
             case DATA:
             case DATA:
             case DEVICE:
             case DEVICE:
             case TIME:
             case TIME:

+ 6 - 0
middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/channel/DeviceUtil.java

@@ -1,12 +1,14 @@
 package com.wdkl.ncs.android.middleware.tcp.channel;
 package com.wdkl.ncs.android.middleware.tcp.channel;
 
 
 import android.os.Build;
 import android.os.Build;
+import android.text.TextUtils;
 
 
 import com.wdkl.ncs.android.middleware.BuildConfig;
 import com.wdkl.ncs.android.middleware.BuildConfig;
 import com.wdkl.ncs.android.middleware.tcp.dto.DeviceConnectDTO;
 import com.wdkl.ncs.android.middleware.tcp.dto.DeviceConnectDTO;
 import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel;
 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.TcpAction;
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpType;
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpType;
+import com.wdkl.ncs.android.middleware.utils.ContactHelper;
 
 
 public class DeviceUtil {
 public class DeviceUtil {
     public static TcpModel deviceConnect(String mac){
     public static TcpModel deviceConnect(String mac){
@@ -18,6 +20,10 @@ public class DeviceUtil {
         connectDTO.setModel(Build.MODEL);
         connectDTO.setModel(Build.MODEL);
         connectDTO.setCode(Build.SERIAL);
         connectDTO.setCode(Build.SERIAL);
         tcpModel.setType(TcpType.DEVICE);
         tcpModel.setType(TcpType.DEVICE);
+        String number = ContactHelper.getPhoneNumber();
+        if (!TextUtils.isEmpty(number)) {
+            connectDTO.setPhoneNumber(number);
+        }
         tcpModel.setAction(TcpAction.DeviceAction.CONNECT);
         tcpModel.setAction(TcpAction.DeviceAction.CONNECT);
         tcpModel.setData(connectDTO);
         tcpModel.setData(connectDTO);
         return tcpModel;
         return tcpModel;

+ 57 - 0
middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/channel/PhoneUtil.java

@@ -0,0 +1,57 @@
+package com.wdkl.ncs.android.middleware.tcp.channel;
+
+import com.wdkl.ncs.android.middleware.model.vo.InteractionVO;
+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;
+
+public class PhoneUtil {
+
+    //电话呼出
+    public static TcpModel phoneCall(Integer fromId, Integer toId){
+        TcpModel tcpModel = new TcpModel(null);
+        tcpModel.setType(TcpType.PHONE);
+        tcpModel.setAction(TcpAction.PhoneAction.CALL);
+        tcpModel.setFromId(fromId);
+        tcpModel.setToId(toId);
+        return tcpModel;
+    }
+
+    //电话取消
+    public static TcpModel phoneCancel(Integer fromId, String tid){
+        TcpModel tcpModel = new TcpModel(tid);
+        tcpModel.setType(TcpType.PHONE);
+        tcpModel.setAction(TcpAction.PhoneAction.CANCEL);
+        tcpModel.setFromId(fromId);
+        return tcpModel;
+    }
+
+    //电话接听
+    public static TcpModel phoneAccept(Integer fromId, String tid, InteractionVO interactionVO){
+        TcpModel tcpModel = new TcpModel(tid);
+        tcpModel.setType(TcpType.PHONE);
+        tcpModel.setAction(TcpAction.PhoneAction.ACCEPT);
+        tcpModel.setFromId(fromId);
+        tcpModel.setData(interactionVO);
+        return tcpModel;
+    }
+
+    //电话拒接
+    public static TcpModel phoneReject(Integer fromId, String tid){
+        TcpModel tcpModel = new TcpModel(tid);
+        tcpModel.setType(TcpType.PHONE);
+        tcpModel.setAction(TcpAction.PhoneAction.REJECT);
+        tcpModel.setFromId(fromId);
+        return tcpModel;
+    }
+
+    //电话挂断
+    public static TcpModel phoneHandoff(Integer fromId, String tid, InteractionVO interactionVO){
+        TcpModel tcpModel = new TcpModel(tid);
+        tcpModel.setType(TcpType.PHONE);
+        tcpModel.setAction(TcpAction.PhoneAction.HANDOFF);
+        tcpModel.setFromId(fromId);
+        tcpModel.setData(interactionVO);
+        return tcpModel;
+    }
+}

+ 10 - 0
middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/dto/DeviceConnectDTO.java

@@ -31,6 +31,8 @@ public class DeviceConnectDTO implements Serializable {
      */
      */
     private String code;
     private String code;
 
 
+    private String phoneNumber;
+
     public String getIdentification() {
     public String getIdentification() {
         return identification;
         return identification;
     }
     }
@@ -70,4 +72,12 @@ public class DeviceConnectDTO implements Serializable {
     public void setCode(String code) {
     public void setCode(String code) {
         this.code = code;
         this.code = code;
     }
     }
+
+    public String getPhoneNumber() {
+        return phoneNumber;
+    }
+
+    public void setPhoneNumber(String phoneNumber) {
+        this.phoneNumber = phoneNumber;
+    }
 }
 }

+ 63 - 0
middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/enums/CommunicationEnum.java

@@ -0,0 +1,63 @@
+package com.wdkl.ncs.android.middleware.tcp.enums;
+
+/**
+ * @author wuyunfeng
+ * 2021-12-19 14:48
+ * 通话方式枚举
+ */
+public enum CommunicationEnum {
+
+    NET_WORK(1, "网络电话"),
+    MOBILE_PHONE(2, "移动电话卡"),
+    TELEPHONE(3, "固定电话");
+
+    private int value;
+    private String typeName;
+
+
+    CommunicationEnum(int value, String typeName) {
+        this.value = value;
+        this.typeName = typeName;
+    }
+
+    public int value() {
+        return this.value;
+    }
+
+    public String typeName() {
+        return this.typeName;
+    }
+
+    /**
+     * 通过typeName 转换成枚举
+     *
+     * @param typeName
+     * @return
+     */
+    public static CommunicationEnum parse(String typeName) {
+        CommunicationEnum[] values = CommunicationEnum.values();
+        for (CommunicationEnum value : values) {
+            if (value.typeName().equals(typeName)) {
+                return value;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 通过value值转换成枚举
+     *
+     * @param value
+     * @return
+     */
+    public static CommunicationEnum parse(int value) {
+        CommunicationEnum[] values = CommunicationEnum.values();
+        for (CommunicationEnum communicationEnum : values) {
+            if (communicationEnum.value() == value) {
+                return communicationEnum;
+            }
+        }
+        return null;
+    }
+
+}

+ 348 - 0
middleware/src/main/code/com/wdkl/ncs/android/middleware/utils/ContactHelper.java

@@ -0,0 +1,348 @@
+package com.wdkl.ncs.android.middleware.utils;
+
+import android.annotation.SuppressLint;
+import android.content.ContentProviderOperation;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.CallLog;
+import android.provider.ContactsContract;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+
+import com.wdkl.ncs.android.lib.base.BaseApplication;
+import com.wdkl.ncs.android.middleware.common.Constants;
+import com.wdkl.ncs.android.middleware.model.vo.PhoneInteractionVO;
+
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+
+public class ContactHelper {
+    private static final String TAG = "ContactHelper";
+
+    //获取通话记录
+    public static void getCallLogs(Context context) {
+        Uri callUri = CallLog.Calls.CONTENT_URI;
+        Cursor cursor = null;
+        try {
+            cursor = context.getContentResolver().query(callUri, // 查询通话记录的URI
+                    //columns,  //数据库列选择 不选则获取所有列
+                    null,
+                    null,
+                    null,
+                    CallLog.Calls.DEFAULT_SORT_ORDER  //按照时间逆序排列,最近打的最先显示
+            );
+            Log.i(TAG, "cursor count:" + cursor.getCount());
+            int i = 0;
+            while (cursor.moveToNext() && i < 20) {
+                i++;
+                String name = cursor.getString(cursor.getColumnIndex(CallLog.Calls.CACHED_NAME));  //姓名
+                String number = cursor.getString(cursor.getColumnIndex(CallLog.Calls.NUMBER));  //号码
+                long dateLong = cursor.getLong(cursor.getColumnIndex(CallLog.Calls.DATE)); //获取通话日期
+                String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(dateLong));
+                //String time = new SimpleDateFormat("HH:mm").format(new Date(dateLong));
+                int duration = cursor.getInt(cursor.getColumnIndex(CallLog.Calls.DURATION));//获取通话时长,值为多少秒
+                int type = cursor.getInt(cursor.getColumnIndex(CallLog.Calls.TYPE)); //获取通话类型:1.呼入 2.呼出 3.未接 4.voicemail 5.拒接
+                //String dayCurrent = new SimpleDateFormat("dd").format(new Date());
+                //String dayRecord = new SimpleDateFormat("dd").format(new Date(dateLong));
+                //String phone_account_address = cursor.getString(cursor.getColumnIndex("phone_account_address"));//本机号码可能获取不到(华为、oppo获取不到)
+                //String phone_account_id = cursor.getString(cursor.getColumnIndex(CallLog.Calls.PHONE_ACCOUNT_ID));//本机sim卡id,即ICCID
+                //String phone_account_hidden = cursor.getString(cursor.getColumnIndex("phone_account_hidden"));
+
+                Log.i(TAG, "Call log: " + "\n"
+                        + "name: " + name + "\n"
+                        + "date: " + date + "\n"
+                        + "phone number: " + number + "\n"
+                        + "duration: " + duration + "\n"
+                        + "type: " + type
+                );
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+    }
+
+
+    public static PhoneInteractionVO getLatestCallLog(final Context context) {
+        Uri callUri = CallLog.Calls.CONTENT_URI;
+        String[] columns = {CallLog.Calls.CACHED_NAME,
+                CallLog.Calls.NUMBER,
+                CallLog.Calls.DATE,
+                CallLog.Calls.DURATION,
+                CallLog.Calls.TYPE};
+        Cursor cursor = null;
+        PhoneInteractionVO interactionVO = null;
+
+        try {
+            cursor = context.getContentResolver().query(
+                    callUri, // 查询通话记录的URI
+                    columns,  //数据库列选择 不选则获取所有列
+                    null,
+                    null,
+                    CallLog.Calls.DEFAULT_SORT_ORDER  //按照时间逆序排列,最近打的最先显示
+            );
+            Log.i(TAG, "cursor count:" + cursor.getCount());
+            if (cursor.moveToNext()) {
+                String name = cursor.getString(cursor.getColumnIndex(CallLog.Calls.CACHED_NAME));  //姓名
+                String number = cursor.getString(cursor.getColumnIndex(CallLog.Calls.NUMBER));  //号码
+                long dateLong = cursor.getLong(cursor.getColumnIndex(CallLog.Calls.DATE)); //获取通话日期
+                String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(dateLong));
+                int duration = cursor.getInt(cursor.getColumnIndex(CallLog.Calls.DURATION));//获取通话时长,值为多少秒
+                int type = cursor.getInt(cursor.getColumnIndex(CallLog.Calls.TYPE)); //获取通话类型:1.来电 2.去电 3.未接的来电 4.voicemail 5.拒接的来电
+
+                interactionVO = new PhoneInteractionVO();
+                if (type == CallLog.Calls.INCOMING_TYPE || type == CallLog.Calls.MISSED_TYPE || type == CallLog.Calls.REJECTED_TYPE) {
+                    //接通的来电,未接的来电,拒接的来电
+                    interactionVO.setFromDevicePhoneNumber(number);
+                    interactionVO.setToDevicePhoneNumber(Constants.Companion.getPHONE_NUMBER());
+                    interactionVO.setToId(Constants.Companion.getIds());
+                } else if (type == CallLog.Calls.OUTGOING_TYPE) {
+                    //去电:包括接通的,自己取消的,对方拒接的
+                    interactionVO.setFromDevicePhoneNumber(Constants.Companion.getPHONE_NUMBER());
+                    interactionVO.setToDevicePhoneNumber(number);
+                    interactionVO.setFromId(Constants.Companion.getIds());
+                }
+                interactionVO.setActionStart(dateLong);
+                interactionVO.setActionCallTime(duration);
+                interactionVO.setActionStatus(type);
+                //interactionVO.setActionAccept();
+                //结束时间需要减去延时的时间
+                interactionVO.setActionEnd(System.currentTimeMillis()-1200);
+
+                Log.i(TAG, "Call log: " + "\n"
+                        + "name: " + name + "\n"
+                        + "date: " + date + "\n"
+                        + "phone number: " + number + "\n"
+                        + "duration: " + duration + "\n"
+                        + "type: " + type
+                );
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+
+        return interactionVO;
+    }
+
+    /**
+     * 插入手机号
+     *
+     * @param context
+     * @param name
+     * @param phoneNumber
+     */
+    public static void insertContact(Context context, String name, String phoneNumber) {
+
+        Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
+        ContentResolver resolver = context.getContentResolver();
+
+        ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();
+        // 操作1.添加Google账号,这里值为null,表示不添加
+        ContentProviderOperation operation = ContentProviderOperation.newInsert(uri)
+                .withValue("account_name", null)// account_name:Google账号
+                .build();
+        // 操作2.添加data表中name字段
+        uri = Uri.parse("content://com.android.contacts/data");
+        ContentProviderOperation operation2 = ContentProviderOperation.newInsert(uri)
+                // 第二个参数int previousResult:表示上一个操作的位于operations的第0个索引,
+                // 所以能够将上一个操作返回的raw_contact_id作为该方法的参数
+                .withValueBackReference("raw_contact_id", 0)
+                .withValue("mimetype", "vnd.android.cursor.item/name")
+                .withValue("data2", name)
+                .build();
+
+        // 操作3.添加data表中phone字段
+        uri = Uri.parse("content://com.android.contacts/data");
+        ContentProviderOperation operation3 = ContentProviderOperation.newInsert(uri)
+                .withValueBackReference("raw_contact_id", 0)
+                .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
+                //.withValue("mimetype", "vnd.android.cursor.item/phone_v2")
+                .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE)
+//                    .withValue("data2", "2")
+                .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phoneNumber)
+                .build();
+
+        operations.add(operation);
+        operations.add(operation2);
+        operations.add(operation3);
+        try {
+            resolver.applyBatch("com.android.contacts", operations);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+
+    /**
+     * 判断某个手机号是否存在
+     */
+    public static Integer isPhoneNumbExist(Context context, String phoneNum) {
+        //uri=  content://com.android.contacts/data/phones/filter/#
+        Cursor cursor = null;
+        try {
+            Uri uri = Uri.parse("content://com.android.contacts/data/phones/filter/" + phoneNum);
+            ContentResolver resolver = context.getContentResolver();
+            cursor = resolver.query(uri, new String[]{ContactsContract.Data.CONTACT_ID},
+                    null, null, null); //从raw_contact表中返回display_name
+            if (cursor != null && cursor.moveToFirst()) {
+                int contact_id = cursor.getInt(0);
+                Log.i("联系人ID", contact_id + "");
+                cursor.close();
+                return contact_id;
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+        return -1;
+    }
+
+
+    /**
+     * 根据姓名查找Contact_id
+     *
+     * @param context
+     * @param name
+     * @return
+     */
+    public static Integer queryRawContactIdByName(Context context, String name) {
+        //根据姓名求id
+        Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
+        ContentResolver resolver = context.getContentResolver();
+        Cursor cursor = resolver.query(uri, new String[]{ContactsContract.Data._ID}, "display_name=?", new String[]{name}, null);
+        if (cursor != null && cursor.moveToFirst()) {
+            int id = cursor.getInt(0);
+            cursor.close();
+            return id;
+        }
+        return null;
+    }
+
+    /**
+     * 更新通讯录,需要传入Contact_id
+     *
+     * @param context
+     * @param contact_id
+     * @param phoneNum
+     */
+    public static void updateContact(Context context, Integer contact_id, String phoneNum) {
+        try {
+            Uri uri = Uri.parse("content://com.android.contacts/data");//对data表的所有数据操作
+//
+////        ContentValues values = new ContentValues();
+////        values.put("data", phoneNum);
+////        resolver.update(uri, values, "mimetype=? and raw_contact_id=?", new String[]{"vnd.android.cursor.item/phone_v2",contact_id+""});
+//        Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
+//        ContentValues values = new ContentValues();
+//        values.put("data1", phoneNum);
+//        resolver.update(uri, values, "mimetype=? and raw_contact_id=?", new String[]{"vnd.android.cursor.item/phone_v2", contact_id + ""});
+
+            ContentResolver resolver = context.getContentResolver();
+            ContentValues values = new ContentValues();
+            values.put(ContactsContract.CommonDataKinds.Phone.NUMBER, phoneNum);
+            values.put(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE);
+
+            String Where = ContactsContract.Data.RAW_CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?";
+            String[] WhereParams = new String[]{contact_id + "", ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE,};
+
+            resolver.update(uri, values, Where, WhereParams);
+
+
+//        try {
+//            Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
+//            ContentResolver resolver = context.getContentResolver();
+//            Cursor cursor = resolver.query(uri, new String[]{ ContactsContract.Data.DATA1, ContactsContract.Data.DATA2, ContactsContract.Data.DATA3}, "raw_contact_id=?", new String[]{contact_id + ""}, null);
+//            if (cursor.moveToFirst()) {
+//                int id = cursor.getInt(0);
+//                String data1 = cursor.getString(1);
+//                String data2 = cursor.getString(2);
+//                Log.i("通讯录", "updateContact: id=" + id + ",data1=" + data1 + ",data2=" + data2);
+//            }
+//            cursor.close();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public static void setContact(Context context, String name, String phoneNumber) {
+
+        Integer contact_id = queryRawContactIdByName(context, name);
+        Integer contact_id2 = isPhoneNumbExist(context, phoneNumber);
+        Log.i("ContactId", "setContact: " + contact_id2 + ", name: " + name + ", phone: " + phoneNumber);
+        if (contact_id != null && contact_id > 0) {
+            deleteContact(context,name);
+            if (!(contact_id2 != null && contact_id2 > 0 && contact_id.equals(contact_id2))) { //非 通讯录中原有号码和姓名匹配的情况
+                if (contact_id2 != null && contact_id2 > 0) { //号码已经存在了
+                    deleteContact(context, contact_id2); //删除号码
+                }
+//                updateContact(context, contact_id, phoneNumber); //更新通讯录
+            }//通讯录姓名和号码没有变化,不用操作
+            insertContact(context, name, phoneNumber);
+        } else { //这个名字不存在通讯录中
+            insertContact(context, name, phoneNumber);
+            if(contact_id2!=null&&contact_id2>0){ //电话号码确在通讯录中
+                deleteContact(context, contact_id2); //删除原来号码通讯录
+            }
+
+        }
+
+
+    }
+
+
+    /**
+     * 删除联系人
+     */
+    public static void deleteContact(Context context, String name) {
+
+        //根据姓名求id
+        Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
+        ContentResolver resolver = context.getContentResolver();
+        Cursor cursor = resolver.query(uri, new String[]{ContactsContract.Data._ID}, "display_name=?", new String[]{name}, null);
+        if (cursor == null)
+            return;
+
+        if (cursor.moveToFirst()) {
+            int id = cursor.getInt(0);
+            //根据id删除data中的相应数据
+            resolver.delete(uri, "display_name=?", new String[]{name});
+            uri = Uri.parse("content://com.android.contacts/data");
+            resolver.delete(uri, "raw_contact_id=?", new String[]{id + ""});
+        }
+        cursor.close();
+    }
+
+    /**
+     * 删除联系人
+     */
+    public static void deleteContact(Context context, Integer contact_id) {
+        //根据姓名求id
+        Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
+        ContentResolver resolver = context.getContentResolver();
+        //根据id删除data中的相应数据
+        resolver.delete(uri, "_id=?", new String[]{contact_id + ""});
+        uri = Uri.parse("content://com.android.contacts/data");
+        resolver.delete(uri, "raw_contact_id=?", new String[]{contact_id + ""});
+
+    }
+
+    public static String getPhoneNumber(){
+        TelephonyManager tm = (TelephonyManager) BaseApplication.appContext.getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE);
+        @SuppressLint("MissingPermission") String te1  = tm.getLine1Number();//获取本机号码
+        return te1;
+    }
+}