Docs
Resources
Tools
News
to top

RCS

一对一通话

音视频呼叫回调注册

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    MtcCallCb.setCallback(this);
    ZmfVideo.addCallback(this);
}
@Override
protected void onDestroy() {
    super.onDestroy();
    MtcCallCb.setCallback(null);
    ZmfVideo.removeCallback(this);
}
//创建本地和远端图像预览
private void createVideoViews() {
    if (mRemoteView != null) return;
    
    Context context = getApplicationContext();
    FrameLayout.LayoutParams flp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
    //添加远端图像预览
    mRemoteView = ZmfVideo.renderNew(context);
    mRemoteView.setLayoutParams(flp);
    mViewMain.addView(mRemoteView, 0);
    ZmfVideo.renderStart(mRemoteView);
    //添加本地图像预览
    mLocalView = ZmfVideo.renderNew(context);
    mLocalView.setLayoutParams(flp);
    mLocalView.setZOrderMediaOverlay(true);
    mViewMain.addView(mLocalView, 1);
    ZmfVideo.renderStart(mLocalView);
    mLocalView.setVisibility(View.GONE);
}

//关闭相关设备,关闭视频渲染
private void destroyVideoViews() {
    //将这路视频通话从设备取消绑定
    MtcCall.Mtc_SessCameraDetach(dwSessId);
    //停止所有视频设备的录制
    ZmfVideo.captureStopAll();
    if (mLocalView != null) {
        ZmfVideo.renderRemoveAll(mLocalView);
        ZmfVideo.renderStop(mLocalView);
        mViewMain.removeView(mLocalView);
        mLocalView = null;
    }
    if (mRemoteView != null) {
        ZmfVideo.renderRemoveAll(mRemoteView);
        ZmfVideo.renderStop(mRemoteView);
        mViewMain.removeView(mRemoteView);
        mRemoteView = null;
    }
}

//设置音频模式
private void setCallMode() {
    if (mCallMode) return;
    mCallMode = true;
    //SDK根据设备寻找最适合的音频模式
    int mode = MtcMedia.Mtc_MdmGetAndroidAudioMode();
    if (mode != mAudioManager.getMode()) {
        mAudioManager.setMode(mode);
    }
    mAudioManager.requestAudioFocus(null, AudioManager.STREAM_VOICE_CALL, AudioManager.AUDIOFOCUS_GAIN);
    new AsyncTask() {
        
        @Override
        protected Void doInBackground(Void... params) {
            synchronized (CallActivity.this) {
                if (CallActivity.this.isCalling()) {
                    ZmfAudio.inputStart(MtcMedia.Mtc_MdmGetAndroidAudioInputDevice()/*获取录音设备*/, 0, 0,
                                        MtcMedia.Mtc_MdmGetOsAec() ? ZmfAudio.AEC_ON : ZmfAudio.AEC_OFF,
                                        MtcMedia.Mtc_MdmGetOsAgc() ? ZmfAudio.AGC_ON : ZmfAudio.AGC_OFF);
                    ZmfAudio.outputStart(MtcMedia.Mtc_MdmGetAndroidAudioOutputDevice(), 0, 0);
                }
            }
            return null;
        }
        
    }.execute();
}

//清除通话相关设置
private void clearCallMode() {
    mCallMode = false;
    if (mAudioManager == null) {
        return;
    }
    synchronized (this) {
        ZmfAudio.inputStopAll();
        ZmfAudio.outputStopAll();
    }
    mAudioManager.abandonAudioFocus(null);
    if (AudioManager.MODE_NORMAL != mAudioManager.getMode()) {
        mAudioManager.setMode(AudioManager.MODE_NORMAL);
    }
}

//设置扬声器方式
private void setSpeakerphoneOn(bool mHasVideo) {
    AudioManager mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
    mAudioManager.setSpeakerphoneOn(mHasVideo);
}

发起音视频呼叫

if (isVideo) {
    createVideoViews();
}
setCallMode();

String phoneNumbwe = "+8618605745829";
String uri = MtcUri.Mtc_UriFormatX(phoneNumber, false);
MtcCall.Mtc_SessCall(uri, 0, true, isVideo);

注:isVideo 判断是否是视频呼叫。

呼叫成功后会依次触发以下回调:

public void mtcCallCbOutgoing(int dwSessId) {
    //通话记录插入数据库
    //设置扬声器方式
    setSpeakerphoneOn(mHasVideo);
    if (mHasVideo) {
        //若为视频呼叫,则开启本地视频预览
        MtcNumber width = new MtcNumber();
        MtcNumber height = new MtcNumber();
        MtcNumber framerate = new MtcNumber();
        //通过菊风MDM模块获取适合的长度、宽度、帧速率
        MtcMedia.Mtc_MdmGetCaptureParms(width, height, framerate);
        ZmfVideo.captureStart(mCapture, width.getValue(), height.getValue(), framerat.getValue());
        
        mLocalView.setVisibility(View.VISIBLE);
        ZmfVideo.renderAdd(mLocalView, ZmfVideo.CaptureFront, 0, ZmfVideo.RENDER_FULL_SCREEN);
        //将这路视频通话绑定到设备
        MtcCall.Mtc_SessCameraAttach(mCurSessId, ZmfVideo.CaptureFront);
    }
}

public void mtcCallCbAlerted(int dwSessId, int dwAlertType) {
//开始响铃,界面显示振铃中
}

音视频呼叫来电

当接到电话时,会触发以下回调:

public void mtcCallCbIncoming(int dwSessId) {
    //获取来电号码,插入数据库
    MtcString ppcDispName = new MtcString();
    MtcString ppcUri = new MtcString();
    MtcCall.Mtc_SessGetPeerId(dwSessId, ppcDispName, ppcUri);
    String number = MtcUri.Mtc_UriGetUserPart(ppcUri.getValue());
    
    //判断来电是否为视频通话
    boolean mHasVideo = MtcCall.Mtc_SessPeerOfferVideo(dwSessId);
    
    //界面刷新显示来电,并开始响铃,若为视频通话,则开启本地预览
    if (mHasVideo) {
        createVideoViews();
        //若为视频呼叫,则开启本地视频预览
        MtcNumber width = new MtcNumber();
        MtcNumber height = new MtcNumber();
        MtcNumber framerate = new MtcNumber();
        //通过菊风MDM模块获取适合的长度、宽度、帧速率
        MtcMedia.Mtc_MdmGetCaptureParms(width, height, framerate);
        ZmfVideo.captureStart(mCapture, width.getValue(), height.getValue(), framerat.getValue());
        
        mLocalView.setVisibility(View.VISIBLE);
        //开始本地图像预览
        ZmfVideo.renderAdd(mLocalView, ZmfVideo.CaptureFront, 0, ZmfVideo.RENDER_FULL_SCREEN);
        //将这路视频通话绑定到设备
        MtcCall.Mtc_SessCameraAttach(mCurSessId, ZmfVideo.CaptureFront);
    }
}

接听音视频呼叫

setCallMode();
MtcCall.Mtc_SessAnswer(dwSessId, 0, true, isVideo);

双方触发以下回调:

public void mtcCallCbTalking(int dwSessId) {
    // 更新数据库状态
    // 判断来电是否为视频通话
    if (MtcCall.Mtc_SessHasVideo(dwSessId)) {
        MtcCall.Mtc_SessVideoStart(dwSessId);
        //开始远端图像预览
        ZmfVideo.renderAdd(mRemoteView, MtcCall.Mtc_SessGetName(dwSessId), 0, ZmfVideo.RENDER_AUTO);
    }
}

取消音视频呼叫

//主动挂断
//第二个参数(定义于 MtcConstants),主动挂断的状态码只能选择以下三种之一:
//EN_MTC_CALL_TERM_STATUS_NORMAL    正常挂断
//EN_MTC_CALL_TERM_STATUS_BUSY      正忙
//EN_MTC_CALL_TERM_STATUS_DECLINE   拒接
MtcCall.Mtc_SessTerm(dwSessId, MtcCallConstants.MTC_CALL_TERM_NORMAL);

对方收到回调:

public void mtcCallCbTermed(int dwSessId, int dwStatCode) {
    // dwStatCode为结束通话的状态码,根据 dwStatCode 判断终止原因,更新数据库状态
    //  MTC_CALL_TERM_BYE = (0xE200+21); /**< @brief Terminated by bye. */
    //  MTC_CALL_TERM_CANCEL = (0xE200+22); /**< @brief Terminated by cancel. */
    //  MTC_CALL_TERM_TIMEOUT = (0xE200+23); /**< @brief Terminated by timeout. */
    //  MTC_CALL_TERM_BUSY = (0xE200+24); /**< @brief Terminated by busy. */
    //  MTC_CALL_TERM_DECLINE = (0xE200+25); /**< @brief Terminated by decline. */
    //  MTC_CALL_TERM_TRSFED = (0xE200+26); /**< @brief Terminated by transfered. */
    //  MTC_CALL_TERM_REDIRECT = (0xE200+27); /**< @brief Terminated by redirect. */
    //  MTC_CALL_TERM_REPLACE = (0xE200+28); /**< @brief Terminated by replace. */
    
    //  EN_MTC_CALL_TERM_REASON_NORMAL      对方正常通话中挂断
    //  EN_MTC_CALL_TERM_REASON_BUSY        对方正忙
    //  EN_MTC_CALL_TERM_REASON_DECLINE     对方拒接
    //  EN_MTC_CALL_TERM_REASON_NOT_AVAILABLE     暂时不可用

    destroyVideoViews();
    
    clearCallMode();
}

监听视频图像开始渲染的回调

@Override
public void renderDidStart(SurfaceView zView, int iSource, String iRender,
                           int iWidth, int iHeight) {
    // 检测本地或远端图像是否开始渲染
    if (zView == mLocalView) {
    } else if (zView == mRemoteView) {
        // 样例,如果远端视频开始渲染,则缩小本地图像预览
        MtcNumber localWidth = new MtcNumber();
        MtcNumber localHeight = new MtcNumber();
        MtcCall.Mtc_SessGetVideoLocalSize(mCurSessId, localHeight, localWidth);
        if (mLocalView.getWidth() == localWidth.getValue() && mLocalView.getHeight() == localHeight.getValue()) {
            return;
        }
        int screenWidth = mViewMain.getWidth();
        int screenHeight = mViewMain.getHeight();
        //计算本地预览图像等比例缩小后的尺寸
        ST_MTC_RECT localRect = MtcVideo.calcLocalRect(localWidth.getValue(),
                                                       localHeight.getValue(), screenWidth, screenHeight);
        MtcVideo.setViewRect(mLocalView, localRect);
        
    }
}

监听音视频通话信号回调

public void mtcCallCbNetStaChanged(int dwSessId, boolean bVideo, boolean bSend, int iType) {
    // 如果信号断开,则主动结束通话
    if (iType == MtcCallConstants.EN_MTC_NET_STATUS_DISCONNECTED) {
        MtcCall.Mtc_SessTerm(dwSessId, MtcCall.EN_MTC_CALL_TERM_REASON_NORMAL);
    }
}

监听音视频通话RTP流回调

public void mtcCallCbSetRtpConnectivity(int dwSessId, boolean bConnected) {
    // 如果RTP流已断开,则主动结束通话
    if (mCurSessId == dwSessId && !bConnected) {
        MtcCall.Mtc_SessTerm(dwSessId, MtcCall.EN_MTC_CALL_TERM_REASON_NORMAL);
    }
}
Juphoon © 2015 中文(简体)
关于我们 JusTalk 开发人员 招聘 隐私政策