Przeglądaj źródła

西班牙客户需求:手柄呼叫时可以和对应门口机通话

weizhengliang 1 rok temu
rodzic
commit
ec800083f6
20 zmienionych plików z 660 dodań i 192 usunięć
  1. 4 0
      android_mobile/src/main/yd_w_xiaomi_2_chile/AndroidManifest.xml
  2. 294 0
      android_mobile/src/main/yd_w_xiaomi_2_chile/code/com/wdkl/ncs/android/component/home/activity/NewCallListActivity.kt
  3. 1 1
      android_mobile/src/main/yd_w_xiaomi_2_chile/code/com/wdkl/ncs/android/component/home/activity/WatchCallRecordsActivity.kt
  4. 23 0
      android_mobile/src/main/yd_w_xiaomi_2_chile/code/com/wdkl/ncs/android/component/home/activity/WatchUserSettingActivity.java
  5. 73 0
      android_mobile/src/main/yd_w_xiaomi_2_chile/code/com/wdkl/ncs/android/component/home/adapter/NewCallItemAdapter.kt
  6. 1 1
      android_mobile/src/main/yd_w_xiaomi_2_chile/code/com/wdkl/ncs/android/component/home/adapter/NewEventItemAdapter.kt
  7. 16 69
      android_mobile/src/main/yd_w_xiaomi_2_chile/code/com/wdkl/ncs/android/component/home/adapter/WatchCallRecordsItemAdapter.kt
  8. 63 46
      android_mobile/src/main/yd_w_xiaomi_2_chile/code/com/wdkl/ncs/android/component/home/service/WdKeepAliveService.kt
  9. 10 0
      android_mobile/src/main/yd_w_xiaomi_2_chile/code/com/wdkl/ncs/android/component/home/settingconfig/SettingConfig.java
  10. 35 60
      android_mobile/src/main/yd_w_xiaomi_2_chile/code/com/wdkl/ncs/android/component/home/ui/CallSingleActivity.java
  11. 6 6
      android_mobile/src/main/yd_w_xiaomi_2_chile/code/com/wdkl/ncs/android/component/home/ui/FragmentAudio.java
  12. 3 2
      android_mobile/src/main/yd_w_xiaomi_2_chile/code/com/wdkl/ncs/android/component/home/ui/SingleCallFragment.java
  13. 4 0
      android_mobile/src/main/yd_w_xiaomi_2_chile/code/com/wdkl/ncs/android/component/home/util/AsyncPlayer.java
  14. 20 1
      android_mobile/src/main/yd_w_xiaomi_2_chile/code/com/wdkl/ncs/android/component/home/util/RingPlayHelper.java
  15. 34 0
      android_mobile/src/main/yd_w_xiaomi_2_chile/res/layout/activity_call_list.xml
  16. 6 3
      android_mobile/src/main/yd_w_xiaomi_2_chile/res/layout/adapter_watch_call_records_item.xml
  17. 35 0
      android_mobile/src/main/yd_w_xiaomi_2_chile/res/layout/call_list_item.xml
  18. 30 1
      android_mobile/src/main/yd_w_xiaomi_2_chile/res/layout/user_setting_layout.xml
  19. 1 1
      build.gradle
  20. 1 1
      common/build.gradle

+ 4 - 0
android_mobile/src/main/yd_w_xiaomi_2_chile/AndroidManifest.xml

@@ -58,6 +58,10 @@
             android:showOnLockScreen="true"
             android:showWhenLocked="true"
             android:launchMode="singleTask"/>
+        <activity android:screenOrientation="portrait" android:name=".activity.NewCallListActivity"
+            android:showOnLockScreen="true"
+            android:showWhenLocked="true"
+            android:launchMode="singleTask"/>
         <activity android:name=".activity.VoiceMsgActivity" android:screenOrientation="portrait"/>
         <activity android:name=".activity.ChannelImActivity" android:screenOrientation="portrait"/>
         <activity android:name=".activity.ContactUpdateActivity" android:screenOrientation="portrait"/>

+ 294 - 0
android_mobile/src/main/yd_w_xiaomi_2_chile/code/com/wdkl/ncs/android/component/home/activity/NewCallListActivity.kt

@@ -0,0 +1,294 @@
+package com.wdkl.ncs.android.component.home.activity
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.content.Intent
+import android.os.Build
+import android.os.Bundle
+import android.os.VibrationEffect
+import android.os.Vibrator
+import android.util.Log
+import android.view.View
+import android.widget.TextView
+import androidx.recyclerview.widget.RecyclerView
+import com.alibaba.android.vlayout.DelegateAdapter
+import com.alibaba.android.vlayout.VirtualLayoutManager
+import com.alibaba.fastjson.JSON
+import com.enation.javashop.utils.base.tool.BaseToolActivity
+import com.google.gson.Gson
+import com.scwang.smartrefresh.layout.SmartRefreshLayout
+import com.wdkl.ncs.android.component.home.R
+import com.wdkl.ncs.android.component.home.adapter.NewCallItemAdapter
+import com.wdkl.ncs.android.component.home.service.WdKeepAliveService
+import com.wdkl.ncs.android.component.home.settingconfig.SettingConfig
+import com.wdkl.ncs.android.component.home.ui.CallSingleActivity
+import com.wdkl.ncs.android.component.home.util.RingPlayHelper
+import com.wdkl.ncs.android.component.home.util.SpeechUtil
+import com.wdkl.ncs.android.lib.base.BaseApplication
+import com.wdkl.ncs.android.lib.utils.AppTool
+import com.wdkl.ncs.android.lib.utils.showMessage
+import com.wdkl.ncs.android.lib.vo.MessageEvent
+import com.wdkl.ncs.android.middleware.common.Constants
+import com.wdkl.ncs.android.middleware.model.vo.InteractionVO
+import com.wdkl.ncs.android.middleware.tcp.TcpClient
+import com.wdkl.ncs.android.middleware.tcp.channel.DeviceChannel
+import com.wdkl.ncs.android.middleware.tcp.channel.VoiceUtil
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel
+import com.wdkl.ncs.android.middleware.tcp.enums.DeviceTypeEnum
+import org.greenrobot.eventbus.EventBus
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+
+class NewCallListActivity : BaseToolActivity(), NewCallItemAdapter.CallClickListener {
+    var TAG = NewCallListActivity::class.java.getSimpleName()
+
+    private val adapter = NewCallItemAdapter(ArrayList(),this)
+    private lateinit var virtualLayoutManager: VirtualLayoutManager
+    private lateinit var delegateAdapter: DelegateAdapter
+
+    private lateinit var recyclerView: RecyclerView
+    private lateinit var refreshView: SmartRefreshLayout
+    private lateinit var emptyView: TextView
+
+    lateinit var mVibrator: Vibrator
+
+    private var transSeconds = 15
+
+    private val screen_flags = (
+            View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
+                    or View.SYSTEM_UI_FLAG_FULLSCREEN
+                    or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+                    or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+                    or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+
+        setContentView(R.layout.activity_call_list)
+
+        if(!EventBus.getDefault().isRegistered(this)){
+            EventBus.getDefault().register(this)
+        }
+
+        mVibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
+
+        transSeconds = SettingConfig.getCountdownTime(activity)
+
+        recyclerView = findViewById(R.id.rv_call_list)
+        refreshView = findViewById(R.id.srl_call_list)
+        emptyView = findViewById(R.id.tv_empty_call)
+
+        /**初始化LayoutMannager*/
+        virtualLayoutManager = VirtualLayoutManager(this.activity)
+
+        /**初始化适配器*/
+        delegateAdapter = DelegateAdapter(virtualLayoutManager)
+        delegateAdapter.addAdapter(adapter)
+        recyclerView.layoutManager = virtualLayoutManager
+        recyclerView.adapter = delegateAdapter
+
+        //ring up
+        RingPlayHelper.playRingTone(BaseApplication.appContext, R.raw.ring_tone, true)
+
+        adapter.setCallClick(this)
+
+        if (Constants.supportCall) {
+            adapter.setOnItemClickListener { data, position ->
+                SpeechUtil.getInstance().stopSpeak()
+                RingPlayHelper.stopRingTone()
+                cancelVibrator()
+
+                val interactionVO = Gson().fromJson(data.data.toString(), InteractionVO::class.java)
+                var roomId: String
+                if (interactionVO.fromDeviceType == DeviceTypeEnum.SIMULATE_BED_DEVICE.value()) {
+                    //模拟分机呼叫,通话由手机端创建
+                    DeviceChannel.callId = interactionVO.fromDeviceId
+                    roomId = Constants.sipId!!
+                } else {
+                    if (interactionVO.fromDeviceId.equals(Constants.deviceId)) {
+                        DeviceChannel.callId = interactionVO.toDeviceId
+                        roomId = interactionVO.toSipId
+                    } else {
+                        DeviceChannel.callId = interactionVO.fromDeviceId
+                        roomId = interactionVO.fromSipId
+                    }
+                }
+                Log.i(TAG, "来电:" + JSON.toJSONString(data))
+
+                //启动 activity
+                var intent = Intent(activity, CallSingleActivity::class.java)
+                intent.putExtra(CallSingleActivity.EXTRA_ROOM_ID, roomId)
+                intent.putExtra(CallSingleActivity.EXTRA_MO, false)
+                intent.putExtra(CallSingleActivity.EXTRA_AUDIO_ONLY, true)
+                intent.putExtra(CallSingleActivity.EXTRA_TCPMODEL, data)
+                intent.putExtra(CallSingleActivity.EXTRA_RING, false)
+                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+                startActivity(intent)
+
+                //移除该条呼叫
+                removeCall(interactionVO)
+            }
+        } else {
+            adapter.setOnItemClickListener { data, position ->
+                SpeechUtil.getInstance().stopSpeak()
+                RingPlayHelper.stopRingTone()
+                val interactionVO = Gson().fromJson(data.data.toString(), InteractionVO::class.java)
+                val callTcp = VoiceUtil.voiceReject(data.tid, Constants.deviceId, interactionVO.fromDeviceId, interactionVO.id)
+                TcpClient.getInstance().sendMsg(callTcp.toJson())
+
+                //移除该条呼叫
+                removeCall(interactionVO)
+            }
+        }
+
+        refreshView.setOnRefreshListener {
+            AppTool.Time.delay(800) {
+                updateCallList()
+                refreshView.finishRefresh()
+            }
+        }
+
+        WdKeepAliveService.mNewCallListActive = true
+
+        handleVibrator()
+
+        //启动线程处理呼叫转移
+        if (SettingConfig.getCallTransfer(BaseApplication.appContext)) {
+            startLoopTransfer()
+        }
+    }
+
+    private fun handleVibrator() {
+        if (mVibrator != null) {
+            mVibrator.cancel()
+            //开启振动后 等待0.1s振动 振动2s 等待1s 振动2s 等待1s
+            val pattern = longArrayOf(100, 2000, 1000, 2000)
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+                mVibrator.vibrate(VibrationEffect.createWaveform(pattern, -1))
+            } else {
+                mVibrator.vibrate(pattern, -1)
+            }
+        }
+    }
+
+    private fun cancelVibrator() {
+        if (mVibrator != null) {
+            mVibrator.cancel()
+        }
+    }
+
+    override fun onWindowFocusChanged(hasFocus: Boolean) {
+        super.onWindowFocusChanged(hasFocus)
+        window.decorView.systemUiVisibility = screen_flags
+    }
+
+    @SuppressLint("CheckResult")
+    private fun startLoopTransfer() {
+        Thread {
+            while (Constants.newCallList.size > 0) {
+                val curTime = System.currentTimeMillis()
+                var interactionVO: InteractionVO? = null
+                var removeCall = false
+                for (item in Constants.newCallList) {
+                    interactionVO = Gson().fromJson(item.data.toString(), InteractionVO::class.java)
+                    if (curTime - interactionVO.createDate*1000L >= transSeconds*1000L) {
+                        val voiceTransferTcpModel = VoiceUtil.voiceTransfer(item.tid, Constants.deviceId, interactionVO.fromDeviceId, interactionVO.id)
+                        TcpClient.getInstance().sendMsg(voiceTransferTcpModel.toJson())
+
+                        removeCall = true
+                        break
+                    }
+                }
+
+                if (removeCall) {
+                    runOnUiThread {
+                        removeCall(interactionVO!!)
+                    }
+                }
+
+                try {
+                    Thread.sleep(5000)
+                } catch (ex: Exception) {
+                    //ex.printStackTrace()
+                }
+            }
+        }.start()
+    }
+
+    override fun onResume() {
+        super.onResume()
+        window.decorView.systemUiVisibility = screen_flags
+
+        updateCallList()
+    }
+
+    override fun onDestroy() {
+        super.onDestroy()
+        RingPlayHelper.stopRingTone()
+        SpeechUtil.getInstance().stopSpeak()
+        if (EventBus.getDefault().isRegistered(this)) {
+            EventBus.getDefault().unregister(this)
+        }
+        WdKeepAliveService.mNewCallListActive = false
+        Constants.newCallList.clear()
+        cancelVibrator()
+    }
+
+    override fun onBackPressed() {
+        showMessage("Please check incoming call")
+    }
+
+    private fun updateCallList() {
+        synchronized(this) {
+            if (Constants.newCallList.size > 0) {
+                adapter.data.clear()
+                adapter.data.addAll(Constants.newCallList)
+                adapter.notifyDataSetChanged()
+            } else {
+                emptyView.visibility = View.VISIBLE
+                AppTool.Time.delay(500) {
+                    finish()
+                }
+            }
+        }
+    }
+
+    private fun removeCall(item: InteractionVO) {
+        synchronized(this) {
+            val iterator = Constants.newCallList.iterator()
+            while (iterator.hasNext()) {
+                val it = iterator.next()
+                val interaction = Gson().fromJson(it.data.toString(), InteractionVO::class.java)
+                if (interaction.id.equals(item.id)) {
+                    iterator.remove()
+                }
+            }
+
+            if (Constants.newCallList.size > 0) {
+                adapter.data.clear()
+                adapter.data.addAll(Constants.newCallList)
+                adapter.notifyDataSetChanged()
+            } else {
+                emptyView.visibility = View.VISIBLE
+                AppTool.Time.delay(500) {
+                    finish()
+                }
+            }
+        }
+    }
+
+    override fun callAccept(model: TcpModel) {
+        //接听电话,进入通话界面,并刷新呼叫列表
+    }
+
+    override fun callReject(model: TcpModel) {
+        //拒绝电话,刷新列表
+    }
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    fun onMoonEvent(messageEvent: MessageEvent) {
+        if (messageEvent.tag == Constants.EVENT_UPDATE_CALL) { //新呼叫
+            updateCallList()
+        }
+    }
+}

+ 1 - 1
android_mobile/src/main/yd_w_xiaomi_2_chile/code/com/wdkl/ncs/android/component/home/activity/WatchCallRecordsActivity.kt

@@ -136,7 +136,7 @@ class WatchCallRecordsActivity : BaseActivity<WatchCallRecordsFragmentPresenter,
             }
             customerRecords->{
                 //通话处理
-                call_relyout.visibility = View.VISIBLE
+                call_relyout.visibility = View.GONE
                 call_relyout.setOnClickListener {
                     call_relyout.isEnabled = false
 

+ 23 - 0
android_mobile/src/main/yd_w_xiaomi_2_chile/code/com/wdkl/ncs/android/component/home/activity/WatchUserSettingActivity.java

@@ -49,6 +49,8 @@ public class WatchUserSettingActivity extends Activity {
     private RadioButton callYes, callNo;
     private RadioGroup imChannelGroup;
     private RadioButton imChannelYes, imChannelNo;
+    private RadioGroup callTransGroup;
+    private RadioButton transferOn, transferOff;
 
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
@@ -80,6 +82,10 @@ public class WatchUserSettingActivity extends Activity {
         imChannelYes = findViewById(R.id.rb_im_channel_yes);
         imChannelNo = findViewById(R.id.rb_im_channel_no);
 
+        callTransGroup = findViewById(R.id.group_call_transfer);
+        transferOn = findViewById(R.id.rb_call_transfer_on);
+        transferOff = findViewById(R.id.rb_call_transfer_off);
+
         tvAppVersion.setText(CommonUtils.getAppVersionName(BaseApplication.appContext) + "_" + BuildConfig.BUILD_TIME);
         tvDeviceId.setText("" + Constants.Companion.getDeviceId());
         tvDeviceImei.setText(Constants.Companion.getImei());
@@ -100,6 +106,12 @@ public class WatchUserSettingActivity extends Activity {
             imChannelNo.setChecked(true);
         }
 
+        if (SettingConfig.getCallTransfer(BaseApplication.appContext)) {
+            transferOn.setChecked(true);
+        } else {
+            transferOff.setChecked(true);
+        }
+
         int mode = SettingConfig.getLanguageMode(BaseApplication.appContext);
         RadioGroup languageMode = findViewById(R.id.group_language_mode);
         RadioButton languageYes = findViewById(R.id.rb_language_yes);
@@ -232,6 +244,17 @@ public class WatchUserSettingActivity extends Activity {
             }
         });
 
+        callTransGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
+            @Override
+            public void onCheckedChanged(RadioGroup group, int checkedId) {
+                if (checkedId == R.id.rb_call_transfer_on) {
+                    SettingConfig.setCallTransfer(BaseApplication.appContext, true);
+                } else {
+                    SettingConfig.setCallTransfer(BaseApplication.appContext, false);
+                }
+            }
+        });
+
 
         Button update = findViewById(R.id.btn_update_contact);
         update.setOnClickListener(new View.OnClickListener() {

+ 73 - 0
android_mobile/src/main/yd_w_xiaomi_2_chile/code/com/wdkl/ncs/android/component/home/adapter/NewCallItemAdapter.kt

@@ -0,0 +1,73 @@
+package com.wdkl.ncs.android.component.home.adapter
+
+import android.app.Activity
+import android.view.ViewGroup
+import com.alibaba.android.vlayout.LayoutHelper
+import com.alibaba.android.vlayout.layout.LinearLayoutHelper
+import com.google.gson.Gson
+import com.wdkl.ncs.android.component.home.R
+import com.wdkl.ncs.android.component.home.databinding.CallListItemBinding
+import com.wdkl.ncs.android.lib.adapter.BaseDelegateAdapter
+import com.wdkl.ncs.android.lib.utils.BaseRecyclerViewHolder
+import com.wdkl.ncs.android.middleware.model.vo.InteractionVO
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel
+
+class NewCallItemAdapter(var data:ArrayList<TcpModel>, val activity: Activity) : BaseDelegateAdapter<BaseRecyclerViewHolder<CallListItemBinding>, TcpModel>() {
+
+    private var callListener: CallClickListener? = null
+
+    override fun dataProvider(): Any {
+        return data
+    }
+
+    override fun itemFilter(position: Int): Boolean {
+        return true
+    }
+
+    override fun getItemCount(): Int {
+        return data.size
+    }
+
+    override fun onCreateViewHolder(p0: ViewGroup, p1: Int): BaseRecyclerViewHolder<CallListItemBinding> {
+        return BaseRecyclerViewHolder.build(p0, R.layout.call_list_item)
+    }
+
+    override fun onCreateLayoutHelper(): LayoutHelper {
+        return LinearLayoutHelper(10, data.size)
+    }
+
+    override fun onBindViewHolder(p0: BaseRecyclerViewHolder<CallListItemBinding>, p1: Int) {
+        p0.bind { binding ->
+            val itemData = getItem(p1)
+            if (itemData.data != null) {
+                val interactionVO = Gson().fromJson(itemData.data.toString(), InteractionVO::class.java)
+
+                binding.tvCallName.text = interactionVO.fromFrameFullName
+                binding.btnCallAccept.setOnClickListener {
+                    //来电接听
+                    if (callListener != null) {
+                        callListener!!.callAccept(itemData)
+                    }
+                }
+
+                binding.btnCallReject.setOnClickListener {
+                    //来电拒绝
+                    if (callListener != null) {
+                        callListener!!.callReject(itemData)
+                    }
+                }
+            }
+        }
+
+    }
+
+    fun setCallClick(listener: CallClickListener) {
+        callListener = listener
+    }
+
+
+    interface CallClickListener{
+        fun callAccept(model: TcpModel)
+        fun callReject(model: TcpModel)
+    }
+}

+ 1 - 1
android_mobile/src/main/yd_w_xiaomi_2_chile/code/com/wdkl/ncs/android/component/home/adapter/NewEventItemAdapter.kt

@@ -285,7 +285,7 @@ class NewEventItemAdapter(var data:ArrayList<InteractionVO>, val activity: Activ
                 TcpType.VOICE.name->{
                     binding.eliEventName.setText(R.string.event_voice_call)
                     if (Constants.oldEvent) {
-                        binding.eliCallout.visibility = View.VISIBLE
+                        binding.eliCallout.visibility = View.GONE
                         binding.eliEventResponse.visibility = View.INVISIBLE
                     } else {
                         binding.eliVoiceRecorder.visibility = View.GONE

+ 16 - 69
android_mobile/src/main/yd_w_xiaomi_2_chile/code/com/wdkl/ncs/android/component/home/adapter/WatchCallRecordsItemAdapter.kt

@@ -67,18 +67,18 @@ class WatchCallRecordsItemAdapter(val data: ArrayList<InteractionVO>) : BaseDele
             val itemData = getItem(position)
 
             if (itemData.createDate != null) {
-                binding.callTimeTv.text = TimeTransition().stampToDate(itemData.createDate*1000)
+                binding.processingTimeTv.text = TimeTransition().stampToDate(itemData.createDate*1000)
             }
             binding.callStatusImagev.visibility = View.INVISIBLE
 
             if (!TextUtils.isEmpty(itemData.fromMemberName)) {
-                binding.sickbedTv.text = "From: " + itemData.fromMemberName
+                binding.sickbedTv.text = "From: " + itemData.fromFrameFullName + " " + itemData.fromMemberName
             } else {
                 binding.sickbedTv.text = "From: " + itemData.fromFrameFullName
             }
 
             if (!TextUtils.isEmpty(itemData.toMemberName)) {
-                binding.nameTv.text = "To: " + itemData.toMemberName
+                binding.nameTv.text = "To: " + itemData.fromFrameFullName + " " + itemData.toMemberName
             } else {
                 binding.nameTv.text = "To: " + itemData.toFrameFullName
             }
@@ -87,26 +87,7 @@ class WatchCallRecordsItemAdapter(val data: ArrayList<InteractionVO>) : BaseDele
             if (itemData.actionEnd != null) {
                 binding.treatmentStateImagev.setImageResource(R.drawable.checked_100)
                 binding.treatmentStateImagev.visibility = View.VISIBLE
-                binding.processingTimeTv.visibility = View.VISIBLE
-
-                //判断是呼入还是呼出
-                /*if (itemData.fromDeviceMemberId == Constants.memberId){
-                    binding.sickbedTv.text = itemData.toFrameFullName
-                    if (TextUtils.isEmpty(itemData.toMemberName)) {
-                        binding.nameTv.text = "To: " + StringUtil.getResString(R.string.str_null)
-                    } else {
-                        binding.nameTv.text = "To: " + itemData.toMemberName
-                    }
-                    binding.callStatusImagev.setImageResource(R.drawable.hu_chu_yi_jie)
-                } else {
-                    binding.sickbedTv.text = itemData.fromFrameFullName
-                    if (TextUtils.isEmpty(itemData.fromMemberName)) {
-                        binding.nameTv.text = "From: " + StringUtil.getResString(R.string.str_null)
-                    } else {
-                        binding.nameTv.text = "From: " + itemData.fromMemberName
-                    }
-                    binding.callStatusImagev.setImageResource(R.drawable.hu_ru_yi_jie)
-                }*/
+                //binding.processingTimeTv.visibility = View.VISIBLE
 
                 if(itemData.actionType == TcpType.SOS.name){ //sos紧急呼叫 已处理
                     binding.playTv.visibility = View.GONE
@@ -114,7 +95,7 @@ class WatchCallRecordsItemAdapter(val data: ArrayList<InteractionVO>) : BaseDele
                     binding.conductorNameTv.visibility = View.VISIBLE
                     binding.projectTv.text = "SOS"
                     binding.conductorNameTv.text = itemData.actionEndMemberName
-                    binding.processingTimeTv.text = TimeTransition().stampToDate(itemData.actionEnd*1000)
+                    //binding.processingTimeTv.text = TimeTransition().stampToDate(itemData.actionEnd*1000)
                     binding.projectTv.setBackgroundResource(R.drawable.sp_event_do)
                     binding.callStatusImagev.setImageResource(R.drawable.sos_96)
                     binding.callStatusImagev.visibility = View.VISIBLE
@@ -124,7 +105,7 @@ class WatchCallRecordsItemAdapter(val data: ArrayList<InteractionVO>) : BaseDele
                     binding.conductorNameTv.visibility = View.VISIBLE
                     binding.projectTv.text = itemData.data
                     binding.conductorNameTv.text = itemData.actionEndMemberName
-                    binding.processingTimeTv.text = TimeTransition().stampToDate(itemData.actionEnd*1000)
+                    //binding.processingTimeTv.text = TimeTransition().stampToDate(itemData.actionEnd*1000)
                     binding.projectTv.setBackgroundResource(R.drawable.sp_event_do)
                     binding.callStatusImagev.setImageResource(R.drawable.event_do)
                     binding.callStatusImagev.visibility = View.VISIBLE
@@ -134,13 +115,7 @@ class WatchCallRecordsItemAdapter(val data: ArrayList<InteractionVO>) : BaseDele
                     binding.playTv.visibility = View.VISIBLE
                     binding.conductorNameTv.visibility = View.GONE
                     binding.playTv.setBackgroundResource(R.drawable.yi_bo_fang)
-                    //检查是否自己发的留言
-                    /*if (itemData.fromDeviceMemberId == Constants.memberId) {
-                        binding.processingTimeTv.text = "对方已播放"
-                    } else {
-                        binding.processingTimeTv.text = "已播放"
-                    }*/
-                    binding.processingTimeTv.visibility = View.GONE
+                    //binding.processingTimeTv.visibility = View.GONE
                     binding.callStatusImagev.setImageResource(R.drawable.voice_recorder)
                     binding.callStatusImagev.visibility = View.VISIBLE
 
@@ -149,48 +124,27 @@ class WatchCallRecordsItemAdapter(val data: ArrayList<InteractionVO>) : BaseDele
                     binding.playTv.visibility = View.GONE
                     binding.treatmentStateImagev.visibility = View.GONE
                     binding.conductorNameTv.visibility = View.GONE
-                    binding.processingTimeTv.visibility = View.GONE
-
+                    //binding.processingTimeTv.visibility = View.GONE
                 }else if(itemData.actionType == TcpType.VIDEO.name){ //视频呼叫已接听
-
                     binding.projectTv.visibility = View.GONE
                     binding.playTv.visibility = View.GONE
                     binding.treatmentStateImagev.visibility = View.GONE
                     binding.conductorNameTv.visibility = View.GONE
-                    binding.processingTimeTv.visibility = View.GONE
+                    //binding.processingTimeTv.visibility = View.GONE
                 }
 
             } else {
                 binding.treatmentStateImagev.setImageResource(R.drawable.unchecked_100)
                 binding.treatmentStateImagev.visibility = View.VISIBLE
                 binding.conductorNameTv.visibility = View.GONE
-                binding.processingTimeTv.visibility = View.VISIBLE
-
-                //判断是呼入还是呼出 1 分机到主机 2主机到分机
-                /*if(Constants.memberId != itemData.fromDeviceMemberId){
-                    binding.sickbedTv.text = itemData.fromFrameFullName
-                    if (TextUtils.isEmpty(itemData.fromMemberName)) {
-                        binding.nameTv.text = "From: " + StringUtil.getResString(R.string.str_null)
-                    } else {
-                        binding.nameTv.text = "From: " + itemData.fromMemberName
-                    }
-                    binding.callStatusImagev.setImageResource(R.drawable.hu_ru_wei_jie)
-                }else{
-                    binding.sickbedTv.text = itemData.toFrameFullName
-                    if (TextUtils.isEmpty(itemData.toMemberName)) {
-                        binding.nameTv.text = "To: " + StringUtil.getResString(R.string.str_null)
-                    } else {
-                        binding.nameTv.text = "To: " + itemData.toMemberName
-                    }
-                    binding.callStatusImagev.setImageResource(R.drawable.hu_chu_wei_jie)
-                }*/
+                //binding.processingTimeTv.visibility = View.VISIBLE
 
                 if(itemData.actionType == TcpType.SOS.name){ //sos紧急呼叫 未处理
                     binding.playTv.visibility = View.GONE
                     binding.projectTv.visibility = View.VISIBLE
                     binding.projectTv.text = "SOS"
                     binding.projectTv.setBackgroundResource(R.drawable.sp_event_undo)
-                    binding.processingTimeTv.setText(R.string.event_undo)
+                    //binding.processingTimeTv.setText(R.string.event_undo)
                     binding.callStatusImagev.setImageResource(R.drawable.sos_96)
                     binding.callStatusImagev.visibility = View.VISIBLE
                 }else if(itemData.actionType == TcpType.EVENT.name){//事件未处理
@@ -200,36 +154,29 @@ class WatchCallRecordsItemAdapter(val data: ArrayList<InteractionVO>) : BaseDele
                     binding.projectTv.setBackgroundResource(R.drawable.sp_event_undo)
                     binding.callStatusImagev.setImageResource(R.drawable.event_undo)
                     binding.callStatusImagev.visibility = View.VISIBLE
-                    binding.processingTimeTv.setText(R.string.event_undo)
+                    //binding.processingTimeTv.setText(R.string.event_undo)
                 }else if (itemData.actionType == TcpType.IM.name){//语音未播放
                     binding.projectTv.visibility = View.GONE
                     binding.playTv.visibility = View.VISIBLE
                     binding.playTv.setBackgroundResource(R.drawable.wei_bo_fang)
-                    //检查是否自己发的留言
-                    /*if (itemData.fromDeviceMemberId == Constants.memberId) {
-                        binding.processingTimeTv.text = "对方未播放"
-                    } else {
-                        binding.processingTimeTv.text = "未播放"
-                    }*/
-                    binding.processingTimeTv.visibility = View.GONE
+                    //binding.processingTimeTv.visibility = View.GONE
                     binding.callStatusImagev.setImageResource(R.drawable.voice_recorder)
                     binding.callStatusImagev.visibility = View.VISIBLE
                 }else if(itemData.actionType == TcpType.VOICE.name || itemData.actionType == TcpType.PHONE.name){ //语音呼叫未接听
                     binding.projectTv.visibility = View.GONE
                     binding.playTv.visibility = View.GONE
                     binding.treatmentStateImagev.visibility = View.GONE
-                    binding.processingTimeTv.visibility = View.GONE
+                    //binding.processingTimeTv.visibility = View.GONE
                 }else if(itemData.actionType == TcpType.VIDEO.name){ //视频呼叫未接听
                     binding.projectTv.visibility = View.GONE
                     binding.playTv.visibility = View.GONE
                     binding.treatmentStateImagev.visibility = View.GONE
-                    binding.processingTimeTv.visibility = View.GONE
-
+                    //binding.processingTimeTv.visibility = View.GONE
                 } else {
                     binding.projectTv.visibility = View.GONE
                     binding.playTv.visibility = View.GONE
                     binding.treatmentStateImagev.visibility = View.GONE
-                    binding.processingTimeTv.visibility = View.GONE
+                    //binding.processingTimeTv.visibility = View.GONE
                 }
             }
 

+ 63 - 46
android_mobile/src/main/yd_w_xiaomi_2_chile/code/com/wdkl/ncs/android/component/home/service/WdKeepAliveService.kt

@@ -20,6 +20,7 @@ import com.google.gson.GsonBuilder
 import com.google.gson.reflect.TypeToken
 import com.wdkl.ncs.android.component.home.R
 import com.wdkl.ncs.android.component.home.activity.AppUpdateActivity
+import com.wdkl.ncs.android.component.home.activity.NewCallListActivity
 import com.wdkl.ncs.android.component.home.activity.NewEventListActivity
 import com.wdkl.ncs.android.component.home.helper.HttpHelper
 import com.wdkl.ncs.android.component.home.settingconfig.SettingConfig
@@ -66,6 +67,7 @@ class WdKeepAliveService : AbsWorkService() {
 
         var mNewEventListActive = false
         var instanceCreated = false
+        var mNewCallListActive = false
     }
 
 
@@ -81,6 +83,7 @@ class WdKeepAliveService : AbsWorkService() {
 
     private var running = true
     private var playThread: ImPlayThread? = null
+    private var waitingCall = false
 
     private var warningTips = false
     private val keepHandler: Handler = object : Handler(Looper.getMainLooper()) {
@@ -347,32 +350,46 @@ class WdKeepAliveService : AbsWorkService() {
                 Util.wakeUpAndUnlock()
 
                 val tcpModel = messageEvent.getMessage() as TcpModel
-                if (tcpModel.getAction() === TcpAction.VoiceAction.HCALL) {
-                    //手柄呼叫以事件的方式提示
-                    eventSpeechOut(tcpModel)
-                    //震动提醒
-                    handleVibrator()
-
-                    val interactionVO = Gson().fromJson(tcpModel.data.toString(), InteractionVO::class.java)
-                    if (Constants.oldEvent) {
-                        Constants.eventList.clear()
-                    }
-                    Constants.oldEvent = false
-                    Constants.eventList.add(interactionVO)
+                if (tcpModel.getAction() === TcpAction.VoiceAction.HCALL || tcpModel.getAction() == TcpAction.VoiceAction.CALL) {
+                    //取消掉语音留言录音
+                    RecordHelper.getInstance().stopCancelRecordByOther(true)
+                    //停止媒体播放,比如正在播放留言
+                    MediaPlayHelper.getInstance().stopMusic(true)
 
-                    if (!mNewEventListActive) {
-                        Thread(Runnable {
-                            while (RecordHelper.getInstance().isRecording) {
-                                Thread.sleep(400)
-                            }
+                    //加入呼叫列表
+                    Constants.newCallList.add(tcpModel)
 
+                    if (!DeviceChannel.calling && !RecordHelper.getInstance().isRecording) {
+                        if (mNewCallListActive) {
+                            EventBus.getDefault().post(MessageEvent(tcpModel, Constants.EVENT_UPDATE_CALL))
+                        } else {
                             val intent = Intent()
-                            intent.setClass(this, NewEventListActivity::class.java)
+                            intent.setClass(this, NewCallListActivity::class.java)
                             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                             startActivity(intent)
-                        }).start()
+                        }
                     } else {
-                        EventBus.getDefault().post(MessageEvent(tcpModel, Constants.EVENT_UPDATE_EVENT))
+                        if (!waitingCall) {
+                            Thread {
+                                while (DeviceChannel.calling || RecordHelper.getInstance().isRecording) {
+                                    waitingCall = true
+                                    Thread.sleep(500)
+                                }
+                                waitingCall = false
+
+                                if (Constants.newCallList.size > 0) {
+                                    //更新界面
+                                    if (mNewCallListActive) {
+                                        EventBus.getDefault().post(MessageEvent(tcpModel, Constants.EVENT_UPDATE_CALL))
+                                    } else {
+                                        val intent = Intent()
+                                        intent.setClass(this, NewCallListActivity::class.java)
+                                        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+                                        startActivity(intent)
+                                    }
+                                }
+                            }.start()
+                        }
                     }
                 } else if (tcpModel.getAction() === TcpAction.VoiceAction.HRESPONSED) {
                     //已响应
@@ -390,7 +407,7 @@ class WdKeepAliveService : AbsWorkService() {
                     }
                 } else if (tcpModel.getAction() == TcpAction.VoiceAction.SUCCESS) {
                     EventBus.getDefault().post(MessageEvent(tcpModel, 1))
-                } else if (tcpModel.getAction() == TcpAction.VoiceAction.CALL) {
+                } /*else if (tcpModel.getAction() == TcpAction.VoiceAction.CALL) {
                     if (DeviceChannel.calling) {
                         Log.d(TAG, "通话中,来电 " + tcpModel.getFromId() + "<>" + DeviceChannel.callId)
                         //相同来源,重新建立通话
@@ -400,13 +417,32 @@ class WdKeepAliveService : AbsWorkService() {
                     } else { //得到通话
                         EventBus.getDefault().post(MessageEvent(tcpModel, 1))
                     }
-                } else if (tcpModel.getAction() == TcpAction.VoiceAction.ACCEPT //我方呼出,对方接受
+                }*/ else if (tcpModel.getAction() == TcpAction.VoiceAction.ACCEPT //我方呼出,对方接受
                     || tcpModel.getAction() == TcpAction.VoiceAction.REJECT //我方呼出,对方拒绝
                     || tcpModel.getAction() == TcpAction.VoiceAction.CALLING //我方呼出,对方通话中
                     || tcpModel.getAction() == TcpAction.VoiceAction.HANDOFF
                     || tcpModel.getAction() == TcpAction.VoiceAction.FAILED //我方呼出,对方不在线,设备离线或其它错误
                     || tcpModel.getAction() == TcpAction.VoiceAction.CANCEL
                     || tcpModel.getAction() == TcpAction.VoiceAction.VOICE_OFF) {
+
+                    if (tcpModel.getAction() === TcpAction.VoiceAction.CANCEL || tcpModel.action == TcpAction.VoiceAction.VOICE_OFF) {
+                        //对方取消呼叫或者呼叫已被其他主机处理(接听或拒绝)
+                        val interactionVO = Gson().fromJson(tcpModel.data.toString(), InteractionVO::class.java)
+                        val iterator = Constants.newCallList.iterator()
+                        while (iterator.hasNext()) {
+                            val it = iterator.next()
+                            val interaction = Gson().fromJson(it.data.toString(), InteractionVO::class.java)
+                            if (interaction.id.equals(interactionVO.id)) {
+                                iterator.remove()
+                            }
+                        }
+
+                        //更新界面
+                        if (mNewCallListActive) {
+                            EventBus.getDefault().post(MessageEvent(tcpModel, Constants.EVENT_UPDATE_CALL))
+                        }
+                    }
+
                     EventBus.getDefault().post(MessageEvent(tcpModel, 2))
                 }
             }
@@ -458,15 +494,6 @@ class WdKeepAliveService : AbsWorkService() {
                         playVoiceMsg(interaction)
                         val msgTcpModel = ImUtil.imRead(Constants.deviceId, interaction.fromDeviceId, interaction.id)
                         TcpClient.getInstance().sendTcp(msgTcpModel, false, null)
-
-                        /*NettyClient.instance.sendMsg(msgTcpModel.toJson()).subscribe {
-                            if (it) {
-                                Log.d(TAG, "TCP.发送消息完成")
-                            } else {
-                                Log.e(TAG, "TCP.发送消息失败")
-                                HandleTcpConnect.instance.tcpReConnectWithMsgShow()
-                            }
-                        }*/
                     }
                 } else if (tcpModel.action == TcpAction.EventAction.KEY_CLICK) { // 收到新事件
                     val interactionVO = Gson().fromJson(tcpModel.data.toString(), InteractionVO::class.java)
@@ -927,7 +954,7 @@ class WdKeepAliveService : AbsWorkService() {
                     RingPlayHelper.playRingTone(BaseApplication.appContext, R.raw.event, false)
                 }
             }
-        } else if (model.type == TcpType.VOICE && model.action == TcpAction.VoiceAction.HCALL) {
+        } else if (model.action == TcpAction.VoiceAction.HCALL || model.action == TcpAction.VoiceAction.CALL) {
             val callRoom = interactionVO.fromFrameFullName.replace("-", " ")
             val callStr = BaseApplication.appContext.getString(R.string.voice_call_speech, callRoom)
             val speechText = "$callStr,$callStr"
@@ -965,15 +992,6 @@ class WdKeepAliveService : AbsWorkService() {
     private fun sendChannelImRead(channelIm: ChannelImDO) {
         val imTcpModel = ChannelImUtil.channelImRead(Constants.deviceId, channelIm)
         TcpClient.getInstance().sendTcp(imTcpModel, false, null)
-
-        /*NettyClient.instance.sendMsg(imTcpModel.toJson()).subscribe {
-            if (it) {
-                Log.d(TAG, "TCP.发送消息完成")
-            } else {
-                Log.e(TAG, "TCP.发送消息失败")
-                HandleTcpConnect.instance.tcpReConnectWithMsgShow()
-            }
-        }*/
     }
 
     private fun initSpeech() {
@@ -1029,11 +1047,6 @@ class WdKeepAliveService : AbsWorkService() {
 
     fun reConnect() {
         if (NetHelper.getInstance().getNetworkState(this@WdKeepAliveService) != NetHelper.NETWORK_NONE) {
-            /*if (!NettyClient.instance.isConnect()) {
-                Log.w(TAG, "TCP.进入重新连接")
-                HandleTcpConnect.instance.tcpReConnect()
-            }*/
-
             if (!TcpClientHandler.getConnected()) {
                 TcpClient.getInstance().doConnect()
             }
@@ -1077,6 +1090,10 @@ class WdKeepAliveService : AbsWorkService() {
                                             Util.wakeUpAndUnlock()
                                         }
 
+                                        /*if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
+                                            Util.wakeUpAndUnlock()
+                                        }*/
+
                                         //if (Constants.channelId == -1) {
                                         //    showMessage(R.string.str_im_no_channel)
                                         //} else {

+ 10 - 0
android_mobile/src/main/yd_w_xiaomi_2_chile/code/com/wdkl/ncs/android/component/home/settingconfig/SettingConfig.java

@@ -31,6 +31,9 @@ public class SettingConfig {
     //是否使用sip通话
     private static final String KEY_SP_SIP_ENABLE = "KEY_SP_SIP_ENABLE";
 
+    //呼叫转移
+    private static final String KEY_SP_CALL_TRANSFER = "KEY_SP_CALL_TRANSFER";
+
     public static int getLanguageId(Context context) {
         //0--auto, 1--English, 2--中文, 3--西班牙语, 4--俄语
         return getSP(context).getInt(KEY_LANGUAGE_ID, 3);
@@ -56,6 +59,13 @@ public class SettingConfig {
         getEditor(context).putBoolean(KEY_SP_SIP_ENABLE, enable).apply();
     }
 
+    public static boolean getCallTransfer(Context context) {
+        return getSP(context).getBoolean(KEY_SP_CALL_TRANSFER, false);
+    }
+
+    public static void setCallTransfer(Context context, boolean on) {
+        getEditor(context).putBoolean(KEY_SP_CALL_TRANSFER, on).apply();
+    }
 
     /**
      * 获取转发时间

+ 35 - 60
android_mobile/src/main/yd_w_xiaomi_2_chile/code/com/wdkl/ncs/android/component/home/ui/CallSingleActivity.java

@@ -72,6 +72,8 @@ public class CallSingleActivity extends AppCompatActivity {
     public static final String EXTRA_AUDIO_ONLY = "audioOnly";
     public static final String EXTRA_TCPMODEL = "tcpModel";
     public static final String EXTRA_SHOWNAME = "showName";
+    public static final String EXTRA_RING = "ring";
+
     private static final String TAG = "CallSingleActivity";
 
     private boolean isOutgoing;
@@ -86,6 +88,8 @@ public class CallSingleActivity extends AppCompatActivity {
     ILogUpload iLogUpload = new LogUpload();
     VideoRoomCallback videoRoomCallback;
     boolean isSimulateBed = false;
+    boolean ringUp = true;
+    boolean callConnected = false;
 
     private SingleCallFragment currentFragment;
     //振动
@@ -131,9 +135,10 @@ public class CallSingleActivity extends AppCompatActivity {
         isAudioOnly = intent.getBooleanExtra(EXTRA_AUDIO_ONLY,true);
         recTcpModel = (TcpModel) intent.getSerializableExtra(EXTRA_TCPMODEL);
         showName = intent.getStringExtra(EXTRA_SHOWNAME);
+        ringUp = intent.getBooleanExtra(EXTRA_RING, true);
 
         if (recTcpModel !=null && recTcpModel.getData() != null) {
-            Log.d(TAG, recTcpModel.toJson());
+            Log.d(TAG, "received tcp: " + recTcpModel.toJson());
             InteractionVO interactionVO = new Gson().fromJson(recTcpModel.getData().toString(), InteractionVO.class);
             isSimulateBed = (interactionVO.getFromDeviceType() == DeviceTypeEnum.SIMULATE_BED_DEVICE.value());
         }
@@ -275,12 +280,12 @@ public class CallSingleActivity extends AppCompatActivity {
 
             //MediaPlayHelper.getInstance().playResMusic(R.raw.incoming_call, 1.0f, true);
             //RingPlayHelper.playRingTone(this, R.raw.incoming_call, true);
-            long[] pattern = new long[]{100L, 2000L, 1000L, 2000L, 1000L, 2000L};
+            /*long[] pattern = new long[]{100L, 2000L, 1000L, 2000L, 1000L, 2000L};
             if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
                 mVibrator.vibrate(VibrationEffect.createWaveform(pattern, -1));
             } else {
                 mVibrator.vibrate(pattern, -1);
-            }
+            }*/
         }
 
         // 6,处理 publishers,每个publisher 包含 id (feedId) 和 display,attach 到发布者的 handler 上,准备接收视频流,每个发布者都要 attach 一遍,然后协商 sdp, SFU,subscribeAttach 到发布者的 handle 上 [janusClient.subscribeAttach(feedId)]。将publisher 放到Room对象中的publishers, 在 janusClient.subscribeAttach(feedId) 中回调 videoRoomCallback.onSubscribeAttached
@@ -350,74 +355,44 @@ public class CallSingleActivity extends AppCompatActivity {
                 interactionVO = new Gson().fromJson(recTcpModel.getData().toString(), InteractionVO.class);
             }
 
-            if (isOutgoing && (recTcpModel.getAction() == TcpAction.VoiceAction.SUCCESS || recTcpModel.getAction() == TcpAction.VoiceAction.ACCEPT)) {
-                int toId;
-                if (interactionVO.getFromDeviceId().equals(Constants.Companion.getDeviceId())) {
-                    toId = interactionVO.getToDeviceId();
-                } else {
-                    toId = interactionVO.getFromDeviceId();
-                }
-
-                TcpModel voiceUtilTcpModel = VoiceUtil.voiceHandoff(recTcpModel.getTid(), Constants.Companion.getDeviceId(), toId, interactionVO.getId());
-                TcpCallback transaction = new TcpCallback(voiceUtilTcpModel.getTid()) {
-                    @Override
-                    public void onSuccess(JSONObject jsonObject) {
-                        //
+            if (isOutgoing) {
+                //去电
+                if (interactionVO != null) {
+                    int toId;
+                    if (interactionVO.getFromDeviceId().equals(Constants.Companion.getDeviceId())) {
+                        toId = interactionVO.getToDeviceId();
+                    } else {
+                        toId = interactionVO.getFromDeviceId();
                     }
 
-                    @Override
-                    public void onFailed(JSONObject jsonObject) {
-                        //
+                    if (recTcpModel.getAction() == TcpAction.VoiceAction.SUCCESS) {
+                        //呼叫成功后取消呼叫
+                        TcpModel voiceUtilTcpModel = VoiceUtil.voiceCancel(recTcpModel.getTid(), Constants.Companion.getDeviceId(), toId, interactionVO.getId());
+                        TcpClient.getInstance().sendMsg(voiceUtilTcpModel.toJson());
+                    } else if (recTcpModel.getAction() == TcpAction.VoiceAction.ACCEPT) {
+                        //对方接听了挂断
+                        TcpModel voiceUtilTcpModel = VoiceUtil.voiceHandoff(recTcpModel.getTid(), Constants.Companion.getDeviceId(), toId, interactionVO.getId());
+                        TcpClient.getInstance().sendMsg(voiceUtilTcpModel.toJson());
                     }
-                };
-                TcpClient.getInstance().sendTcp(voiceUtilTcpModel, false, transaction);
-
-                /*NettyClient.Companion.getInstance().sendMsg(voiceUtilTcpModel.toJson()).subscribe(it-> {
-                    if (it) {
-                        Log.d(TAG, "TCP.发送消息完成");
-                    } else {
-                        Log.e(TAG, "TCP.发送消息失败");
-                        HandleTcpConnect.Companion.getInstance().tcpReConnectWithMsgShow();
-                    }
-                });*/
-            } else if (recTcpModel.getAction() == TcpAction.VoiceAction.CALL) {
-                int toId;
-                if (interactionVO==null){
-                    toId = recTcpModel.getToId();
-                } else {
+                }
+            } else if (recTcpModel.getAction() == TcpAction.VoiceAction.CALL || recTcpModel.getAction() == TcpAction.VoiceAction.HCALL) {
+                //来电
+                if (interactionVO != null) {
+                    int toId;
                     if (interactionVO.getFromDeviceId().equals(Constants.Companion.getDeviceId())) {
                         toId = interactionVO.getToDeviceId();
                     } else {
                         toId = interactionVO.getFromDeviceId();
                     }
-                }
-                TcpModel voiceUtilTcpModel;
-                if (interactionVO == null){
-                    voiceUtilTcpModel = VoiceUtil.voiceCancel(recTcpModel.getTid(), Constants.Companion.getDeviceId(),recTcpModel.getToId(), null);
-                } else {
-                    voiceUtilTcpModel = VoiceUtil.voiceHandoff(recTcpModel.getTid(), Constants.Companion.getDeviceId(), toId, interactionVO.getId());
-                }
-                TcpCallback transaction = new TcpCallback(voiceUtilTcpModel.getTid()) {
-                    @Override
-                    public void onSuccess(JSONObject jsonObject) {
-                        //
-                    }
 
-                    @Override
-                    public void onFailed(JSONObject jsonObject) {
-                        //
-                    }
-                };
-                TcpClient.getInstance().sendTcp(voiceUtilTcpModel, false, transaction);
-
-                /*NettyClient.Companion.getInstance().sendMsg(voiceUtilTcpModel.toJson()).subscribe(it-> {
-                    if (it) {
-                        Log.d(TAG, "TCP.发送消息完成");
+                    if (callConnected) {
+                        TcpModel voiceUtilTcpModel = VoiceUtil.voiceHandoff(recTcpModel.getTid(), Constants.Companion.getDeviceId(), toId, interactionVO.getId());
+                        TcpClient.getInstance().sendMsg(voiceUtilTcpModel.toJson());
                     } else {
-                        Log.e(TAG, "TCP.发送消息失败");
-                        HandleTcpConnect.Companion.getInstance().tcpReConnectWithMsgShow();
+                        TcpModel voiceUtilTcpModel = VoiceUtil.voiceReject(recTcpModel.getTid(), Constants.Companion.getDeviceId(), toId, interactionVO.getId());
+                        TcpClient.getInstance().sendMsg(voiceUtilTcpModel.toJson());
                     }
-                });*/
+                }
             }
         }
     }

+ 6 - 6
android_mobile/src/main/yd_w_xiaomi_2_chile/code/com/wdkl/ncs/android/component/home/ui/FragmentAudio.java

@@ -94,10 +94,10 @@ public class FragmentAudio extends SingleCallFragment implements View.OnClickLis
         }
         transHandler = new TransHandler();
         //是来电,且是客户来电进入延时转接
-        if (!isOutgoing && interactionVO.getFromClerkId()==null) {
+        /*if (!isOutgoing && interactionVO.getFromClerkId()==null) {
             int transSeconds = SettingConfig.getCountdownTime(this.getContext());
             transHandler.sendEmptyMessageDelayed(TRANS, transSeconds * 1000);
-        }
+        }*/
 
         // 如果已经接通
         if (callSingleActivity.janusClient != null && callSingleActivity.janusClient.getCallState() == EnumType.CallState.Connected) {
@@ -131,9 +131,9 @@ public class FragmentAudio extends SingleCallFragment implements View.OnClickLis
                         frameName = getShowName();
                     }
 
-                    String text = frameName + getString(R.string.call_incoming) + frameName + getString(R.string.call_incoming)
+                    /*String text = frameName + getString(R.string.call_incoming) + frameName + getString(R.string.call_incoming)
                             + frameName + getString(R.string.call_incoming) + frameName + getString(R.string.call_incoming);
-                    SpeechUtil.getInstance().startSpeak(text);
+                    SpeechUtil.getInstance().startSpeak(text);*/
                 }
             }
         }
@@ -226,10 +226,10 @@ public class FragmentAudio extends SingleCallFragment implements View.OnClickLis
     }
 
     private void showCallConnected() {
-        if (callConnected) {
+        if (callSingleActivity.callConnected) {
             return;
         }
-        callConnected = true;
+        callSingleActivity.callConnected = true;
 
         MediaPlayHelper.getInstance().stopMusic(true);
         RingPlayHelper.stopRingTone();

+ 3 - 2
android_mobile/src/main/yd_w_xiaomi_2_chile/code/com/wdkl/ncs/android/component/home/ui/SingleCallFragment.java

@@ -81,7 +81,6 @@ public abstract class SingleCallFragment extends Fragment {
     CallSingleActivity callSingleActivity;
     CallHandler handler;
     boolean isHandoff = false;
-    boolean callConnected = false;
 
     boolean endWithNoAnswerFlag = false;
     public static final int WHAT_DELAY_END_CALL = 0x01;
@@ -118,7 +117,9 @@ public abstract class SingleCallFragment extends Fragment {
         if (isOutgoing) {
             RingPlayHelper.playRingTone(BaseApplication.appContext, R.raw.ring_back2, true);
         } else {
-            RingPlayHelper.playRingTone(BaseApplication.appContext, R.raw.ring_tone, true);
+            if (callSingleActivity.ringUp) {
+                RingPlayHelper.playRingTone(BaseApplication.appContext, R.raw.ring_tone, true);
+            }
         }
     }
 

+ 4 - 0
android_mobile/src/main/yd_w_xiaomi_2_chile/code/com/wdkl/ncs/android/component/home/util/AsyncPlayer.java

@@ -138,6 +138,10 @@ public class AsyncPlayer {
         }
     }
 
+    public boolean isPlay() {
+        return mState == PLAY;
+    }
+
     private void enqueueLocked(Command cmd) {
         mCmdQueue.add(cmd);
         if (mThread == null) {

+ 20 - 1
android_mobile/src/main/yd_w_xiaomi_2_chile/code/com/wdkl/ncs/android/component/home/util/RingPlayHelper.java

@@ -2,20 +2,39 @@ package com.wdkl.ncs.android.component.home.util;
 
 import android.content.Context;
 import android.media.AudioManager;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
 import android.util.Log;
 
 public class RingPlayHelper {
 
     private static AsyncPlayer ringPlayer;
+    private final static Handler handler = new Handler(Looper.getMainLooper()) {
+        @Override
+        public void handleMessage(Message msg) {
+            if (ringPlayer != null) {
+                ringPlayer.stop();
+            }
+        }
+    };
 
     public static void playRingTone(Context context, int res, boolean loop) {
         if (ringPlayer == null) {
             ringPlayer = new AsyncPlayer(null);
         }
-        ringPlayer.play(context, res, loop, AudioManager.STREAM_MUSIC);
+
+        if (!ringPlayer.isPlay()) {
+            ringPlayer.play(context, res, loop, AudioManager.STREAM_MUSIC);
+            handler.removeCallbacksAndMessages(null);
+            //if (loop) {
+            handler.sendEmptyMessageDelayed(10, 60000);
+            //}
+        }
     }
 
     public static void stopRingTone() {
+        handler.removeCallbacksAndMessages(null);
         if (ringPlayer != null) {
             ringPlayer.stop();
         }

+ 34 - 0
android_mobile/src/main/yd_w_xiaomi_2_chile/res/layout/activity_call_list.xml

@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:bind="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:background="#FFBDC3">
+
+    <com.scwang.smartrefresh.layout.SmartRefreshLayout
+        android:id="@+id/srl_call_list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_marginLeft="3sp"
+        android:layout_marginRight="3sp"
+        bind:srlEnableLoadMore="true"
+        bind:srlEnableRefresh="true">
+        <androidx.recyclerview.widget.RecyclerView
+            android:id="@+id/rv_call_list"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:background="#FFBDC3" />
+    </com.scwang.smartrefresh.layout.SmartRefreshLayout>
+
+    <TextView
+        android:id="@+id/tv_empty_call"
+        android:layout_width="match_parent"
+        android:layout_height="60dp"
+        android:gravity="center"
+        android:textSize="24sp"
+        android:textColor="@color/warn_orange"
+        android:text="没有呼叫"
+        android:background="@color/color_white"
+        android:visibility="gone"/>
+</FrameLayout>

+ 6 - 3
android_mobile/src/main/yd_w_xiaomi_2_chile/res/layout/adapter_watch_call_records_item.xml

@@ -107,7 +107,7 @@
             </RelativeLayout>
 
             <LinearLayout
-                android:layout_width="wrap_content"
+                android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:layout_below="@+id/nursing_project_relalyout"
                 android:layout_alignParentEnd="true"
@@ -116,15 +116,18 @@
 
                 <TextView
                     android:id="@+id/conductor_name_tv"
-                    android:layout_width="wrap_content"
+                    android:layout_width="0dp"
                     android:layout_height="wrap_content"
+                    android:layout_weight="1"
                     android:layout_marginEnd="10dp"
                     android:textSize="12sp" />
 
                 <TextView
                     android:id="@+id/processing_time_tv"
-                    android:layout_width="wrap_content"
+                    android:layout_width="0dp"
                     android:layout_height="wrap_content"
+                    android:layout_weight="1"
+                    android:gravity="end"
                     android:textSize="12sp" />
             </LinearLayout>
         </RelativeLayout>

+ 35 - 0
android_mobile/src/main/yd_w_xiaomi_2_chile/res/layout/call_list_item.xml

@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="60dp"
+    android:gravity="center_vertical"
+    android:paddingLeft="10dp"
+    android:paddingRight="10dp"
+    android:background="@color/color_white">
+
+    <TextView
+        android:id="@+id/tv_call_name"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_weight="6"
+        android:textSize="24sp"/>
+
+    <ImageView
+        android:id="@+id/btn_call_accept"
+        android:layout_width="48dp"
+        android:layout_height="48dp"
+        android:layout_weight="1"
+        android:src="@drawable/av_audio_answer_selector"
+        android:visibility="gone"/>
+
+    <ImageView
+        android:id="@+id/btn_call_reject"
+        android:layout_width="48dp"
+        android:layout_height="48dp"
+        android:layout_weight="1"
+        android:src="@drawable/av_hangup_selector"
+        android:visibility="gone"/>
+
+</LinearLayout>
+</layout>

+ 30 - 1
android_mobile/src/main/yd_w_xiaomi_2_chile/res/layout/user_setting_layout.xml

@@ -317,10 +317,39 @@
                 </RadioGroup>
 
                 <TextView
+                    android:id="@+id/tv_call_transfer"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_below="@id/btn_update_contact"
+                    android:layout_marginTop="16dp"
+                    android:text="@string/str_call_transfer_title"
+                    android:textSize="16sp" />
+
+                <RadioGroup
+                    android:id="@+id/group_call_transfer"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_below="@id/tv_call_transfer"
+                    android:layout_marginTop="10dp"
+                    android:orientation="horizontal">
+                    <RadioButton
+                        android:id="@+id/rb_call_transfer_on"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:text="@string/str_yes"/>
+                    <RadioButton
+                        android:id="@+id/rb_call_transfer_off"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:layout_marginLeft="4dp"
+                        android:text="@string/str_no"/>
+                </RadioGroup>
+
+                <TextView
                     android:id="@+id/tv_im_channel_title"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:layout_below="@id/tv_call_title"
+                    android:layout_below="@id/group_call_transfer"
                     android:layout_marginTop="16dp"
                     android:text="@string/media_button_message"
                     android:textSize="16sp" />

+ 1 - 1
build.gradle

@@ -40,7 +40,7 @@ buildscript {
      * YD-S5-W_QIN2PRO-2: 多亲手机
      * ...
      */
-    ext.app_device_type = "yd_watch_2"
+    ext.app_device_type = "yd_w_xiaomi_2_chile"
 
     if (app_device_type == "yd_s5_w_qin2_2") {
         ext.build_tools_version = "26.0.2"

+ 1 - 1
common/build.gradle

@@ -150,7 +150,7 @@ dependencies {
     api(name: 'linphone-sdk-android-5.2.10', ext: 'aar')
 
     //toast 框架
-    compile files('libs/Toaster-12.6.aar')
+    api(name: 'Toaster-12.6', ext: 'aar')
 
     /**
      *  constraint-layout布局依赖