点对点音视频通话

点对点音视频通话功能包含点对点的音频通话和点对点的音视频通话,提供呼叫接听挂断等功能。通过阅读该章节,您可以快速了解点对点实时音视频通话的流程,帮助您迅速搭建一个最简单的点对点实时音视频通话功能。

呼叫/接听流程

sequenceDiagram 主叫->>被叫: 主叫发起通话请求(call2) 被叫->>被叫: 被叫收到通话请求回调(observeIncomingCall) 被叫->>主叫: 被叫响应通话请求(accept2) 被叫->>被叫: 呼入的通话已经被该帐号其他端处理回调(observeOnlineAckNotification) 主叫->>主叫: 主叫收到被叫响应回调(observeCalleeAckNotification) 主叫->>主叫: 通话建立成功(onCallEstablished) 被叫->>被叫: 通话建立成功(onCallEstablished)

主叫发起通话请求

graph TB B[enableRtc] --> C[setChannelProfile 可选 设置音频场景模式 ] C --> D[enableVideo 视频通话需要 ] D --> E[setupVideoCapturer 视频通话需要 ] E --> F[setupLocalVideoRender 视频通话需要 ] F --> G[setParameter/setParameters 可选 用于设置参数 ] G --> H[startVideoPreview 视频通话需要 ] H --> I[call2]

在发起通话时先开启音视频引擎、设置通话可选参数、视频通话设置等初始化设置,然后发起通话。

会话类型参数 AVChatType 主要分为语音通话和视频通话。

会话通知参数 AVChatNotifyOption 包含iOS的通知配置, WebRTC兼容以及可自定义的扩展消息。音视频发起通话是否持续呼叫是根据AVChatNotifyOption中的forceKeepCalling来控制。WebRTC从版本4.5.0开始正式商用,如果没有WebRTC客户端参与时不要设置WebRTC相关参数

其中,设置音频场景模式(可选)setChannelProfile详见音频场景模式节;设置打开预览startVideoPreview详见开始和停止视频采集节。

  /**
     * 激活音视频通话底层引擎
     *
     * 在进行音视频通话前需要调用此接口来激活音视频通话引擎,
     * 否则后续所有的接口调用会导致异常。如果方法调用成功, 后续需要调用  {@link AVChatManagerLite#disableRtc()}
     * 来关闭音视频底层引擎, 否则会出现资源泄漏。
     *
     * @return {@code true} 方法调用成功,{@code false} 方法调用失败
     *
     * @see AVChatManagerLite#disableRtc()
     */
    public abstract boolean enableRtc();

    /**
     * 激活视频模块
     *
     * 如果你通话过程中有视频相关内容, 那必须在视频相关接口调用前先激活视频模块。
     * 通话结束前需要调用  {@link AVChatManagerLite#disableVideo()} 来关闭视频模块。
     * 在通话过程中, 通过此接口可以实现引擎的音视频通话模式切换,
     * 信令层可以通过使用 {@link AVChatManagerLite#sendControlCommand(long, byte, AVChatCallback)} 来通知
     * 对方目前的会话模式切换。 默认情况下视频模块是处于非激活状态。
     *
     * @return {@code true} 方法调用成功,{@code false} 方法调用失败
     *
     * @see AVChatManagerLite#disableVideo()
     */
    public abstract boolean enableVideo();

    /**
     * 设置一个视频捕获器用于提供视频输入, 每次通话只需设置一次
     * 可以使用{@link AVChatVideoCapturerFactory#createCameraCapturer()}创建一个相机捕获器
     * 该方法需要在{@link AVChatManager#startVideoPreview()}前调用
     *
     * @param videoCapturer 视频采集
     * @return {@code true} 方法调用成功,{@code false} 方法调用失败
     * @see com.netease.nimlib.sdk.avchat.model.AVChatCameraCapturer
     * @see AVChatVideoCapturerFactory#createCameraCapturer()
     * @see com.netease.nimlib.sdk.avchat.model.AVChatExternalVideoCapturer
     */
    public abstract boolean setupVideoCapturer(AVChatVideoCapturer videoCapturer);

    /**
     * 设置本地用户视频画布。
     * 如果需要预览,设置自己视频画面的画布需要在call或者joinRoom的onSuccess回调中调用.
     * 如果不需要预览,设置自己视频画面的画布需要在 <code>AVChatStateObserver#onCallEstablished</code> 后调用.
     *
     * @param render      画布. {@link AVChatSurfaceViewRenderer}, {@link AVChatExternalVideoRender}, {@link AVChatTextureViewRenderer}
     * @param mirror      绘制是否镜像, 设置画布为 {@link AVChatSurfaceViewRenderer} 时有效
     * @param scalingType 绘制模式, 设置画布为 {@link AVChatSurfaceViewRenderer} 时有效
     * @return {@code true} 方法调用成功,{@code false} 方法调用失败
     * @see com.netease.nimlib.sdk.avchat.constant.AVChatVideoScalingType
     */
    public abstract boolean setupLocalVideoRender(IVideoRender render, boolean mirror, int scalingType);

   /**
     * 设置参数。
     * 参数类型参考 {@link AVChatParameters.Key#type()}。
     * 参数可设置时机参考 {@link AVChatParameters.Key#runtime()},支持 {@code runtime} 代表通话过程中可操作,不支持则仅能通话前操作。
     * 参数是否可设置参考 {@link AVChatParameters.Key#writable()}, 支持 {@code writable} 代表能够设置参数值,不支持则仅能获取参数值。
     *
     * @param params 设置参数
     * @throws IllegalArgumentException 参数值非法或者参数不支持运行时设置
     * @see AVChatParameters
     * @see AVChatParameters.Key
     * @see AVChatMediaCodecMode
     * @see AVChatAudioEffectMode
     */
    public abstract void setParameters(AVChatParameters params) throws IllegalArgumentException;

 /**
     * 信令层发起双人通话
     *
     * 在信令层发起呼叫, 成功调用此接口后对方会收到相应的会话通知。 在呼叫过程中需要上层实现定时器, 当超过一定时间对方未接听时
     * 需要 {@link AVChatManagerLite#hangUp2(long, AVChatCallback)} 挂断会话。
     *
     * 在发起会话时有几个比较重要可选字段:
     *     {@link AVChatNotifyOption#extendMessage}  附加信息字段, 接听会话的用户会收到此字段。
     *     {@link AVChatNotifyOption#webRTCCompat}  webRTC 兼容, 如果产品没有相关web端参与,不要打开此字段, 目前兼容模式处于测试阶段。
     *     {@link AVChatNotifyOption#forceKeepCalling}  持续呼叫,如果对方不在线也会继续呼叫, 否则会直接返回失败。
     *
     *在调用信令层发起通话接口前需要先调用以下接口:
     *
     *     开启音视频引擎  {@link AVChatManagerLite#enableRtc()}
     *     可选, 激活视频模块 {@link AVChatManagerLite#enableVideo()}
     *     可选, 设置本地预览画布,{@link AVChatManagerLite#setupLocalVideoRender(IVideoRender, boolean, int)}
     *     可选, 开启视频预览,{@link AVChatManagerLite#startVideoPreview()}
     *     可选, 通话相关参数设置 {@link AVChatManagerLite#setParameters(AVChatParameters)},
     *
     * @param account      对方用户账号
     * @param callType     通话类型:语音、视频
     * @param notifyOption 可选通知参数
     * @param callback     回调函数,返回 {@link AVChatData}
     * @see AVChatManagerLite#accept2(long, AVChatCallback)
     * @see AVChatManagerLite#hangUp2(long, AVChatCallback)
     *
     */
    public abstract void call2(String account,
                               AVChatType callType,
                               AVChatNotifyOption notifyOption,
                               AVChatCallback<AVChatData> callback);

setupVideoCapturer参数说明:

参数 说明
AVChatVideoCapturer 相机捕获器

setupLocalVideoRender参数说明:

参数 说明
render 画布,IVideoRender的实现类,可以是AVChatSurfaceViewRendererAVChatExternalVideoRenderAVChatTextureViewRenderer
callType 通话类型:语音、视频
notifyOption 可选通知参数

setParameters参数说明:

参数 说明
params 网络通话可选设置参数,参考AVChatParameters

call2参数说明:

参数 说明
account 对方用户账号
callType 通话类型:语音、视频,参考AVChatType
notifyOption 可选通知参数,参考AVChatNotifyOption
callback 回调函数,参考AVChatCallback
    /**
     * 拨打音视频
     */
    public void outGoingCalling(String account, final AVChatType callTypeEnum) {
        AVChatNotifyOption notifyOption = new AVChatNotifyOption();
        //附加字段
        notifyOption.extendMessage = "extra_data";
        //是否兼容WebRTC模式
        notifyOption.webRTCCompat = webrtcCompat;
        //默认forceKeepCalling为true,开发者如果不需要离线持续呼叫功能可以将forceKeepCalling设为false
        notifyOption.forceKeepCalling = false;
        //打开Rtc模块
        AVChatManager.getInstance().enableRtc();

        this.callingState = (callTypeEnum == AVChatType.VIDEO ? CallStateEnum.VIDEO : CallStateEnum.AUDIO);

        //设置自己需要的可选参数
        AVChatManager.getInstance().setParameters(avChatParameters);

        //视频通话
        if (callTypeEnum == AVChatType.VIDEO) {
            //打开视频模块
            AVChatManager.getInstance().enableVideo();

            //创建视频采集模块并且设置到系统中
            if (mVideoCapturer == null) {
                mVideoCapturer = AVChatVideoCapturerFactory.createCameraCapturer();
                AVChatManager.getInstance().setupVideoCapturer(mVideoCapturer);
            }

            //设置本地预览画布
            AVChatManager.getInstance().setupLocalVideoRender(textureViewRenderer, false, scalingType);

            //开始视频预览
            AVChatManager.getInstance().startVideoPreview();
        }

        //呼叫
        AVChatManager.getInstance().call2(account, callTypeEnum, notifyOption, new AVChatCallback<AVChatData>() {
            @Override
            public void onSuccess(AVChatData data) {
                avChatData = data;
                //发起会话成功
            }

            @Override
            public void onFailed(int code) {
                closeRtc();
                closeSessions(-1);
            }

            @Override
            public void onException(Throwable exception) {
                closeRtc();
                closeSessions(-1);
            }
        });
    }

注意: (1)超时挂断请在APP上层实现,sdk未来会移除超时相关接口,可以参考demo中的AVChatTimeoutObserver类进行实现。 (2)在通话时可以根据需要设置与取消画布,示例如下:

        //取消用户的画布
        AVChatManager.getInstance().setupLocalVideoRender(null, false, 0);

        AVChatManager.getInstance().setupRemoteVideoRender(user, null, false, 0);

        //设置用户的画布
        AVChatManager.getInstance().setupLocalVideoRender(render1, false, AVChatVideoScalingType.SCALE_ASPECT_BALANCED);

        AVChatManager.getInstance().setupRemoteVideoRender(user, render2, false, AVChatVideoScalingType.SCALE_ASPECT_BALANCED);

被叫收到通话请求回调

一般是在 APP 启动时注册来电监听,例如在 Application 的 onCreate 里添加。当监听到来电时,会返回来电信息 AVChatData,其中包含呼叫方式(音频或者视频)、来电帐号。

    /**
     * 注册/注销网络来电.
     * 当收到对方来电请求时,会通知上层通话信息。
     * 用户可以选择 {@link AVChatManager#accept2(long, AVChatCallback)} 来接听电话,
     * 或者 {@link AVChatManager#hangUp2(long, AVChatCallback)}  来挂断电话。 通常在收到来电请求时,上层需要维持
     * 一个超时器,当超过一定时间没有操作时直接调用 {@link AVChatManager#hangUp2(long, AVChatCallback)} 来挂断。
     * 当用户当前有电话在进行时,如果收到来电请求,需要选择是接听当前电话和是继续原来的通话。如果接听当前来电,则需要
     * {@link AVChatManager#hangUp2(long, AVChatCallback)} 原来进行的电话,然后 {@link AVChatManager#accept2(long, AVChatCallback)}
     * 当前来电。 如果选择继续原来的通话,挂断当前来电,最好能够先发送一个正忙的指令给对方 {@link AVChatManager#sendControlCommand(long, byte, AVChatCallback)},
     * 然后在再挂断 {@link AVChatManager#hangUp2(long, AVChatCallback)} 当前通话。
     *
     * @param observer 观察者,参数为被叫通话的基本信息
     * @param register {@code true} 注册监听,{@code false} 注销监听
     */
    public abstract void observeIncomingCall(Observer<AVChatData> observer, boolean register);
参数 说明
observer 观察者,AVChatData 中包含具体的来电信息。
register 是否注册观察者,注册为 true, 注销为 false

对来电进行处理,需要在 AndroidManifest.xml 文件中配置接收器

<!-- 申明本地电话状态(通话状态)的广播接收器,第三方APP集成时音视频模块时,如果需要在App中处理网络通话与本地电话的交互请加上此接收器 -->
<!-- 在Demo的示例代码中是在Application进行了网络通话与本地电话的互斥处理 -->
<receiver android:name="com.netease.nim.demo.avchat.receiver.IncomingCallReceiver">
    <intent-filter>
        <action android:name="android.intent.action.PHONE_STATE"/>
    </intent-filter>
</receiver>

然后在需要注册监听的地方进行注册

private void enableAVChat() {
    registerAVChatIncomingCallObserver(true);
}

private void registerAVChatIncomingCallObserver(boolean register) {
    AVChatManager.getInstance().observeIncomingCall(new Observer<AVChatData>() {
        @Override
        public void onEvent(AVChatData data) {
            String extra = data.getExtra();
            Log.e("Extra", "Extra Message->" + extra);
            if (PhoneCallStateObserver.getInstance().getPhoneCallState() != PhoneCallStateObserver.PhoneCallStateEnum.IDLE
                    || AVChatProfile.getInstance().isAVChatting()
                    || AVChatManager.getInstance().getCurrentChatId() != 0) {
                LogUtil.i(TAG, "reject incoming call data =" + data.toString() + " as local phone is not idle");
                AVChatManager.getInstance().sendControlCommand(data.getChatId(), AVChatControlCommand.BUSY, null);
                return;
            }
            // 有网络来电打开AVChatActivity
            AVChatProfile.getInstance().setAVChatting(true);
            AVChatActivity.launch(DemoCache.getContext(), data, AVChatActivity.FROM_BROADCASTRECEIVER);
        }
    }, register);
}

被叫响应通话请求

当监听到来电后启动通话界面,被叫方可以选择接听或者拒绝。当选择接听时,同样需要在接听通话前进行前面的开启音视频引擎、设置通话可选参数、视频通话设置等初始化设置,然后接听通话,建立通话连接。

其中,enableRtcenableVideosetupVideoCapturersetupLocalVideoRendersetParameter详见主叫发起通话请求节,设置音频场景模式(可选)setChannelProfile详见音频场景模式节;设置打开预览startVideoPreview详见开始和停止视频采集节。

    /**
     * 信令层接听双人通话
     *
     * 在程序启动时需要注册 {@link AVChatManagerLite#observeIncomingCall(Observer, boolean)}, 这样在有其他用户
     * 呼叫时将会收到来电通知, 收到来电通知后一般会有相应的界面展示, 如果需要接听电话那个需要调用此接口, 如果需要拒绝通话请调用
     * {@link AVChatManagerLite#hangUp2(long, AVChatCallback)}。
     *
     * 在成功接听会话后, 引擎就会自动去连接预先分配好的媒体服务器。 连接媒体服务器的结果将会在
     * {@link AVChatStateObserverLite#onJoinedChannel(int, String, String, int)} 中进行通知。
     *
     *
     * 在调用信令层接听会话接口前需要先调用以下接口:
     *
     *     开启音视频引擎  {@link AVChatManagerLite#enableRtc()}
     *     可选, 激活视频模块 {@link AVChatManagerLite#enableVideo()}
     *     可选, 设置本地预览画布,{@link AVChatManagerLite#setupLocalVideoRender(IVideoRender, boolean, int)}
     *     可选, 开启视频预览,{@link AVChatManagerLite#startVideoPreview()}
     *     可选, 通话相关参数设置 {@link AVChatManagerLite#setParameters(AVChatParameters)}
     *
     * @param chatId   会话ID
     * @param callback 回调函数,返回接听后,本地音视频设备启动是否成功。
     *                 回调onSuccess表示成功;回调onFailed表示失败,错误码-1表示初始化引擎失败,需要重试。
     *                 注意:由于音视频引擎析构需要时间,请尽可能保持上一次通话挂断到本次电话接听时间间隔在2秒以上,否则有可能在接听时出现初始化引擎失败(code = -1)
     *
     * @see AVChatManagerLite#call2(String, AVChatType, AVChatNotifyOption, AVChatCallback)
     * @see AVChatManagerLite#hangUp2(long, AVChatCallback)
     */
public abstract void accept2(long chatId, AVChatCallback<Void> callback);
参数 说明
chatId 会话ID。
callback 是回调函数,返回接听后,本地音视频设备启动是否成功。回调onSuccess表示成功;回调onFailed表示失败,错误码-1表示初始化引擎失败,需要重试。
    /**
     * 接听来电
     */
    private void receiveInComingCall() {
        //接听,告知服务器,以便通知其他端

        AVChatManager.getInstance().enableRtc();
        if (mVideoCapturer == null) {
            mVideoCapturer = AVChatVideoCapturerFactory.createCameraCapturer();
            AVChatManager.getInstance().setupVideoCapturer(mVideoCapturer);
        }
        AVChatManager.getInstance().setParameters(avChatParameters);
        if (callingState == CallStateEnum.VIDEO_CONNECTING) {
            AVChatManager.getInstance().enableVideo();
            AVChatManager.getInstance().startVideoPreview();
        }

        AVChatManager.getInstance().accept2(avChatData.getChatId(), new AVChatCallback<Void>() {
            @Override
            public void onSuccess(Void aVoid) {
                LogUtil.i(TAG, "accept success");

                isCallEstablish.set(true);
                canSwitchCamera = true;
            }

            @Override
            public void onFailed(int code) {
                if (code == -1) {
                    Toast.makeText(context, "本地音视频启动失败", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(context, "建立连接失败", Toast.LENGTH_SHORT).show();
                }
                LogUtil.e(TAG, "accept onFailed->" + code);
                handleAcceptFailed();
            }

            @Override
            public void onException(Throwable exception) {
                LogUtil.d(TAG, "accept exception->" + exception);
                handleAcceptFailed();
            }
        });
    }

    private void handleAcceptFailed() {
        if (destroyRTC) {
            return;
        }
        if (callingState == CallStateEnum.VIDEO_CONNECTING) {
            AVChatManager.getInstance().stopVideoPreview();
            AVChatManager.getInstance().disableVideo();
        }
        AVChatManager.getInstance().disableRtc();
        destroyRTC = true;
        closeSessions(AVChatExitCode.CANCEL);
    }

注意: (1)由于音视频引擎析构需要时间,请尽可能保证上一次通话挂断到本次电话接听时间间隔在2秒以上,否则有可能在接听时出现初始化音视频引擎失败,此问题后期会进行优化。 (2)超时挂断请在APP上层实现,sdk未来会移除超时相关接口,可以参考demo中的AVChatTimeoutObserver类进行实现。

主叫收到被叫响应回调

主叫方在发起呼叫成功后需要监听被叫方的回应,监听接口 observeCalleeAckNotification,回调返回 AVChatCalleeAckEvent,其中包含被叫方的回应结果: (1) 对方拒绝接听; (2) 对方已经有来电了,此时会返回忙; (3) 对方同意接听,此时 SDK 会自动开启音视频设备,建立通话连接,然后双方就可以进行语音视频通话了。

    /**
     * 注册/注销网络通话被叫方的响应(接听、拒绝、忙)
     *
     * @param observer 观察者, 参数为接收到的网络通话的通知消息
     * @param register {@code true} 注册监听,{@code false} 注销监听
     */
    public abstract void observeCalleeAckNotification(Observer<AVChatCalleeAckEvent> observer, boolean register);
参数 说明
observer 观察者,在观察者中根据 AVChatCalleeAckEvent 的类型进行处理,参考AVChatCalleeAckEvent
register 是否注册观察者,注册为 true, 注销为 false

呼入的通话已经被该帐号其他端处理回调

如果自己的帐号有其他端在线(PC、Web),来电会被其他端做了回应,那么移动端会收到一条通知。因此,移动端在收到来电后需要监听 PC 端对主叫方的响应。

 /**
     * 注册/注销同时在线的其他端对主叫方的响应
     *
     * @param observer 观察者,参数为同时在线的其他端响应主叫方的同步通知
     * @param register {@code true} 注册监听,{@code false} 注销监听
     */
    public abstract void observeOnlineAckNotification(Observer<AVChatOnlineAckEvent> observer, boolean register);
参数 说明
observer 观察者,参数为同时在线的其他端响应主叫方的同步通知,在观察者中根据 AVChatOnlineAckEvent 的类型进行处理。
register 是否注册观察者,注册为 true, 注销为 false
AVChatManager.getInstance().observeOnlineAckNotification(onlineAckObserver, register);
Observer<AVChatOnlineAckEvent> onlineAckObserver = new Observer<AVChatOnlineAckEvent>() {
        @Override
        public void onEvent(AVChatOnlineAckEvent ackInfo) {
            if (ackInfo.getClientType() != ClientType.Android) {
                String client; // 做回应的客户端
                switch (ackInfo.getClientType()) {
                    ...
                    case ClientType.Windows:
                        client = "Windows";
                        break;
                    default:
                        break;
                }
                // your code
                avChatUI.closeSessions();
            }
        }
    };

通话建立结果回调

音视频连接建立,会回调 onCallEstablished。音频切换到正在通话的界面,并开始计时等处理。视频则通过为用户设置对应画布并添加到相应的 layout 上显示图像。

Override
public void onCallEstablished() {
    if (state == AVChatTypeEnum.AUDIO.getValue()) {
        aVChatUIManager.onCallStateChange(CallStateEnum.AUDIO);
    } else {
        aVChatUIManager.initSmallSurfaceView();
        aVChatUIManager.onCallStateChange(CallStateEnum.VIDEO);
    }
    isCallEstablished = true;
}

挂断流程

主叫或者被叫都可以调用结束通话相关接口进行挂断通话,下面以主叫挂断进行示例,被叫挂断也是同样的流程。

sequenceDiagram 主叫->>被叫: 结束通话(hangup2) 被叫->>被叫: 收到对方结束通话回调(observeHangUpNotification) 被叫->>被叫: 通话断开(disableRtc) 主叫->>主叫: 通话断开(disableRtc)

结束通话

graph TB B[stopVideoPreview 视频通话需要 ] --> C[disableVideo 视频通话需要 ] C --> D[hangUp2 ] D --> E[disableRtc]

发起结束通话的一方,调用 stopVideoPreviewdisableVideohangUp2disableRtc 接口。另外一方,需要注册 observeHangUpNotification 监听挂断通知,收到通知后,做相应处理,代码示例见 收到对方结束通话回调(主叫方、被叫方)

其中,设置关闭预览stopVideoPreview详见开始和停止视频采集节。

    /**
     * 关闭视频模块
     *
     * 关闭视频相关模块。 在通过过程中调用会让引擎切换到语音模式, 如果信令层需要通知对方,则通过
     * {@link AVChatManagerLite#sendControlCommand(long, byte, AVChatCallback)} 实现。
     *
     * @return {@code true} 方法调用成功,{@code false} 方法调用失败
     *
     * @see AVChatManagerLite#enableVideo()
     */
    public abstract boolean disableVideo();

    /**
     * 信令层挂断或者拒绝通话请求
     *
     * 在程序启动时需要注册 {@link AVChatManagerLite#observeIncomingCall(Observer, boolean)}, 这样在有其他用户
     * 呼叫时将会收到来电通知, 收到来电通知后一般会有相应的界面展示, 如果需要拒绝电话调用此接口, 如果需要接听通话请调用
     * {@link AVChatManagerLite#accept2(long, AVChatCallback)}。
     *
     * 如果在通话过程中调用此接口,则会直接挂断通话, 同时对方会收到你挂断通知信令。
     *
     * 此接口仅仅是信令层的挂断,如果需要销毁引擎释放资源需要调用以下接口:
     *      可选, 关闭视频预览 {@link AVChatManagerLite#stopVideoPreview()} ()}
     *      可选, 关闭视频模块 {@link AVChatManagerLite#disableVideo()}}
     *      释放通话资源 {@link AVChatManagerLite#disableRtc()}
     *
     * @param chatId   会话ID。发起通话和被叫通知都有会话ID通知,挂断时需要制定会话ID,如果在呼叫过程中还没有返回会话ID, 则传入0能够挂断正在呼叫的会话。
     * @param callback 回调函数
     * @see AVChatManagerLite#call2(String, AVChatType, AVChatNotifyOption, AVChatCallback)
     * @see AVChatManagerLite#accept2(long, AVChatCallback)
     */
    public abstract void hangUp2(long chatId, AVChatCallback<Void> callback);

    /**
     * 关闭音视频通话底层引擎
     *
     * 在通话结束后需要调用此接口关闭音视频通话引擎来释放资源。
     * 关闭音视频引擎后后续所有的其他调用都会失败或者异常。
     *
     * @return {@code true} 方法调用成功,{@code false} 方法调用失败
     *
     * @see AVChatManagerLite#enableRtc()
     */
    public abstract boolean disableRtc();

hangUp2参数说明:

参数 说明
chatId 会话ID。
callback 回调函数,返回挂断是否成功。回调onSuccess表示成功;回调onFailed表示失败
// 如果是视频通话,关闭视频模块
AVChatManager.getInstance().disableVideo();
// 如果是视频通话,需要先关闭本地预览
AVChatManager.getInstance().stopVideoPreview();
//挂断
AVChatManager.getInstance().hangUp2(avChatData.getChatId(), new AVChatCallback<Void>() {};
//销毁音视频引擎和释放资源
AVChatManager.getInstance().disableRtc();

收到对方结束通话回调

当被叫方收到来电时(在通话建立之前)需要监听主叫方挂断通知,当双方通话建立之后,都需要监听对方挂断通知来结束本次通话。

    /**
     * 注册/注销网络通话对方挂断的通知
     *
     * @param observer 观察者, 参数为接收到的网络通话的挂断消息
     * @param register {@code true} 注册监听,{@code false} 注销监听
     */
    public abstract void observeHangUpNotification(Observer<AVChatCommonEvent> observer, boolean register);
参数 说明
observer 观察者,参数为接收到的网络通话的挂断消息,参考AVChatCommonEvent
register 是否注册观察者,注册为 true, 注销为 false
AVChatManager.getInstance().observeHangUpNotification(callHangupObserver, register);
Observer<AVChatCommonEvent> callHangupObserver = new Observer<AVChatCommonEvent>() {
        @Override
        public void onEvent(AVChatCommonEvent hangUpInfo) {
            // 结束通话
        }
    };

通话断开

在收到对方结束通话回调时,在回调中需要进行通话断开操作来关闭音视频通话引擎和释放资源。

设置关闭预览stopVideoPreview详见开始和停止视频采集节,disableVideodisableRtc详见结束通话节。

     //如果是视频通话需要先调用结束预览和关闭视频接口
     if (callingState == CallStateEnum.OUTGOING_VIDEO_CALLING || callingState == CallStateEnum.VIDEO) {
            AVChatManager.getInstance().stopVideoPreview();
            AVChatManager.getInstance().disableVideo();
     }
     //关闭音视频通话底层引擎
     AVChatManager.getInstance().disableRtc();