本文介绍如何使用声网 RDC Windows SDK 快速实现远程控制功能。
声网为远程控制提供示例项目源码,请联系技术支持获取。
实现远程控制的步骤如下:
joinChannel
创建并加入频道。使用同一频道名称的 app 客户端默认加入同一频道。App 客户端加入频道需要以下信息:
参考以下步骤创建一个 Windows 项目。若已有 Windows 项目,直接查看集成 SDK。
RDC-Test
,选择项目存储路径,并点击确认。libs
目录中。在解决方案资源管理器窗口中,右击项目名称并点击属性进行以下配置,配置完成后点击确定。
在 C/C++ > 常规 > 附加包含目录点击编辑,并在弹出窗口中输入 $(SolutionDir)libs\agora_rdc_sdk\include;$(SolutionDir)libs\agora_rtc_sdk\include
。
在链接器 > 常规 > 附加库目录点击编辑,并在弹出窗口中输入 $(SolutionDir)libs\agora_rdc_sdk\$(PlatformTarget);$(SolutionDir)libs\agora_rtc_sdk\$(PlatformTarget)
。
进入链接器 > 输入 > 附加依赖项菜单,点击编辑,并在弹出窗口中依次输入 agora_rtc_sdk.lib
和 agora_rdc_sdk.lib
。
参考如下步骤,实现远程控制。远程控制的 API 使用时序见下图:
RDC-TestDlg.h
文件中,引入头文件及声明变量。#include <IAgoraRtcEngine.h> // 引入声网 RTC SDK
#include <IAgoraRDCEngine.h> // 引入声网 RDC SDK
#define DEFAULT_CHANNEL_ID "channelId" // 填写频道名称
#define DEFAULT_APP_ID "appId" // 填写你的项目在声网控制台中生成的 App ID
#define HOST_USER "rdc_host" // 填写主控端 userID
#define CONTROLLED_USER "rdc_controlled" // 填写被控端 userID
agora::rtc::IRtcEngine* g_lpEngine = nullptr; // 声明 RTC 对象指针
agora::rc::IRemoteControlEngine* g_lpRDCEngine = nullptr; // 声明 RDC 对象指针
// 声明 RTC 回调类
class CRDCTestDlg
: public agora::rtc::IRtcEngineEventHandler
, public agora::rc::IRemoteControlEventHandler
{
public:
CRDCTestDlg(CWnd* pParent = nullptr); // 声明构造函数
protected:
// IRtcEngineEventHandler overrides
void onJoinChannelSuccess(const char* channel, agora::rtc::uid_t userId, int elapsed) override;
void onError(int err, const char* msg) override;
void onWarning(int warn, const char* msg) override;
void onLeaveChannel(const agora::rtc::RtcStats& stats) override;
void onUserJoined(uid_t uid, int elapsed) override;
void onStreamMessage(uid_t uid, int streamId, const char* data, size_t length) override;
// IRemoteControlEventHandler overrides
void onEvent(agora::rc::RDC_EVENT event, int code, const char* msg) override;
......
private:
BOOL m_bHost; // 当前用户是否为主控端
CString m_szUserId; // 当前用户 userID
};
// 声明 RDC 回调类
void CRDCTestDlg::onEvent(agora::rc::RDC_EVENT event, int code, const char* msg) override {
switch(event) {
// 登录成功回调
case agora::rc::EVT_LOGIN:
if (code != 0) {
... // 登录失败处理逻辑
} else {
... // 登录成功处理逻辑
}
break;
// 登出成功回调
case agora::rc::EVT_LOGOUT:
if (code != 0) {
// 登出失败处理逻辑
} else {
// 登出成功处理逻辑
}
break;
// 发生错误回调
case agora::rc::EVT_ERROR:
// TRACE("[RDC] err:%d, message:%s", code, msg);
break;
// 其他 RDC 回调
......
}
}
RDC-TestDlg.cpp
文件中,同时实现远程控制主控端和被控端的具体逻辑。// 实现构造函数
CRDCTestDlg::CRDCTestDlg(CWnd* pParent /*=nullptr*/) {
if (MessageBox(L"当前用户是主控端吗?", L"设置角色", MB_YESNO | MB_ICONQUESTION)) {
m_bMaster = TRUE;
} else {
m_bMaster = FALSE;
}
}
// 初始化 RTC SDK 服务,并加入频道
int CRDCTestDlg::initAndLoginRTC() {
// 创建 RtcEngine 对象
g_lpEngine = createAgoraRtcEngine();
// 声明 Context,用于初始化
agora::rtc::RtcEngineContext ctx;
ctx.appId = DEFAULT_APP_ID;
// 声明 RTC 事件回调
ctx.eventHandler = reinterpret_cast<agora::rtc::IRtcEngineEventHandler*>(this);
//初始化 RtcEngine 引擎
g_lpEngine->initialize(ctx);
// 被控端发布屏幕流,主控端订阅被控端的屏幕流
if (!g_bMaster) {
g_lpEngine->setClientRole(agora::rtc::CLIENT_ROLE_BROADCASTER);
g_lpEngine->enableAudio();
g_lpEngine->enableVideo();
// 被控端根据需要分享屏幕或窗口到对端,详见互动直播的《屏幕共享》文档
g_lpEngine->startScreenCaptureByScreenRect(...);
} else {
g_lpEngine->setClientRole(agora::rtc::CLIENT_ROLE_AUDIENCE);
g_lpEngine->disableAudio();
g_lpEngine->disableVideo();
}
// 加入频道
if (g_lpEngine->joinChannel(NULL, DEFAULT_CHANNEL_ID, NULL, 0) != 0) {
//报错:登录频道失败
return -1;
}
return 0;
}
// 初始化 RDC SDK 服务并登录 RDC 系统,主控端显示被控端桌面的窗口句柄
int CRDCTestDlg::initAndLoginRDC(HWND hWnd) {
// 创建 RDCEngine 对象
g_lpRDCEngine = createRDCEngine();
// 准备配置类
agora::rc::Configuration config;
config.appId = DEFAULT_APP_ID;
// 声明 RDC 事件回调
config.eventHandler =
reinterpret_cast<agora::rc::IRemoteControlEventHandler*>(this);
// 将远程控制视图窗口句柄传到 RDCEngine
config.hwnd = hWnd;
// 传入用户角色
config.role = g_bMaster ? agora::rc::HOST : agora::rc::CONTROLLED
if (g_lpRDCEngine->initialize(config) != 0) {
// 报错:初始化失败
return -1001;
}
if (g_lpRDCEngine->login(DEFAULT_USER_ID, NULL) != 0) {
// 报错:登录 RDC 系统失败
return -1002;
}
return 0;
}
// 初始化 RDCEngine
void CRDCTestDlg::onJoinChannelSuccess(const char* channel,
agora::rtc::uid_t userId,
int elapsed) {
if (!g_lpRDCEngine) {
initAndLoginRDC(GetSafeHwnd());
}
}
// 当对端也进入频道后,开始渲染对端桌面
void CRDCTestDlg::onUserJoined(agora::rtc::uid_t uid, int elapsed) {
// 如果用户角色是主控端,则开始渲染对端视频
if (m_bMaster) {
agora::rtc::VideoCanvas vc;
vc.renderMode = agora::rtc::RENDER_MODE_FILL;
vc.uid = uid;
vc.view = g_hWnd;
g_lpEngine->setupRemoteVideo(vc);
}
}
完成项目后,在 Windows 设备中运行该项目。运行成功后,你会看到登录界面。
为保障通信安全,在正式生产环境中,你需要在自己的 app 服务端生成 Token。由于声网 RDC SDK 使用声网 RTM 的信令服务,因此登录声网 RDC 系统等同于登录声网 RTM 系统,并使用 RTM Token 鉴权机制,详见使用 RTM Token 鉴权。