美文网首页Android开发
接入声网视频通话SDK-初步接通视频通话教程

接入声网视频通话SDK-初步接通视频通话教程

作者: 你的益达233 | 来源:发表于2022-05-05 16:29 被阅读0次

    一、前言

    视频通话接通不难,难的是各种情况处理,且有点功能声网SDK是不提供的,如果要完整的视频通话,这代码量有点大,这篇文章仅以接通为目标

    二、看下效果图(设计图)

    video_calling.png video_call.png

    二、跟着我开始步骤

    1、配置部分

    在app下的build.gradle中配置

    implementation 'io.agora.rtc:full-sdk:3.6.2'
    
    2、拨打前或者加入频道前先询问权限
    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){
                                //禁止,不做操作,拨打方直接关闭界面,接听方在点接听时再询问一次
                                if (isCallOutGoing || isClickAcceptCallBack != null){
                                    show(R.string.call_permission_empty_tip)
                                    finish()
                                }
    
                            } else {
                                //永久禁止,需求说只弹前面的弹框,永久禁止就直接跳设置
                                //点接听时跳到设置,返回不处理,让它再点一次接听按钮
                                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、有了权限初始化声网引擎和加入频道(显示自己的视频画面)

    initVideoEngine()代码如下:

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

    我这个本地视频用了相芯美颜的,可参考它demo原来的代码。上面代码中token和channelName都是app服务器接口返回的

    4、自己加入频道后通知对方
    /**
         * @desc : 自己加入频道成功回调
         * @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 {
                    //拨打方加入频道后,邀请对方通话
                    if(disposableIntervalCall == null || disposableIntervalCall!!.isDisposed){
                        disposableIntervalCall = Observable.interval(0,5, TimeUnit.SECONDS, AndroidSchedulers.mainThread())
                            .take(55)
                            .subscribe {
                                //只有第一次邀请要通知栏
                                mViewModel.getChatMediaSendInvite(startCallBean.mediaId,it == 0L)
    
                            }
                    }
                    //自己加入频道后,给对方60s加入频道的时间
                    longTimeNoResponse(timeOutNoResponse)
                }
    
            }
        }
    

    注:onJoinChannelSuccess是加入频道成功后的回调,拨打方加入频道后,就通知对方。如果是接听方加入频道后就可以显示通话中界面了。声网是没有通知对方的api的,我项目是用融云IM通知对方的。

    5、对方加入频道后(显示对方的视频画面)
    /**
         * @desc : 对方加入频道成功回调
         * 此回调在以下任一情况下触发:
         * 1、远程用户/主机通过调用joinChannel方法加入通道。
         * 2、远程用户在加入通道后通过调用setClientRole方法将用户角色切换到主机。
         * 3、网络中断后,远程用户/主机重新加入通道。
         * 4、主机通过调用addInjectStreamUrl方法将在线媒体流注入频道。
         * @author : congge on 2022-03-24 15:08
         **/
        override fun onUserJoined(uid: Int, elapsed: Int) {
            runOnUiThread {
                LogUtils.i("mRtcEventHandler","onUserJoined")
                //stopRinging关闭声音要在dealViewShow前面,里面有关扬声器
                CallRingingUtil.getInstance().stopRinging()
                dealViewShow(false)
                dealCallTime(true)
                //10s内对方进入了频道
                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、拨打方监听到接听方进入频道的回调
    2、接听方进入频道后也会收到这回调

    6、至此双方应该能互相看见对方了,最后就是挂断了

    挂断就是退出频道

    rtcEngine?.leaveChannel()
    

    然后对方就会收到以下回调

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

    如果需要完整的声网音视频通话的代码,可私信我

    相关文章

      网友评论

        本文标题:接入声网视频通话SDK-初步接通视频通话教程

        本文链接:https://www.haomeiwen.com/subject/jvqoyrtx.html