本文介绍android下实时视频通话功能的实现流程,即构科技提供相关SDK接入和开放源码。

实时视频场景的典型使用之一是,同一会话中的多用户进行视频实时通话。

以 2 人间的实时视频为例,主要流程如下:
这里写图片描述
请注意:

1、上面流程中以2 名房间成员间的实时视频为例,实际上 Zego SDK 支持多人实时视频。建议开发者按需设计。

2、为了便于开发者更快理解 VideoTalk 中的逻辑,下述每节会将功能核心源码片段挑出来并加以讲解。开发者亦可直接阅读 VideoTalk 源码,两者是一致的。

一、 登录房间

用户间进行实时视频对话前,需要先登录到同一个房间。

VideoTalk 中登录相关源码片段演示如下,仅供参考:

GuestActivity.java

@Override
protected void doBusiness(Bundle savedInstanceState) {
    super.doBusiness(savedInstanceState);

    // 登陆房间
    showMainMsg(getString(R.string.start_to_login_room, mRoomID));
    recordLog(getString(R.string.myself, getString(R.string.start_to_login_room, mRoomID)));
    mZegoLiveRoom.loginRoom(mRoomID, ZegoConstants.RoomRole.Audience, new IZegoLoginCompletionCallback() {
        @Override
        public void onLoginCompletion(int errorCode, ZegoStreamInfo[] zegoStreamInfos) {
            if(errorCode == 0){
               //登陆成功处理
            }else {
               //登陆失败处理
            }
        }
    });
}

二、 开始视频通话

房间成员同意视频通话后,开始走推流、拉流流程,以推送己方画面和观看对方画面。

VideoTalk 中开始视频通话(即推流、拉流)相关源码片段演示如下,仅供参考:

BaseLiveActivity.java

/**
 * 开始发布.
 */
protected void startPublish() {
    // 6.0及以上的系统需要在运行时申请CAMERA RECORD_AUDIO权限
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED
                || ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{
                    Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO}, 101);
        } else {
            publishStream();
        }
    } else {
        publishStream();
    }
}

// 开启预览,同时推流
protected void publishStream() {
    if (TextUtils.isEmpty(mPublishStreamID)) {
        return;
    }

    ViewLive freeViewLive = getFreeViewLive();
    if (freeViewLive == null) {
        return;
    }

    // 设置流信息
    freeViewLive.setStreamID(mPublishStreamID);
    freeViewLive.setPublishView(true);

    // 输出发布状态
    recordLog(getString(R.string.myself, getString(R.string.start_to_publish_stream, mPublishStreamID)));

    // 开启流量自动控制
    int properties = ZegoConstants.ZegoTrafficControlProperty.ZEGOAPI_TRAFFIC_FPS
            | ZegoConstants.ZegoTrafficControlProperty.ZEGOAPI_TRAFFIC_RESOLUTION;
    mZegoLiveRoom.enableTrafficControl(properties, true);

    // 开始播放
    mZegoLiveRoom.setPreviewView(freeViewLive.getTextureView());
    mZegoLiveRoom.startPreview();
    mZegoLiveRoom.startPublishing(mPublishStreamID, mPublishTitle, 0);
    mZegoLiveRoom.setPreviewViewMode(ZegoVideoViewMode.ScaleAspectFill);
}

// 收到别人的推流,执行拉流观看
@Override
public void onStreamAdded(ZegoStreamInfo[] listStream, String roomID) {
    for (ZegoStreamInfo streamInfo : listStream) {
        recordLog(getString(R.string.someone_created_stream, streamInfo.userName, streamInfo.streamID));
        startPlay(streamInfo.streamID);
        // 存储流信息
        mMapStreamToUser.put(streamInfo.streamID, streamInfo.userName);
    }
}

/**
 * 开始播放流.
 */
protected void startPlay(String streamID) {

    if (isStreamExisted(streamID)) {
        Toast.makeText(this, getString(R.string.stream_existed, streamID), Toast.LENGTH_SHORT).show();
        recordLog(getString(R.string.stream_existed, streamID));
        return;
    }

    ViewLive freeViewLive = getFreeViewLive();
    if (freeViewLive == null) {
        return;
    }

    // 设置流信息
    freeViewLive.setStreamID(streamID);
    freeViewLive.setPlayView(true);

    // 输出播放状态
    recordLog(getString(R.string.myself, getString(R.string.start_to_play_stream, streamID)));

    // 播放
    mZegoLiveRoom.startPlayingStream(streamID, freeViewLive.getTextureView());
    mZegoLiveRoom.setViewMode(ZegoVideoViewMode.ScaleAspectFill, streamID);
}

三、结束视频通话

视频通话结束后的操作主要是停止推流、停止拉流、清理视图、登出房间等,开发者可按需调用。

VideoTalk 中结束视频通话相关源码片段演示如下,仅供参考:

BaseLiveActivity.java

// 用户点击停止按钮
protected void logout() {
    AlertDialog dialog = new AlertDialog.Builder(this).setMessage(getString(R.string.do_you_really_want_to_leave_the_chat_room)).setTitle(getString(R.string.hint)).setPositiveButton(getString(R.string.Yes), new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            stopAllStream();
            dialog.dismiss();
            finish();
        }
    }).setNegativeButton(getString(R.string.No), new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            dialog.dismiss();
        }
    }).create();

    dialog.show();
}

// 停止所有推拉流
protected void stopAllStream() {
    for (ViewLive viewLive : mListViewLive) {
        if (viewLive.isPublishView()) {
            stopPublish();
        } else if (viewLive.isPlayView()) {
            stopPlay(viewLive.getStreamID());
        }
        // 释放view
        viewLive.setFree();
    }
}

// 停止推流
protected void stopPublish() {
    if (mIsPublishing) {
        recordLog(getString(R.string.myself, getString(R.string.stop_publising_stream, mPublishStreamID)));

        mZegoLiveRoom.stopPreview();
        mZegoLiveRoom.stopPublishing();
        mZegoLiveRoom.setPreviewView(null);

        handlePublishStop(1, mPublishStreamID);
    }
}

// 停止拉流
protected void stopPlay(String streamID) {
    if (!TextUtils.isEmpty(streamID)) {
        recordLog(getString(R.string.myself, getString(R.string.stop_playing_stream, streamID)));

        mZegoLiveRoom.stopPlayingStream(streamID);

        handlePlayStop(1, streamID);
    }
}

四、 API 调用时序图
这里写图片描述

Logo

致力于链接即构和开发者,提供实时互动和元宇宙领域的前沿洞察、技术分享和丰富的开发者活动,共建实时互动世界。

更多推荐