SDK集成

本场景需要集成火山引擎的RTC SDK 以及SUD MGP 互动小游戏接入平台,您需要在 RTC 的控制台开通服务,并下载对应的SUD MGP 的SDK,相应开通指南如下:

RTC SDK 接入

详细细节请参见 RTC服务开通指南

alt

小游戏 SDK 接入
整体实现流程

alt


核心功能实现
房主创建游戏房以及观众加入游戏房流程:
时序图

alt

示例代码
/**
  * 加入RTC房间并初始化参数 
  * @param token 加入 RTC 房间的 token
  * @param roomId 加入 RTC 房间的 id
  * @param userId 加入 RTC 房间的 用户id
  */
 public static void joinRoom(String token, String roomId, String uid) {
     MLog.d("joinChannel", "token:" + token + " roomId:" + roomId + " uid:" + uid);
     leaveRoom();
     if (mRTCVideo  == null) {
         return;
     }
     mRTCRoom  = mRTCVideo.createRTCRoom(roomId);
     mRTCRoom.setRTCRoomEventHandler(mRTCRoomEventHandler);
     UserInfo userInfo = new UserInfo(uid, null);
     RTCRoomConfig roomConfig = new RTCRoomConfig(ChannelProfile.CHANNEL_PROFILE_COMMUNICATION,
             true, true, true);
     mRTCRoom.joinRoom(token, userInfo, roomConfig);
}
 /**
  * 初始化SudMGP sdk
  *
  * @param activity 游戏所在页面
  * @param gameId   游戏id
  * @param code     令牌
  */
 private void initSdk(FragmentActivity activity, long gameId, String code) {
     String appId = getAppId();
     String appKey = getAppKey();
     // 初始化sdk
     SudMGP.initSDK(activity, appId, appKey, isTestEnv(), new ISudListenerInitSDK() {
         @Override
         public void onSuccess() {
             loadGame(activity, code, gameId);
         }

         @Override
         public void onFailure(int errCode, String errMsg) {
             if (isTestEnv()) {
                 Toast.makeText(activity, "initSDK onFailure:" + errMsg + "(" + errCode + ")", Toast.LENGTH_LONG).show();
             }

             delayLoadGame(activity, gameId);
         }
     });
 }

 /**
  * 加载游戏
  * APP和游戏的相互调用
  * ISudFSTAPP:APP调用游戏的接口
  * ISudFSMMG:游戏调APP的响应回调
  *
  * @param activity 游戏所在页面
  * @param code     登录令牌
  * @param gameId   游戏id
  */
 private void loadGame(FragmentActivity activity, String code, long gameId) {
     if (activity.isDestroyed() || !isRunning || gameId != playingGameId) {
         return;
     }

     // 给装饰类设置回调
     sudFSMMGDecorator.setSudFSMMGListener(this);

     // 调用游戏sdk加载游戏
     ISudFSTAPP iSudFSTAPP = SudMGP.loadMG(activity, getUserId(), gameRoomId, code, gameId, getLanguageCode(), sudFSMMGDecorator);

     // 如果返回空,则代表参数问题或者非主线程
     if (iSudFSTAPP == null) {
         Toast.makeText(activity, "loadMG params error", Toast.LENGTH_LONG).show();
         delayLoadGame(activity, gameId);
         return;
     }

     // APP调用游戏接口的装饰类设置
     sudFSTAPPDecorator.setISudFSTAPP(iSudFSTAPP);

     // 获取游戏视图,将其抛回Activity进行展示
     // Activity调用:gameContainer.addView(view, FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
     gameView = iSudFSTAPP.getGameView();
     onAddGameView(gameView);
 }
 
 /**
  * 处理游戏视图信息(游戏安全区)
  * 文档:https://docs.sud.tech/zh-CN/app/Client/API/ISudFSMMG/onGetGameViewInfo.html
  */
 public void processOnGetGameViewInfo(View gameView, ISudFSMStateHandle handle) {
     //拿到游戏View的宽高
     int gameViewWidth = gameView.getMeasuredWidth();
     int gameViewHeight = gameView.getMeasuredHeight();
     if (gameViewWidth > 0 && gameViewHeight > 0) {
         notifyGameViewInfo(handle, gameViewWidth, gameViewHeight);
         return;
     }

     //如果游戏View未加载完成,则监听加载完成时回调
     gameView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
         @Override
         public void onGlobalLayout() {
             gameView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
             int width = gameView.getMeasuredWidth();
             int height = gameView.getMeasuredHeight();
             notifyGameViewInfo(handle, width, height);
         }
     });
 }

 /** 通知游戏,游戏视图信息 */
 private void notifyGameViewInfo(ISudFSMStateHandle handle, int gameViewWidth, int gameViewHeight) {
     GameViewInfoModel gameViewInfoModel = new GameViewInfoModel();
     gameViewInfoModel.ret_code = 0;
     // 游戏View大小
     gameViewInfoModel.view_size.width = gameViewWidth;
     gameViewInfoModel.view_size.height = gameViewHeight;

     // 游戏安全操作区域
     getGameRect(gameViewInfoModel);

     // 给游戏侧进行返回
     String json = SudJsonUtils.toJson(gameViewInfoModel);
     handle.success(json);
 }
java
观众请求上麦和房主拉观众上麦
观众请求上麦时序图

alt

房主拉观众上麦时序图

alt

示例代码
/**
 * 观众举手
 */
public void onCSRaiseHandsMicEvent(RaiseHandsMicEvent event) {
    mChatRoomAdapter.updateRaiseHandStatus(event.userId);
    mIsSomeoneRaiseHand = true;
    updateUI();
}

/**
 * 主动邀请上麦
 */
public void onCSInviteMicEvent(InviteMicEvent event) {
    if (!GameRoomDataManger.isSelf(event.userId)) {
        return;
    }
    if (mDialog != null) {
        mDialog.dismiss();
    }
    if (TextUtils.equals(event.userId, mUserId)) {
        CommonDialog dialog = new CommonDialog(this);
        dialog.setMessage("主播邀请您上麦");
        dialog.setPositiveListener(v -> {
            GameRoomRtmClient rtmClient = GameRoomRtcManager.getRtmClient();
            if (rtmClient != null) {
                rtmClient.confirmBecomeSpeaker();
            }
            dialog.dismiss();
        });
        dialog.setNegativeListener(v -> dialog.dismiss());
        dialog.show();
        mDialog = dialog;
    }
}

/**
 * 收到上麦邀请
 */
public void onCSInviteMicEvent(InviteMicEvent event) {
    if (!GameRoomDataManger.isSelf(event.userId)) {
        return;
    }
    if (mDialog != null) {
        mDialog.dismiss();
    }
    if (TextUtils.equals(event.userId, mUserId)) {
        CommonDialog dialog = new CommonDialog(this);
        dialog.setMessage("主播邀请您上麦");
        dialog.setPositiveListener(v -> {
            GameRoomRtmClient rtmClient = GameRoomRtcManager.getRtmClient();
            if (rtmClient != null) {
                rtmClient.confirmBecomeSpeaker();
            }
            dialog.dismiss();
        });
        dialog.setNegativeListener(v -> dialog.dismiss());
        dialog.show();
        mDialog = dialog;
    }
}

/**
 * 成功上麦通知
 */
public void onCSMicOnEvent(MicOnEvent event) {
    if (TextUtils.equals(event.user.userId, mUserId)) {
        if (!hasAudioPermission()) {
            SafeToast.show("麦克风权限已关闭,请至设备设置页开启");
            requestPermissions(Manifest.permission.RECORD_AUDIO);
        }
        showToast("您已经成功上麦", true);
        mIsSpeaker = true;
        mIsRaiseHand = false;
        switchMic(true);
    }
    mChatRoomAdapter.onUserRoleChange(event.user.userId, true);
    updateUI();
}

/**
 * 下麦通知
 */
public void onCSMicOffEvent(MicOffEvent event) {
    if (TextUtils.equals(event.userId, mUserId)) {
        showToast("您已回到听众席", true);
        mIsSpeaker = false;
        switchMic(false);
    }
    mChatRoomAdapter.onUserRoleChange(event.userId, false);
    updateUI();
}
c
核心功能 API 与回调参考
API
功能点API
创建 RTCVideo 对象createRTCVideo
创建 RTCRoom 对象createRTCRoom
设置用户可见性setUserVisibility
开启本地音频采集startAudioCapture
加入RTC房间joinRoom
离开房间leaveRoom
关闭内部音频采集stopAudioCapture
销毁 RTCRoom 对象destroy
功能点回调
本地用户加入 RTC 房间回调onRoomStateChanged
远端可见用户加入房间onUserJoined