接入聲網(wǎng)視頻通話SDK-初步接通視頻通話教程

一、前言

視頻通話接通不難,難的是各種情況處理,且有點(diǎn)功能聲網(wǎng)SDK是不提供的,如果要完整的視頻通話,這代碼量有點(diǎn)大,這篇文章僅以接通為目標(biāo)

二、看下效果圖(設(shè)計(jì)圖)

video_calling.png
video_call.png

二、跟著我開始步驟

1、配置部分

在app下的build.gradle中配置

implementation 'io.agora.rtc:full-sdk:3.6.2'
2、撥打前或者加入頻道前先詢問權(quán)限
private fun checkPermission(isClickAcceptCallBack:(() -> Unit)?= null){
    if (PermissionCheckUtil.checkPermissions(mContext,if (startCallBean.type == AUDIO_TYPE) PermissionAppUtils.Group.MICROPHONE else PermissionAppUtils.Group.CAMERA_RECORD)){
        if (startCallBean.type == AUDIO_TYPE) isClickAcceptCallBack?.invoke()?:initAudioEngine() else isClickAcceptCallBack?.invoke()?:initVideoEngine()
    } else {
        DialogUtils.okAndCancel(
            mContext,
            if (startCallBean.type == AUDIO_TYPE) getString(R.string.audio_call_permission_tip) else getString(R.string.video_call_permission_tip),
            ok = getString(R.string.go_open),
            okListener = {
                PermissionAppUtils.requestCombinedPermission(mContext,if (startCallBean.type == AUDIO_TYPE) PermissionAppUtils.Group.MICROPHONE else PermissionAppUtils.Group.CAMERA_RECORD) {
                    if (it.granted){
                        if (isClickAcceptCallBack != null){
                            if (startCallBean.type == AUDIO_TYPE) {
                                initAudioEngine()
                                isClickAcceptCallBack.invoke()
                            } else {
                                initVideoEngine()
                                isClickAcceptCallBack.invoke()
                            }
                        } else {
                            if (startCallBean.type == AUDIO_TYPE) initAudioEngine() else initVideoEngine()
                        }

                    } else  {
                        if (it.shouldShowRequestPermissionRationale){
                            //禁止,不做操作,撥打方直接關(guān)閉界面,接聽方在點(diǎn)接聽時(shí)再詢問一次
                            if (isCallOutGoing || isClickAcceptCallBack != null){
                                show(R.string.call_permission_empty_tip)
                                finish()
                            }

                        } else {
                            //永久禁止,需求說只彈前面的彈框,永久禁止就直接跳設(shè)置
                            //點(diǎn)接聽時(shí)跳到設(shè)置,返回不處理,讓它再點(diǎn)一次接聽按鈕
                            if (isClickAcceptCallBack == null){
                                isJumpAppSetting = true
                                CUtils.startAppSettings(mContext)
                            }

                        }
                    }

                }

            })
    }
}

override fun onResume() {
    super.onResume()
    if (isJumpAppSetting){
        isJumpAppSetting = false
        when(startCallBean.type){
            AUDIO_TYPE -> {
                if (PermissionCheckUtil.checkPermissions(mContext,PermissionAppUtils.Group.MICROPHONE)){
                    initAudioEngine()
                }
            }
            VIDEO_TYPE -> {
                if (PermissionCheckUtil.checkPermissions(mContext,PermissionAppUtils.Group.CAMERA_RECORD)){
                    initVideoEngine()
                }
            }
            else ->{
                show(R.string.call_permission_empty_tip)
                finish()
            }
        }
    }

}
3、有了權(quán)限初始化聲網(wǎng)引擎和加入頻道(顯示自己的視頻畫面)

initVideoEngine()代碼如下:

private fun initVideoEngine(){
    initializeAgoraEngine()
    setupVideoProfile()
    initVideoModule()
    setupLocalVideo(startCallBean.closeCamera)
    rtcEngine?.setVideoSource(RtcVideoConsumer())
    if (isCallOutGoing && !startCallBean.isFloatBackCall){
        joinChannel(startCallBean.token,startCallBean.channelName,SPUtil.getUserId())
    }
}

我這個(gè)本地視頻用了相芯美顏的,可參考它demo原來的代碼。上面代碼中token和channelName都是app服務(wù)器接口返回的

4、自己加入頻道后通知對(duì)方
/**
     * @desc : 自己加入頻道成功回調(diào)
     * @author : congge on 2022-03-24 15:07
     **/
    override fun onJoinChannelSuccess(channel: String, uid: Int, elapsed: Int) {
        runOnUiThread {
            LogUtils.i("mRtcEventHandler","onJoinChannelSuccess")
            if (!isCallOutGoing){
                dealViewShow(true)
                dealCallTime(true)
                mViewModel.postChatMediaAnswer(startCallBean.mediaId)
            } else {
                //撥打方加入頻道后,邀請(qǐng)對(duì)方通話
                if(disposableIntervalCall == null || disposableIntervalCall!!.isDisposed){
                    disposableIntervalCall = Observable.interval(0,5, TimeUnit.SECONDS, AndroidSchedulers.mainThread())
                        .take(55)
                        .subscribe {
                            //只有第一次邀請(qǐng)要通知欄
                            mViewModel.getChatMediaSendInvite(startCallBean.mediaId,it == 0L)

                        }
                }
                //自己加入頻道后,給對(duì)方60s加入頻道的時(shí)間
                longTimeNoResponse(timeOutNoResponse)
            }

        }
    }

注:onJoinChannelSuccess是加入頻道成功后的回調(diào),撥打方加入頻道后,就通知對(duì)方。如果是接聽方加入頻道后就可以顯示通話中界面了。聲網(wǎng)是沒有通知對(duì)方的api的,我項(xiàng)目是用融云IM通知對(duì)方的。

5、對(duì)方加入頻道后(顯示對(duì)方的視頻畫面)
/**
     * @desc : 對(duì)方加入頻道成功回調(diào)
     * 此回調(diào)在以下任一情況下觸發(fā):
     * 1、遠(yuǎn)程用戶/主機(jī)通過調(diào)用joinChannel方法加入通道。
     * 2、遠(yuǎn)程用戶在加入通道后通過調(diào)用setClientRole方法將用戶角色切換到主機(jī)。
     * 3、網(wǎng)絡(luò)中斷后,遠(yuǎn)程用戶/主機(jī)重新加入通道。
     * 4、主機(jī)通過調(diào)用addInjectStreamUrl方法將在線媒體流注入頻道。
     * @author : congge on 2022-03-24 15:08
     **/
    override fun onUserJoined(uid: Int, elapsed: Int) {
        runOnUiThread {
            LogUtils.i("mRtcEventHandler","onUserJoined")
            //stopRinging關(guān)閉聲音要在dealViewShow前面,里面有關(guān)揚(yáng)聲器
            CallRingingUtil.getInstance().stopRinging()
            dealViewShow(false)
            dealCallTime(true)
            //10s內(nèi)對(duì)方進(jìn)入了頻道
            cancelLongTimeNoResponse()
            if (startCallBean.type == VIDEO_TYPE){
                videoUid = uid
                setupRemoteVideo(uid)
            }
        }
    }

private fun setupRemoteVideo(uid: Int,fl: FrameLayout? = mBinding.flVideoCallRemoteVideo,surfaceViewRemote1:SurfaceView? = null) {
    if (isMBindingViewInitialised()){
        fl?.let {
            if (it.childCount >= 1) {
                return
            }
            it.removeAllViews()
            if (surfaceViewRemote1 == null){
                surfaceViewRemote = RtcEngine.CreateRendererView(mContext)
                it.addView(surfaceViewRemote)
                // Initializes the video view of a remote user.
                rtcEngine?.setupRemoteVideo(VideoCanvas(surfaceViewRemote, VideoCanvas.RENDER_MODE_HIDDEN, uid))
                surfaceViewRemote!!.tag = uid // for mark purpose
            } else {
                surfaceViewRemote = surfaceViewRemote1
                it.addView(surfaceViewRemote)
                surfaceViewRemote!!.tag = uid
            }
        }
    }
}

1、撥打方監(jiān)聽到接聽方進(jìn)入頻道的回調(diào)
2、接聽方進(jìn)入頻道后也會(huì)收到這回調(diào)

6、至此雙方應(yīng)該能互相看見對(duì)方了,最后就是掛斷了

掛斷就是退出頻道

rtcEngine?.leaveChannel()

然后對(duì)方就會(huì)收到以下回調(diào)

override fun onUserOffline(uid: Int, reason: Int) 

如果需要完整的聲網(wǎng)音視頻通話的代碼,可私信我

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容