Browse Source

#CHANGE 通话优化

weizhengliang 3 years ago
parent
commit
6e7d75e2c7

+ 5 - 5
home/src/main/code/com/wdkl/ncs/android/component/home/activity/HomeActivity.kt

@@ -33,6 +33,7 @@ import com.wdkl.ncs.android.component.home.BuildConfig
 import com.wdkl.ncs.android.component.home.R
 import com.wdkl.ncs.android.component.home.broadcast.BatteryBroadcastReceiver
 import com.wdkl.ncs.android.component.home.databinding.ActivityHomeBinding
+import com.wdkl.ncs.android.component.home.fragment.SkyCallFragment
 import com.wdkl.ncs.android.component.home.fragment.VisitFragment
 import com.wdkl.ncs.android.component.home.launch.HomeLaunch
 import com.wdkl.ncs.android.component.home.service.TcpHandleService
@@ -483,11 +484,10 @@ class HomeActivity : BaseActivity<HomeActivityPresenter, ActivityHomeBinding>(),
             }
             watch_activity_home_linyout.visibility = View.VISIBLE
         } else if (messageEvent.tag == Constants.VISIT_MSG) {
-            currentFragment = VisitFragment()
+            currentFragment = SkyCallFragment()
             var bundle = Bundle()
-            bundle.putBoolean("out_going", false)
-            bundle.putString("show_text", "连接中")
-            bundle.putString("target_id", Constants.inviteId)
+            bundle.putInt("call_state", 1)
+            bundle.putBoolean("audio_only", false)
             currentFragment?.arguments = bundle
             supportFragmentManager.beginTransaction()
                 .add(R.id.frame_visit, currentFragment)
@@ -519,7 +519,7 @@ class HomeActivity : BaseActivity<HomeActivityPresenter, ActivityHomeBinding>(),
                 if (DeviceChannel.calling == true) {
                     val gEngineKit = SkyEngineKit.Instance()
                     if (gEngineKit != null && gEngineKit.currentSession != null && gEngineKit.currentSession.state != EnumType.CallState.Idle) {
-                        //通话中处理
+                        //通话中挂断
                         gEngineKit.endCall()
                         if (Constants.visitHostId != -1) {
                             VideoUtil.handoffVideoCall(Constants.deviceId, Constants.visitHostId, Constants.interactionId)

+ 103 - 0
home/src/main/code/com/wdkl/ncs/android/component/home/fragment/BaseCallFragment.kt

@@ -0,0 +1,103 @@
+package com.wdkl.ncs.android.component.home.fragment
+
+import android.os.Bundle
+import android.support.v4.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import com.enation.javashop.utils.base.tool.BaseToolActivity
+import com.wdkl.core.voip.VoipEvent
+import com.wdkl.ncs.android.component.nursehome.common.Constants
+import com.wdkl.ncs.android.middleware.utils.MessageEvent
+import com.wdkl.skywebrtc.SkyEngineKit
+import com.wdkl.skywebrtc.except.NotInitializedException
+import org.greenrobot.eventbus.EventBus
+
+abstract class BaseCallFragment: Fragment() {
+
+    private var layout: View? = null
+
+    protected lateinit var baseActivity: BaseToolActivity
+
+    //通话状态:0-去电, 1-来电
+    protected var callState : Int = 0
+    protected var onlyAudio: Boolean = true
+    //来电设备id
+    protected var fromId: Int = -1
+    protected var interactionId: Int? = -1
+    protected var targetId: String? = null
+
+    protected var gEngineKit: SkyEngineKit? = null
+
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        retainInstance = true
+        callState = arguments.getInt("call_state")
+        onlyAudio = arguments.getBoolean("audio_only")
+        fromId = arguments.getInt("fromId")
+        interactionId = arguments.getInt("interactionId")
+        targetId = arguments.getString("targetId")
+    }
+
+    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+        if (layout == null) {
+            layout = inflater.inflate(getLayId(), null)
+        }
+
+        /**初始化宿主Activity*/
+        baseActivity = getActivity() as BaseToolActivity
+
+        return layout
+    }
+
+    override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
+        super.onViewCreated(view, savedInstanceState)
+
+        try {
+            SkyEngineKit.init(VoipEvent())
+            gEngineKit = SkyEngineKit.Instance()
+        } catch (e: NotInitializedException) {
+            SkyEngineKit.init(VoipEvent())
+            try {
+                gEngineKit = SkyEngineKit.Instance()
+            } catch (ex: NotInitializedException) {
+                ex.printStackTrace()
+                baseActivity.finish()
+            }
+        }
+
+        init()
+        bindEvent()
+    }
+
+    override fun onDestroyView() {
+        super.onDestroyView()
+        destroy()
+    }
+
+    override fun onStart() {
+        EventBus.getDefault().register(this)
+        super.onStart()
+    }
+
+    override fun onStop() {
+        EventBus.getDefault().unregister(this)
+        super.onStop()
+    }
+
+    protected abstract fun getLayId(): Int
+
+    protected abstract fun init()
+
+    protected abstract fun bindEvent()
+
+    protected abstract fun destroy()
+
+
+    //返回主界面
+    protected fun backToMain() {
+        EventBus.getDefault().post(MessageEvent("back_to_main", Constants.BACK_TO_MAIN_MSG))
+    }
+
+}

+ 379 - 0
home/src/main/code/com/wdkl/ncs/android/component/home/fragment/SkyCallFragment.kt

@@ -0,0 +1,379 @@
+package com.wdkl.ncs.android.component.home.fragment
+
+import android.os.Handler
+import android.os.Looper
+import android.os.SystemClock
+import android.util.Log
+import android.view.View
+import android.view.ViewGroup
+import com.google.gson.Gson
+import com.wdkl.ncs.android.component.home.R
+import com.wdkl.ncs.android.component.home.util.AppUtils
+import com.wdkl.ncs.android.component.nursehome.common.Constants
+import com.wdkl.ncs.android.lib.utils.showMessage
+import com.wdkl.ncs.android.middleware.model.vo.InteractionVO
+import com.wdkl.ncs.android.middleware.tcp.channel.DeviceChannel
+import com.wdkl.ncs.android.middleware.tcp.channel.VideoUtil
+import com.wdkl.ncs.android.middleware.tcp.channel.VoiceUtil
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel
+import com.wdkl.ncs.android.middleware.tcp.enums.TcpAction
+import com.wdkl.ncs.android.middleware.tcp.enums.TcpType
+import com.wdkl.ncs.android.middleware.utils.MessageEvent
+import com.wdkl.skywebrtc.CallSession
+import com.wdkl.skywebrtc.EnumType
+import com.wdkl.skywebrtc.SkyEngineKit
+import kotlinx.android.synthetic.main.sky_voice_call_layout.*
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+import org.webrtc.SurfaceViewRenderer
+import java.util.*
+
+class SkyCallFragment: BaseCallFragment(), CallSession.CallSessionCallback {
+
+    private var localSurfaceView: SurfaceViewRenderer? = null
+    private var remoteSurfaceView: SurfaceViewRenderer? = null
+
+    private val handler = Handler(Looper.getMainLooper())
+
+    private var callEnded: Boolean = false
+
+    override fun getLayId(): Int {
+        return R.layout.sky_voice_call_layout
+    }
+
+    override fun init() {
+        acceptCall()
+
+        when (callState) {
+            0 -> {
+                //发起通话
+            }
+
+            1 -> {
+                //接受通话
+                DeviceChannel.calling = true
+                val session = gEngineKit?.getCurrentSession()
+                if (session != null) {
+                    session.setSessionCallback(this)
+                }
+                if (onlyAudio) {
+                    Handler().postDelayed({
+                        joinAudioCall()
+                    }, 500)
+                } else {
+                    Handler().postDelayed({
+                        joinVideoCall()
+                    }, 500)
+                }
+            }
+        }
+    }
+
+    override fun bindEvent() {
+        //通话挂断
+        sky_voice_call_hangup.setOnClickListener {
+            //结束sip通话
+            gEngineKit?.endCall()
+
+            if (Constants.visitHostId != -1) {
+                VideoUtil.handoffVideoCall(Constants.deviceId, Constants.visitHostId, Constants.interactionId)
+            }
+
+            DeviceChannel.calling = false
+            sky_voice_call_timer.stop()
+        }
+    }
+
+    override fun destroy() {
+        DeviceChannel.calling = false
+        if (sky_voice_call_timer != null) {
+            sky_voice_call_timer.stop()
+        }
+    }
+
+    //开始接听
+    private fun acceptCall() {
+        sky_voice_call_calling_text.text = "连接中..."
+        sky_voice_call_outgoing.visibility = View.VISIBLE
+        sky_voice_call_timer.visibility = View.GONE
+    }
+
+    //语音接通
+    private fun joinAudioCall() {
+        val session = gEngineKit?.getCurrentSession()
+        if (session != null) {
+            Log.e("dds", "audio call session state: " + session.state)
+
+            if (session.state == EnumType.CallState.Incoming) {
+                session.joinHome(session.roomId)
+                session.toggleSpeaker(true)
+            } else if (session.state == EnumType.CallState.Idle) {
+                callEnd()
+                return
+            }
+
+            Handler().postDelayed({
+                if (session.state == EnumType.CallState.Connected){
+                    showCalling(onlyAudio)
+                } else {
+                    gEngineKit?.endCall()
+                    callEnd()
+                }
+            }, 1500)
+        }
+    }
+
+    //视频接通
+    private fun joinVideoCall() {
+        val session = gEngineKit?.getCurrentSession()
+        if (session != null) {
+            Log.e("dds", "video call session state: " + session.state)
+
+            if (session.state == EnumType.CallState.Incoming) {
+                val surfaceView = gEngineKit!!.currentSession.setupLocalVideo(false)
+                if (surfaceView != null) {
+                    localSurfaceView = surfaceView as SurfaceViewRenderer
+                    localSurfaceView!!.setZOrderMediaOverlay(false)
+                    fullscreen_video_frame.addView(localSurfaceView)
+                }
+
+                session.joinHome(session.roomId)
+                session.toggleSpeaker(true)
+            } else if (session.state == EnumType.CallState.Idle) {
+                callEnd()
+                return
+            }
+
+            Handler().postDelayed({
+                if (session.state == EnumType.CallState.Connected){
+                    showCalling(onlyAudio)
+                } else {
+                    gEngineKit?.endCall()
+                    callEnd()
+                }
+            }, 2000)
+        }
+    }
+
+    private fun showCalling(audioOnly: Boolean) {
+        if (audioOnly) {
+            //移除视频画面
+            fullscreen_video_frame.visibility = View.GONE
+            pip_video_frame.visibility = View.GONE
+            ll_voice_call.visibility = View.VISIBLE
+        } else {
+            //显示视频画面
+            fullscreen_video_frame.visibility = View.VISIBLE
+            pip_video_frame.visibility = View.VISIBLE
+            ll_voice_call.visibility = View.GONE
+        }
+
+        sky_voice_call_calling_text.text = "通话中..."
+        sky_voice_call_timer.visibility = View.VISIBLE
+        sky_voice_call_timer.base = SystemClock.elapsedRealtime()
+        sky_voice_call_timer.start()
+
+        if (Constants.hookOn) {
+            //手柄放下,免提模式
+            AppUtils.switchAudioMode(activity, true)
+        } else {
+            //手柄拿起,听筒模式
+            AppUtils.switchAudioMode(activity, false)
+        }
+    }
+
+    //创建会话
+    private fun startCall(targetId: String, audioOnly: Boolean): Boolean {
+        val room = UUID.randomUUID().toString() + System.currentTimeMillis()
+        val b = gEngineKit!!.startOutCall(baseActivity, room, targetId, audioOnly)
+        if (b) {
+            val session = gEngineKit!!.currentSession
+            if (session == null) {
+                return false
+            } else {
+                DeviceChannel.calling = true
+                session.setSessionCallback(this)
+                session.toggleSpeaker(true)
+
+                //3s还未连接上则判定为通话失败
+                Handler().postDelayed({
+                    if (session.state == EnumType.CallState.Connected){
+                        showCalling(onlyAudio)
+                    } else {
+                        gEngineKit?.endCall()
+                        callEnd()
+                    }
+                }, 3000)
+            }
+        }
+        return b
+    }
+
+    //通话结束
+    private fun callEnd() {
+        Log.e("dds", "call end !!!!!!!!!!!!!!!!!!")
+        if (callEnded) {
+            return
+        }
+        callEnded = true
+
+        DeviceChannel.calling = false
+
+        if (sky_voice_call_timer != null) {
+            sky_voice_call_timer.stop()
+        }
+        if (gEngineKit != null && gEngineKit!!.currentSession != null && gEngineKit!!.currentSession.state != EnumType.CallState.Idle) {
+            gEngineKit!!.endCall()
+        }
+        backToMain()
+    }
+
+
+    /********************************************************
+     ********************* webrtc通话回调 ********************
+     * 注意: 如涉及到UI更新的需要在主线程处理,务必注意
+     *******************************************************/
+    override fun didChangeState(state: EnumType.CallState?) {
+        Log.e("dds", "didChangeState: " + state)
+        /*handler.post {
+            if (state == EnumType.CallState.Connected) {
+                //更新界面显示
+                showCalling(onlyAudio)
+            }
+        }*/
+    }
+
+    override fun didDisconnected(userId: String?) {
+        handler.post {
+            showMessage("断开连接")
+            callEnd()
+        }
+    }
+
+    override fun didError(error: String?) {
+        handler.post {
+            showMessage("通话错误")
+            callEnd()
+        }
+    }
+
+    //处理本地视频画面
+    override fun didCreateLocalVideoTrack() {
+        Log.e("dds", "didCreateLocalVideoTrack")
+        handler.post {
+            val session = gEngineKit!!.currentSession
+            if (session != null && !callEnded) {
+                if (localSurfaceView == null) {
+                    val surfaceView = gEngineKit!!.currentSession.setupLocalVideo(true)
+                    Log.e("dds", "didCreateLocalVideoTrack surfaceView: " + surfaceView)
+                    if (surfaceView != null) {
+                        localSurfaceView = surfaceView as SurfaceViewRenderer
+                    }
+                }
+            }
+        }
+    }
+
+    //处理远端视频画面
+    override fun didReceiveRemoteVideoTrack(userId: String?) {
+        Log.e("dds", "didReceiveRemoteVideoTrack  userId: " + userId)
+        handler.post {
+            val session = gEngineKit!!.currentSession
+            if (session != null && !callEnded) {
+                //本地画面
+                if (localSurfaceView != null) {
+                    localSurfaceView!!.setZOrderMediaOverlay(true)
+                    if (localSurfaceView!!.parent != null) {
+                        (localSurfaceView!!.parent as ViewGroup).removeView(localSurfaceView)
+                    }
+                    pip_video_frame!!.addView(localSurfaceView)
+                }
+
+                //远端画面
+                val surfaceView = gEngineKit!!.currentSession.setupRemoteVideo(userId, false)
+                Log.e("dds", "didReceiveRemoteVideoTrack,surfaceView = $surfaceView")
+                if (surfaceView != null) {
+                    remoteSurfaceView = surfaceView as SurfaceViewRenderer
+                    fullscreen_video_frame.removeAllViews()
+                    if (remoteSurfaceView!!.parent != null) {
+                        (remoteSurfaceView!!.parent as ViewGroup).removeView(remoteSurfaceView)
+                    }
+                    fullscreen_video_frame.addView(remoteSurfaceView)
+                }
+            }
+        }
+    }
+
+    override fun didCallEndWithReason(callEndReason: EnumType.CallEndReason?) {
+        handler.post {
+            when (callEndReason) {
+                EnumType.CallEndReason.Busy -> {
+                    showMessage("对方忙线中")
+                }
+                EnumType.CallEndReason.AcceptByOtherClient -> {
+                    showMessage("通话中")
+                }
+                EnumType.CallEndReason.Hangup -> {
+                    showMessage("通话结束")
+                }
+                EnumType.CallEndReason.MediaError -> {
+                    showMessage("媒体错误")
+                }
+                EnumType.CallEndReason.OpenCameraFailure -> {
+                    showMessage("打开摄像头错误")
+                }
+                EnumType.CallEndReason.RemoteHangup -> {
+                    showMessage("对方挂断")
+                }
+                EnumType.CallEndReason.RemoteSignalError -> {
+                    showMessage("对方网络断开")
+                }
+                EnumType.CallEndReason.SignalError -> {
+                    showMessage("连接断开")
+                }
+                EnumType.CallEndReason.Timeout -> {
+                    showMessage("对方未接听")
+                }
+            }
+
+            callEnd()
+        }
+    }
+
+    override fun didChangeMode(isAudioOnly: Boolean) {
+        handler.post {
+            //
+        }
+    }
+
+    override fun didUserLeave(userId: String?) {
+        handler.post {
+            showMessage("通话结束")
+            callEnd()
+        }
+    }
+
+
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    fun onMoonEvent(messageEvent: MessageEvent) {
+        when (messageEvent.getType()) {
+            /*Constants.EVENT_TCP_MSG -> {
+                if (messageEvent.getMessage() is TcpModel) {
+                    val curTcpModel = messageEvent.getMessage() as TcpModel
+                    if (curTcpModel.getType() == TcpType.VOICE) {
+                        val curInteractionVO = Gson().fromJson(curTcpModel.data.toString(), InteractionVO::class.java)
+                        if (curTcpModel.getAction() == TcpAction.VoiceAction.HANDOFF) {
+                            //对方挂断,不论我方呼出或呼入
+                            if (Constants.interactionId == curInteractionVO.id) {
+                                gEngineKit?.endCall()
+                                callEnd()
+                            }
+                        }
+                    }
+                }
+            }*/
+        }
+    }
+
+}

+ 73 - 2
home/src/main/code/com/wdkl/ncs/android/component/home/util/Util.kt

@@ -5,22 +5,41 @@ import android.app.KeyguardManager
 import android.content.Context
 import android.content.Context.KEYGUARD_SERVICE
 import android.os.Build
+import android.os.Environment
 import android.os.PowerManager
 import android.telephony.TelephonyManager
 import android.util.Log
 import com.enation.javashop.utils.base.tool.SystemTool
 import com.google.common.base.Strings
+import java.io.File
+import java.io.FileInputStream
+import java.io.FileOutputStream
+import java.io.IOException
 import java.lang.Exception
+import java.util.*
 
 object Util {
 
     var IMEI = ""
+    var UUID_FILE_NAME = "wdkl_uuid.txt"
 
     /*
       激活获取IMEI用
     */
     @SuppressLint("MissingPermission", "PrivateApi")
     fun getIMEI(context: Context): String {
+        if (Build.VERSION.SDK_INT >= 29) {
+            val UUIDStr = readSD()
+            if (UUIDStr == null || UUIDStr.isEmpty()) { //如果为空或者空字符串就生成UUID创建文件并写入UUID
+                val uuid: String = Date().getTime().toString()
+                writeSD(uuid)
+                IMEI = uuid
+            } else {
+                IMEI = UUIDStr
+            }
+            return IMEI
+        }
+
         IMEI = SystemTool.getPhoneImei(context)
         if (Strings.isNullOrEmpty(IMEI)) {
             val tm = (context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager)
@@ -34,8 +53,9 @@ object Util {
             }
 
             if (Strings.isNullOrEmpty(IMEI)) {
-                IMEI = "35" + //we make this look like a valid IMEI
-                        Build.BOARD.length % 10 + Build.BRAND.length % 10 + Build.CPU_ABI.length % 10 + Build.DEVICE.length % 10 + Build.DISPLAY.length % 10 + Build.HOST.length % 10 + Build.ID.length % 10 + Build.MANUFACTURER.length % 10 + Build.MODEL.length % 10 + Build.PRODUCT.length % 10 + Build.TAGS.length % 10 + Build.TYPE.length % 10 + Build.USER.length % 10 //13 digits
+                IMEI = SystemTool.getLocalMacAddress()
+//                IMEI = "35" + //we make this look like a valid IMEI
+//                        Build.BOARD.length % 10 + Build.BRAND.length % 10 + Build.CPU_ABI.length % 10 + Build.DEVICE.length % 10 + Build.DISPLAY.length % 10 + Build.HOST.length % 10 + Build.ID.length % 10 + Build.MANUFACTURER.length % 10 + Build.MODEL.length % 10 + Build.PRODUCT.length % 10 + Build.TAGS.length % 10 + Build.TYPE.length % 10 + Build.USER.length % 10 //13 digits
             }
         }
         return IMEI
@@ -85,4 +105,55 @@ object Util {
         }
         return String(value)
     }
+
+    fun writeSD(content: String): String? {
+        //文件输出流
+        var out: FileOutputStream? = null
+        //设置文件路径
+        val file = File(Environment.getExternalStorageDirectory(), UUID_FILE_NAME)
+        return try {
+            out = FileOutputStream(file)
+            out.write(content.toByteArray())
+            content
+        } catch (e: Exception) {
+            e.printStackTrace()
+            ""
+        } finally {
+            try {
+                if (out != null) {
+                    out.close()
+                }
+            } catch (e: IOException) {
+                e.printStackTrace()
+            }
+        }
+    }
+
+    fun readSD(): String? {
+        //文件输入流
+        var `in`: FileInputStream? = null
+        //设置文件路径
+        val file = File(Environment.getExternalStorageDirectory(), UUID_FILE_NAME)
+        return try {
+            `in` = FileInputStream(file)
+            //使用缓冲来读
+            val buf = ByteArray(1024) //每1024字节读一次
+            val builder = StringBuilder()
+            while (`in`.read(buf) !== -1) {
+                builder.append(String(buf).trim { it <= ' ' })
+            }
+            builder.toString()
+        } catch (e: java.lang.Exception) {
+            e.printStackTrace()
+            ""
+        } finally {
+            try {
+                if (`in` != null) {
+                    `in`.close()
+                }
+            } catch (e: IOException) {
+                e.printStackTrace()
+            }
+        }
+    }
 }

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


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


+ 5 - 0
home/src/main/res/drawable/selector_call_hangup.xml

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

+ 75 - 0
home/src/main/res/layout/sky_voice_call_layout.xml

@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout>
+    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="@android:color/background_dark">
+        <!--全屏视频画面-->
+        <FrameLayout
+            android:id="@+id/fullscreen_video_frame"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_gravity="center" />
+
+        <!--小窗视频画面-->
+        <FrameLayout
+            android:id="@+id/pip_video_frame"
+            android:layout_width="70dp"
+            android:layout_height="100dp"
+            android:layout_gravity="top|end"
+            android:layout_marginHorizontal="10dp"
+            android:layout_marginTop="10dp" />
+
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+
+            <LinearLayout
+                android:id="@+id/ll_voice_call"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_centerInParent="true"
+                android:gravity="center_horizontal"
+                android:visibility="gone">
+
+                <TextView
+                    android:id="@+id/sky_voice_call_calling_text"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:gravity="center"
+                    android:text="连接中..."
+                    android:textColor="#9E9E9F"
+                    android:textSize="20sp" />
+            </LinearLayout>
+
+            <!--呼出-->
+            <LinearLayout
+                android:id="@+id/sky_voice_call_outgoing"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_alignParentBottom="true"
+                android:layout_centerHorizontal="true"
+                android:layout_marginBottom="40dp"
+                android:gravity="center_horizontal"
+                android:orientation="vertical"
+                android:visibility="visible">
+
+                <Chronometer
+                    android:id="@+id/sky_voice_call_timer"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:gravity="center"
+                    android:text="00:00"
+                    android:textColor="@color/color_white"
+                    android:textSize="16sp" />
+
+                <ImageView
+                    android:id="@+id/sky_voice_call_hangup"
+                    android:layout_width="40dp"
+                    android:layout_height="40dp"
+                    android:layout_marginTop="10dp"
+                    android:src="@drawable/selector_call_hangup" />
+            </LinearLayout>
+        </RelativeLayout>
+    </FrameLayout>
+</layout>

+ 29 - 10
rtc-chat/src/main/java/com/wdkl/skywebrtc/engine/webrtc/WebRTCEngine.java

@@ -517,9 +517,28 @@ public class WebRTCEngine implements IEngine, Peer.IPeerEvent {
     // -----------------------------其他方法--------------------------------
     private void initIceServer() {
         // 初始化一些stun和turn的地址
-//        PeerConnection.IceServer var1 = PeerConnection.IceServer.builder("stun:stun.l.google.com:19302")
-//                .createIceServer();
-//        iceServers.add(var1);
+        iceServers.add(PeerConnection.IceServer.builder("stun:stun.xten.com:3478").createIceServer());
+        iceServers.add(PeerConnection.IceServer.builder("stun:stun.voipbuster.com:3478").createIceServer());
+        iceServers.add(PeerConnection.IceServer.builder("stun:stun.sipgate.net:3478").createIceServer());
+        iceServers.add(PeerConnection.IceServer.builder("stun:stun.ideasip.com:3478").createIceServer());
+        iceServers.add(PeerConnection.IceServer.builder("stun:stun.internetcalls.com:3478").createIceServer());
+        /*
+stun.xten.com
+stun.voipbuster.com
+stun.sipgate.net
+stun.ekiga.net
+stun.ideasip.com
+stun.schlund.de
+stun.voiparound.com
+stun.voipstunt.com
+stun.counterpath.com
+stun.1und1.de
+stun.gmx.net
+stun.callwithus.com
+stun.counterpath.net
+stun.internetcalls.com
+numb.viagenie.ca
+         */
 
         PeerConnection.IceServer var11 = PeerConnection.IceServer
                 .builder("stun:"+serverIP+":3478?transport=udp")
@@ -533,15 +552,15 @@ public class WebRTCEngine implements IEngine, Peer.IPeerEvent {
                 .setPassword(turnUserPwd)
                 .setTlsCertPolicy(PeerConnection.TlsCertPolicy.TLS_CERT_POLICY_INSECURE_NO_CHECK)
                 .createIceServer();
-//        PeerConnection.IceServer var13 = PeerConnection.IceServer
-//                .builder("turn:"+serverIP+":3478?transport=tcp")
-//                .setUsername(turnUser)
-//                .setPassword(turnUserPwd)
-//                .setTlsCertPolicy(PeerConnection.TlsCertPolicy.TLS_CERT_POLICY_INSECURE_NO_CHECK)
-//                .createIceServer();
+        PeerConnection.IceServer var13 = PeerConnection.IceServer
+                .builder("turn:"+serverIP+":3478?transport=tcp")
+                .setUsername(turnUser)
+                .setPassword(turnUserPwd)
+                .setTlsCertPolicy(PeerConnection.TlsCertPolicy.TLS_CERT_POLICY_INSECURE_NO_CHECK)
+                .createIceServer();
         iceServers.add(var11);
         iceServers.add(var12);
-//        iceServers.add(var13);
+        iceServers.add(var13);
     }