Kotlin高仿微信-第14篇-单聊-视频通话
生活随笔
收集整理的這篇文章主要介紹了
Kotlin高仿微信-第14篇-单聊-视频通话
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Kotlin高仿微信-項目實踐58篇詳細講解了各個功能點,包括:注冊、登錄、主頁、單聊(文本、表情、語音、圖片、小視頻、視頻通話、語音通話、紅包、轉賬)、群聊、個人信息、朋友圈、支付服務、掃一掃、搜索好友、添加好友、開通VIP等眾多功能。
Kotlin高仿微信-項目實踐58篇,點擊查看詳情
效果圖:
?
實現代碼:
/*** 視頻通話、語音通話*/ private fun showVideoPopupWindow(){var popupView = layoutInflater.inflate(R.layout.wc_chat_video_pop_view , moment_root, false)var popupWindow = PopupWindow(popupView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, true)var popupRoot = popupView.findViewById<LinearLayout>(R.id.chat_video_pop_root)popupWindow.showAtLocation(popupRoot, Gravity.BOTTOM, 0, 0)var window = requireActivity().window//popupWindow在彈窗的時候背景半透明val params = window.attributesparams.alpha = 0.5fwindow.attributes = paramspopupWindow.setOnDismissListener {params.alpha = 1.0fwindow.attributes = params}//視頻通話popupView.findViewById<AppCompatTextView>(R.id.chat_pop_video_call).setOnClickListener {popupWindow.dismiss()CallSingleActivity.openActivity( requireActivity(),toUserId, true, toUserName, false, false)}//語音通話popupView.findViewById<AppCompatTextView>(R.id.chat_pop_voice_call).setOnClickListener {popupWindow.dismiss()CallSingleActivity.openActivity( requireActivity(),toUserId, true, toUserName, true, false)}//取消popupView.findViewById<AppCompatTextView>(R.id.chat_pop_cancel).setOnClickListener {popupWindow.dismiss()}} /*** Author : wangning* Email : maoning20080809@163.com* Date : 2022/5/15 13:49* Description :*/ class CallSingleActivity : AppCompatActivity(), CallSession.CallSessionCallback {companion object {val EXTRA_TARGET = "targetId"val EXTRA_MO = "isOutGoing"val EXTRA_AUDIO_ONLY = "audioOnly"val EXTRA_USER_NAME = "userName"val EXTRA_FROM_FLOATING_VIEW = "fromFloatingView"fun openActivity(context: Context, targetId: String, isOutgoing: Boolean, inviteUserName: String,isAudioOnly: Boolean, isClearTop: Boolean) {val intent = getCallIntent(context, targetId, isOutgoing, inviteUserName, isAudioOnly, isClearTop)if (context is Activity) {context.startActivity(intent)} else {intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)context.startActivity(intent)}}fun getCallIntent(context: Context, targetId: String, isOutgoing: Boolean, inviteUserName: String,isAudioOnly: Boolean, isClearTop: Boolean): Intent {val voip = Intent(context, CallSingleActivity::class.java)voip.putExtra(EXTRA_MO, isOutgoing)voip.putExtra(EXTRA_TARGET, targetId)voip.putExtra(EXTRA_USER_NAME, inviteUserName)voip.putExtra(EXTRA_AUDIO_ONLY, isAudioOnly)voip.putExtra(EXTRA_FROM_FLOATING_VIEW, false)if (isClearTop) {voip.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)}return voip}}private val TAG = "CallSingleActivity"private val handler = Handler(Looper.getMainLooper())private var isOutgoing = falseprivate var targetId: String = ""private var inviteUserName: String = ""var isAudioOnly = falseprivate var isFromFloatingView = falseprivate var gEngineKit: SkyEngineKit? = nullprivate var currentFragment: SingleCallFragment? = nullprivate var room: String = ""private var activity:CallSingleActivity? = nulloverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setStatusBarOrScreenStatus(this)setContentView(R.layout.activity_single_call)activity = thistry {gEngineKit = SkyEngineKit.Instance()} catch (e: NotInitializedException) {SkyEngineKit.init(VoipEvent()) //重新初始化try {gEngineKit = SkyEngineKit.Instance()} catch (ex: NotInitializedException) {finish()}}val intent = intenttargetId = intent.getStringExtra(EXTRA_TARGET)!!inviteUserName = intent.getStringExtra(EXTRA_USER_NAME)!!isFromFloatingView = intent.getBooleanExtra(EXTRA_FROM_FLOATING_VIEW, false)isOutgoing = intent.getBooleanExtra(EXTRA_MO, false)isAudioOnly = intent.getBooleanExtra(EXTRA_AUDIO_ONLY, false)if (isFromFloatingView) {val serviceIntent = Intent(this, FloatingVoipService::class.java)stopService(serviceIntent)init(targetId, false, isAudioOnly, false)} else {// 權限檢測val per: Array<String>per = if (isAudioOnly) {arrayOf(Manifest.permission.RECORD_AUDIO)} else {arrayOf(Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA)}Permissions.request(this, per, object : Consumer<Int> {override fun accept(t: Int) {if (t === 0) {// 權限同意init(targetId, isOutgoing, isAudioOnly, false)} else {Toast.makeText(activity, "權限被拒絕", Toast.LENGTH_SHORT).show()// 權限拒絕finish()}}})}}override fun onBackPressed() {}private fun init(targetId: String, outgoing: Boolean, audioOnly: Boolean, isReplace: Boolean) {val fragment: SingleCallFragmentif (audioOnly) {fragment = FragmentAudio()} else {fragment = FragmentVideo()}val fragmentManager: FragmentManager = getSupportFragmentManager()currentFragment = fragmentif (isReplace) {fragmentManager.beginTransaction().replace(android.R.id.content, fragment).commit()} else {fragmentManager.beginTransaction().add(android.R.id.content, fragment).commit()}if (outgoing && !isReplace) {// 創建會話room = UUID.randomUUID().toString() + System.currentTimeMillis()val b: Boolean = gEngineKit?.startOutCall(applicationContext, room, targetId, audioOnly)!!TagUtils.d("創建房間返回:${room} , ${targetId} , ${b}")if (!b) {finish()return}WcApp.getInstance().roomId = roomWcApp.getInstance().otherUserId = targetIdval session: CallSession? = gEngineKit?.getCurrentSession()if (session == null) {finish()} else {session.setSessionCallback(this)}} else {val session: CallSession? = gEngineKit?.getCurrentSession()if (session == null) {finish()} else {if (session.isAudioOnly() && !audioOnly) { //這種情況是,對方切換成音頻的時候,activity還沒啟動,這里啟動后需要切換一下isAudioOnly = session.isAudioOnly()fragment.didChangeMode(true)}session.setSessionCallback(this)}}}fun getEngineKit(): SkyEngineKit? {return gEngineKit}fun isOutgoing(): Boolean {return isOutgoing}fun getInviteUserName(): String {return inviteUserName}fun getToUserId(): String {return targetId}fun isFromFloatingView(): Boolean {return isFromFloatingView}// 顯示小窗fun showFloatingView() {if (!checkOverlayPermission()) {return}val intent = Intent(this, FloatingVoipService::class.java)intent.putExtra(EXTRA_TARGET, targetId)intent.putExtra(EXTRA_USER_NAME, inviteUserName)intent.putExtra(EXTRA_AUDIO_ONLY, isAudioOnly)intent.putExtra(EXTRA_MO, isOutgoing)startService(intent)finish()}// 切換到語音通話fun switchAudio() {init(targetId, isOutgoing, true, true)}fun getRoomId(): String {return room}// ======================================界面回調================================override fun didCallEndWithReason(reason: EnumType.CallEndReason) {WcApp.getInstance().otherUserId = "0"//交給fragment去finish // finish();handler.post { currentFragment?.didCallEndWithReason(reason) }}override fun didChangeState(callState: EnumType.CallState) {if (callState === EnumType.CallState.Connected) {isOutgoing = false}handler.post { currentFragment?.didChangeState(callState) }}override fun didChangeMode(var1: Boolean) {handler.post { currentFragment?.didChangeMode(var1) }}override fun didCreateLocalVideoTrack() {handler.post { currentFragment?.didCreateLocalVideoTrack() }}override fun didReceiveRemoteVideoTrack(userId: String) {handler.post { currentFragment?.didReceiveRemoteVideoTrack(userId) }}override fun didUserLeave(userId: String) {handler.post { currentFragment?.didUserLeave(userId) }}override fun didError(var1: String) {handler.post { currentFragment?.didError(var1) } // finish();}override fun didDisconnected(userId: String) {handler.post { currentFragment?.didDisconnected(userId) }}// ========================================================================================// ========================================================================================private fun checkOverlayPermission(): Boolean {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {SettingsCompat.setDrawOverlays(this, true)if (!SettingsCompat.canDrawOverlays(this)) {Toast.makeText(this, "需要懸浮窗權限", Toast.LENGTH_LONG).show()SettingsCompat.manageDrawOverlays(this)return false}}return true}@TargetApi(19)private fun getSystemUiVisibility(): Int {var flags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_FULLSCREEN orView.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREENif (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {flags = flags or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY}return flags}/*** 設置狀態欄透明*/@TargetApi(19)fun setStatusBarOrScreenStatus(activity: Activity) {val window = activity.window//全屏+鎖屏+常亮顯示window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN orWindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON orWindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED orWindowManager.LayoutParams.FLAG_TURN_SCREEN_ON)window.decorView.systemUiVisibility = getSystemUiVisibility()if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {val layoutParams = getWindow().attributeslayoutParams.layoutInDisplayCutoutMode =WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGESwindow.attributes = layoutParams}// 5.0以上系統狀態欄透明if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {//清除透明狀態欄window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)//設置狀態欄顏色必須添加window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)window.statusBarColor = Color.TRANSPARENT //設置透明} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { //19window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)}}override fun onDestroy() {super.onDestroy()} } /*** Author : wangning* Email : maoning20080809@163.com* Date : 2022/5/15 16:58* Description : 視頻通話控制界面*/ class FragmentVideo : SingleCallFragment(), View.OnClickListener {//private val TAG = "FragmentVideo"private var outgoingAudioOnlyImageView: ImageView? = nullprivate var audioLayout: LinearLayout? = nullprivate var incomingAudioOnlyImageView: ImageView? = nullprivate var hangupLinearLayout: LinearLayout? = nullprivate var acceptLinearLayout: LinearLayout? = nullprivate var connectedAudioOnlyImageView: ImageView? = nullprivate var connectedHangupImageView: ImageView? = nullprivate var switchCameraImageView: ImageView? = nullprivate var fullscreenRenderer: FrameLayout? = nullprivate var pipRenderer: FrameLayout? = nullprivate var inviteeInfoContainer: LinearLayout? = nullprivate var isFromFloatingView = falseprivate var localSurfaceView: SurfaceViewRenderer? = nullprivate var remoteSurfaceView: SurfaceViewRenderer? = nulloverride fun onAttach(context: Context) {super.onAttach(context)if (callSingleActivity != null) {isFromFloatingView = callSingleActivity!!.isFromFloatingView()}}override fun getLayout(): Int {return R.layout.fragment_video}override fun initView(view: View) {super.initView(view)fullscreenRenderer = view.findViewById(R.id.fullscreen_video_view)pipRenderer = view.findViewById(R.id.pip_video_view)inviteeInfoContainer = view.findViewById(R.id.inviteeInfoContainer)outgoingAudioOnlyImageView = view.findViewById(R.id.outgoingAudioOnlyImageView)audioLayout = view.findViewById(R.id.audioLayout)incomingAudioOnlyImageView = view.findViewById(R.id.incomingAudioOnlyImageView)hangupLinearLayout = view.findViewById(R.id.hangupLinearLayout)acceptLinearLayout = view.findViewById(R.id.acceptLinearLayout)connectedAudioOnlyImageView = view.findViewById(R.id.connectedAudioOnlyImageView)connectedHangupImageView = view.findViewById(R.id.connectedHangupImageView)switchCameraImageView = view.findViewById(R.id.switchCameraImageView)outgoingHangupImageView?.setOnClickListener(this)incomingHangupImageView?.setOnClickListener(this)minimizeImageView?.setOnClickListener(this)connectedHangupImageView?.setOnClickListener(this)acceptImageView?.setOnClickListener(this)switchCameraImageView?.setOnClickListener(this)pipRenderer?.setOnClickListener(this)outgoingAudioOnlyImageView?.setOnClickListener(this)incomingAudioOnlyImageView?.setOnClickListener(this)connectedAudioOnlyImageView?.setOnClickListener(this)if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M || OSUtils.isMiui() || OSUtils.isFlyme()) {lytParent!!.post {val params = inviteeInfoContainer?.getLayoutParams() as RelativeLayout.LayoutParamsparams.topMargin = (BarUtils.getStatusBarHeight() * 1.2).toInt()inviteeInfoContainer?.setLayoutParams(params)val params1 = minimizeImageView?.layoutParams as RelativeLayout.LayoutParamsparams1.topMargin = BarUtils.getStatusBarHeight()minimizeImageView?.layoutParams = params1}pipRenderer?.post(Runnable {val params2 = pipRenderer?.getLayoutParams() as FrameLayout.LayoutParamsparams2.topMargin = (BarUtils.getStatusBarHeight() * 1.2).toInt()pipRenderer?.setLayoutParams(params2)})}}override fun init() {super.init()val session = gEngineKit!!.getCurrentSession()if (session != null) {currentState = session.getState()}if (session == null || EnumType.CallState.Idle === session.getState()) {if (callSingleActivity != null) {callSingleActivity!!.finish()}} else if (EnumType.CallState.Connected === session.getState()) {incomingActionContainer!!.visibility = View.GONEoutgoingActionContainer!!.visibility = View.GONEconnectedActionContainer!!.visibility = View.VISIBLEinviteeInfoContainer!!.visibility = View.GONEminimizeImageView!!.visibility = View.VISIBLEstartRefreshTime()} else {if (isOutgoing) {incomingActionContainer!!.visibility = View.GONEoutgoingActionContainer!!.visibility = View.VISIBLEconnectedActionContainer!!.visibility = View.GONEdescTextView?.setText(R.string.av_waiting)} else {incomingActionContainer!!.visibility = View.VISIBLEoutgoingActionContainer!!.visibility = View.GONEconnectedActionContainer!!.visibility = View.GONEdescTextView?.setText(R.string.av_video_invite)if (currentState === EnumType.CallState.Incoming) {val surfaceView = gEngineKit!!.getCurrentSession()!!.setupLocalVideo(false)TagUtils.d("init surfaceView != null is " + (surfaceView != null) + "; isOutgoing = " + isOutgoing + "; currentState = " + currentState)if (surfaceView != null) {localSurfaceView = surfaceView as SurfaceViewRenderer?localSurfaceView!!.setZOrderMediaOverlay(false)fullscreenRenderer!!.addView(localSurfaceView)}}}}if (isFromFloatingView) {didCreateLocalVideoTrack()if (session != null) {didReceiveRemoteVideoTrack(session.mTargetId)}}}override fun didChangeState(state: EnumType.CallState) {currentState = stateTagUtils.d( "didChangeState, state = $state")runOnUiThread {if (state === EnumType.CallState.Connected) {handler!!.removeMessages(WHAT_DELAY_END_CALL)incomingActionContainer!!.visibility = View.GONEoutgoingActionContainer!!.visibility = View.GONEconnectedActionContainer!!.visibility = View.VISIBLEinviteeInfoContainer!!.visibility = View.GONEdescTextView!!.visibility = View.GONEminimizeImageView!!.visibility = View.VISIBLE// 開啟計時器startRefreshTime()} else {// do nothing now}}}override fun didChangeMode(isAudio: Boolean?) {runOnUiThread { callSingleActivity!!.switchAudio() }}override fun didCreateLocalVideoTrack() {if (localSurfaceView == null) {val surfaceView = gEngineKit!!.getCurrentSession()!!.setupLocalVideo(true)localSurfaceView = if (surfaceView != null) {surfaceView as SurfaceViewRenderer?} else {if (callSingleActivity != null) callSingleActivity!!.finish()return}} else {localSurfaceView!!.setZOrderMediaOverlay(true)}TagUtils.d("didCreateLocalVideoTrack localSurfaceView != null is " + (localSurfaceView != null) + "; remoteSurfaceView == null = " + (remoteSurfaceView == null))if (localSurfaceView!!.parent != null) {(localSurfaceView!!.parent as ViewGroup).removeView(localSurfaceView)}if (isOutgoing && remoteSurfaceView == null) {if (fullscreenRenderer != null && fullscreenRenderer!!.childCount != 0) fullscreenRenderer!!.removeAllViews()fullscreenRenderer!!.addView(localSurfaceView)} else {if (pipRenderer!!.childCount != 0) pipRenderer!!.removeAllViews()pipRenderer!!.addView(localSurfaceView)}}override fun didReceiveRemoteVideoTrack(userId: String?) {pipRenderer!!.visibility = View.VISIBLEif (localSurfaceView != null) {localSurfaceView!!.setZOrderMediaOverlay(true)if (isOutgoing) {if (localSurfaceView!!.parent != null) {(localSurfaceView!!.parent as ViewGroup).removeView(localSurfaceView)}pipRenderer!!.addView(localSurfaceView)}}val surfaceView = gEngineKit!!.getCurrentSession()!!.setupRemoteVideo(userId!!, false)TagUtils.d( "didReceiveRemoteVideoTrack,surfaceView = $surfaceView")if (surfaceView != null) {fullscreenRenderer!!.visibility = View.VISIBLEremoteSurfaceView = surfaceView as SurfaceViewRenderer?fullscreenRenderer!!.removeAllViews()if (remoteSurfaceView!!.parent != null) {(remoteSurfaceView!!.parent as ViewGroup).removeView(remoteSurfaceView)}fullscreenRenderer!!.addView(remoteSurfaceView)}}override fun didUserLeave(userId: String?) {}override fun didError(error: String?) {}override fun onClick(v: View) {val id = v.id// 接聽val session = gEngineKit!!.getCurrentSession()if (id == R.id.acceptImageView) {TagUtils.d("接聽 ")if (session != null && session.getState() === EnumType.CallState.Incoming) {TagUtils.d("接聽 if = > ${session.getRoomId()}")session.joinHome(session.getRoomId()!!)} else if (session != null) {TagUtils.d("接聽 else callSingleActivity = ${callSingleActivity}")if (callSingleActivity != null) {session.sendRefuse()callSingleActivity!!.finish()}}}// 掛斷電話if (id == R.id.incomingHangupImageView || id == R.id.outgoingHangupImageView || id == R.id.connectedHangupImageView) {if (session != null) {TagUtils.d("FragmentVideo 掛電話:endCall ")SkyEngineKit.Instance()?.endCall()}if (callSingleActivity != null) callSingleActivity?.finish()}// 切換攝像頭if (id == R.id.switchCameraImageView) {session!!.switchCamera()}if (id == R.id.pip_video_view) {val isFullScreenRemote = fullscreenRenderer!!.getChildAt(0) === remoteSurfaceViewfullscreenRenderer!!.removeAllViews()pipRenderer!!.removeAllViews()if (isFullScreenRemote) {remoteSurfaceView!!.setZOrderMediaOverlay(true)pipRenderer!!.addView(remoteSurfaceView)localSurfaceView!!.setZOrderMediaOverlay(false)fullscreenRenderer!!.addView(localSurfaceView)} else {localSurfaceView!!.setZOrderMediaOverlay(true)pipRenderer!!.addView(localSurfaceView)remoteSurfaceView!!.setZOrderMediaOverlay(false)fullscreenRenderer!!.addView(remoteSurfaceView)}}// 切換到語音撥打if (id == R.id.outgoingAudioOnlyImageView || id == R.id.incomingAudioOnlyImageView || id == R.id.connectedAudioOnlyImageView) {if (session != null) {if (callSingleActivity != null) callSingleActivity!!.isAudioOnly = truesession.switchToAudio()}}// 小窗if (id == R.id.minimizeImageView) {if (callSingleActivity != null) callSingleActivity!!.showFloatingView()}}override fun onDestroyView() {super.onDestroyView()fullscreenRenderer!!.removeAllViews()pipRenderer!!.removeAllViews()} } /*** Author : wangning* Email : maoning20080809@163.com* Date : 2022/5/15 16:14* Description :*/ abstract class SingleCallFragment : Fragment() {private val TAG = "SingleCallFragment"var minimizeImageView: ImageView? = null// 用戶頭像var portraitImageView : ImageView? = null// 用戶昵稱var nameTextView : TextView? = null// 狀態提示用語var descTextView : TextView? = null// 通話時長var durationTextView : Chronometer? = nullvar outgoingHangupImageView: ImageView? = nullvar incomingHangupImageView: ImageView? = nullvar acceptImageView: ImageView? = nullvar tvStatus: TextView? = nullvar outgoingActionContainer: View? = nullvar incomingActionContainer: View? = nullvar connectedActionContainer: View? = nullvar lytParent: View? = nullvar isOutgoing = falsevar inviteUserName = ""var toUserId = ""var gEngineKit: SkyEngineKit? = nullvar handler: CallHandler? = nullcompanion object {var callSingleActivity: CallSingleActivity? = nullval WHAT_DELAY_END_CALL = 0x01val WHAT_NO_NET_WORK_END_CALL = 0x02var currentState: EnumType.CallState? = nullvar headsetPlugReceiver: HeadsetPlugReceiver? = nullvar endWithNoAnswerFlag = falsevar isConnectionClosed = false}override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)retainInstance = trueif (!EventBus.getDefault().isRegistered(this)) {EventBus.getDefault().register(this)}handler = CallHandler()}override fun onCreateView(inflater: LayoutInflater,container: ViewGroup?,savedInstanceState: Bundle?): View? {val view = inflater.inflate(getLayout(), container, false)initView(view)init()return view}override fun onDestroyView() {if (durationTextView != null) durationTextView!!.stop()refreshMessage(true)super.onDestroyView()}override fun onDestroy() {if (EventBus.getDefault().isRegistered(this)) {EventBus.getDefault().unregister(this)}super.onDestroy()}abstract fun getLayout(): Int@Subscribe(threadMode = ThreadMode.MAIN)fun onEvent(messageEvent: MsgEvent<Any?>) {val code: Int = messageEvent.getCode()Log.d(TAG, "onEvent code = \$code; endWithNoAnswerFlag = \$endWithNoAnswerFlag")if (code == MsgEvent.CODE_ON_CALL_ENDED) {if (endWithNoAnswerFlag) {didCallEndWithReason(EnumType.CallEndReason.Timeout)} else if (isConnectionClosed) {didCallEndWithReason(EnumType.CallEndReason.SignalError)} else {if (callSingleActivity != null) {callSingleActivity!!.finish()}}} else if (code == MsgEvent.CODE_ON_REMOTE_RING) {descTextView!!.text = "對方已響鈴"}}override fun onAttach(context: Context) {super.onAttach(context)callSingleActivity = activity as CallSingleActivity?TagUtils.d("SingleCallFragment callSingleActivity 的對象: ${callSingleActivity}")if (callSingleActivity != null) {callSingleActivity?.let {isOutgoing = it.isOutgoing()gEngineKit = it.getEngineKit()inviteUserName = it.getInviteUserName()toUserId = it.getToUserId()}headsetPlugReceiver = HeadsetPlugReceiver()val filter = IntentFilter()filter.addAction(Intent.ACTION_HEADSET_PLUG)callSingleActivity!!.registerReceiver(headsetPlugReceiver, filter)}}override fun onDetach() {super.onDetach()callSingleActivity!!.unregisterReceiver(headsetPlugReceiver) //注銷監聽callSingleActivity = null}open fun initView(view: View) {lytParent = view.findViewById(R.id.lytParent)minimizeImageView = view.findViewById(R.id.minimizeImageView)portraitImageView = view.findViewById(R.id.portraitImageView)nameTextView = view.findViewById(R.id.nameTextView)descTextView = view.findViewById(R.id.descTextView)durationTextView = view.findViewById(R.id.durationTextView)outgoingHangupImageView = view.findViewById(R.id.outgoingHangupImageView)incomingHangupImageView = view.findViewById(R.id.incomingHangupImageView)acceptImageView = view.findViewById(R.id.acceptImageView)tvStatus = view.findViewById(R.id.tvStatus)outgoingActionContainer = view.findViewById(R.id.outgoingActionContainer)incomingActionContainer = view.findViewById(R.id.incomingActionContainer)connectedActionContainer = view.findViewById(R.id.connectedActionContainer)durationTextView?.setVisibility(View.GONE)nameTextView?.setText(inviteUserName)//portraitImageView.setImageResource(R.mipmap.icon_default_header);BaseUtils.showAvatar(toUserId, portraitImageView!!)TagUtils.d("邀請名稱:" + inviteUserName +" , " + toUserId)if (isOutgoing) {handler!!.sendEmptyMessageDelayed(WHAT_DELAY_END_CALL,(60 * 1000).toLong()) //1分鐘之后未接通,則掛斷電話}}open fun init() {}// ======================================界面回調================================fun didCallEndWithReason(callEndReason: EnumType.CallEndReason) {when (callEndReason) {EnumType.CallEndReason.Busy -> {tvStatus!!.text = "對方忙線中"}EnumType.CallEndReason.SignalError -> {tvStatus!!.text = "連接斷開"}EnumType.CallEndReason.RemoteSignalError -> {tvStatus!!.text = "對方網絡斷開"}EnumType.CallEndReason.Hangup -> {tvStatus!!.text = "掛斷"}EnumType.CallEndReason.MediaError -> {tvStatus!!.text = "媒體錯誤"}EnumType.CallEndReason.RemoteHangup -> {tvStatus!!.text = "對方掛斷"}EnumType.CallEndReason.OpenCameraFailure -> {tvStatus!!.text = "打開攝像頭錯誤"}EnumType.CallEndReason.Timeout -> {tvStatus!!.text = "對方未接聽"}EnumType.CallEndReason.AcceptByOtherClient -> {tvStatus!!.text = "在其它設備接聽"}}incomingActionContainer!!.visibility = View.GONEoutgoingActionContainer!!.visibility = View.GONEif (connectedActionContainer != null) connectedActionContainer!!.visibility = View.GONErefreshMessage(false)Handler(Looper.getMainLooper()).postDelayed({if (callSingleActivity != null) {callSingleActivity!!.finish()}}, 1500)}open fun didChangeState(state: EnumType.CallState) {}open fun didChangeMode(isAudio: Boolean?) {}open fun didCreateLocalVideoTrack() {}open fun didReceiveRemoteVideoTrack(userId: String?) {}open fun didUserLeave(userId: String?) {}open fun didError(error: String?) {}fun didDisconnected(error: String?) {handler!!.sendEmptyMessage(WHAT_NO_NET_WORK_END_CALL)}private fun refreshMessage(isForCallTime: Boolean) {if (callSingleActivity == null) {return}// 刷新消息; demo中沒有消息,不用處理這兒快邏輯}fun startRefreshTime() {val session = SkyEngineKit.Instance()!!.getCurrentSession() ?: returnif (durationTextView != null) {durationTextView!!.visibility = View.VISIBLEdurationTextView!!.base =SystemClock.elapsedRealtime() - (System.currentTimeMillis() - session.getStartTime())durationTextView!!.start()}}fun runOnUiThread(runnable: Runnable?) {if (callSingleActivity != null) {callSingleActivity!!.runOnUiThread(runnable)}}class CallHandler : Handler() {override fun handleMessage(msg: Message) {if (msg.what == WHAT_DELAY_END_CALL) {if (currentState !== EnumType.CallState.Connected) {endWithNoAnswerFlag = trueif (callSingleActivity != null) {TagUtils.d("SingleCallFragment 掛電話:endCall 555 ")SkyEngineKit.Instance()?.endCall()}}} else if (msg.what == WHAT_NO_NET_WORK_END_CALL) {isConnectionClosed = trueif (callSingleActivity != null) {TagUtils.d("SingleCallFragment 掛電話:endCall 666 ")SkyEngineKit.Instance()?.endCall()}}}}class HeadsetPlugReceiver : BroadcastReceiver() {override fun onReceive(context: Context, intent: Intent) {if (intent.hasExtra("state")) {val session = SkyEngineKit.Instance()!!.getCurrentSession() ?: returnif (intent.getIntExtra("state", 0) == 0) { //拔出耳機session.toggleHeadset(false)} else if (intent.getIntExtra("state", 0) == 1) { //插入耳機session.toggleHeadset(true)}}}}}?
總結
以上是生活随笔為你收集整理的Kotlin高仿微信-第14篇-单聊-视频通话的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 南网优惠电费接口API源码
- 下一篇: 尼尔 android,尼尔转生wiki官