实时语音通话能够拉近人与人之间的距离,为用户提供沉浸式的交流体验,帮助你的 app 提高用户黏性。
本文介绍如何通过少量代码集成 Agora SDK 并调用 API,在你的应用中实现高质量、低延迟的语音通话功能。
下图展示在 app 中实现声网语音通话的基本工作流程:
实现语音通话的步骤如下:
1. 设置角色
将用户角色均设置为主播。
2. 加入频道
调用 joinChannel
创建并加入频道。在 App ID 一致的前提下,传入相同频道名的用户会进入同一个频道。
3、4. 在频道内发布和订阅音频
加入频道后,两位主播可以发布音频并互相订阅。
Microsoft Visual Studio 2017 或以上版本
Windows 7 或以上版本的设备
C++ 11 或以上版本
有效的声网账户(免费注册)
计算机可以访问互联网。请确保你的网络环境未部署防火墙,否则可能无法正常使用声网服务。
一个有效的声网账号以及声网项目。请参考 开始使用声网平台 从声网控制台获得以下信息:
参考以下操作,在你的 app 中实现语音通话功能:
参考创建 C++ 控制台应用项目,在 Visual Studio 上创建一个 C++ 控制台应用项目。
参考以下步骤将声网 SDK 集成到你的项目中。
sdk
文件夹中的所有子文件夹复制到你的解决方案文件夹下。保证这些子文件夹和你的 sln
文件处于同一目录。在解决方案资源管理器窗口中,右击项目名称并点击属性进行以下配置,配置完成后点击确定。
$(SolutionDir)include
。$(SolutionDir)lib
。agora_rtc_sdk.dll.lib
。本节介绍如何使用声网 SDK 在你的 app 中实现语音通话功能。API 的调用时序见下图:
创建用户界面
为直观地体验语音通话,需根据应用场景创建用户界面(UI)。若项目中已有用户界面,直接查看初始化 IRtcEngine。
如果你想实现一个语音通话,推荐在 UI 上添加以下控件:
如下界面可供你参考:
初始化 IRtcEngine
在调用其他声网 API 前,需要创建并初始化 IRtcEngine
对象。
调用 createAgoraRtcEngine
方法和 initialize
方法并传入 App ID,初始化 IRtcEngine
。
你也可以根据需求,在初始化时实现其他功能,如注册用户加入频道和离开频道的回调。
// 创建一个 IRtcEngine 实例。
m_lpAgoraEngine = createAgoraRtcEngine();
RtcEngineContext ctx;
// 添加注册回调和事件。
ctx.eventHandler = &m_engineEventHandler;
// 输入你的 App ID。你可以在声网控制台获取你的项目的 App ID。
ctx.appId = "Your App ID";
// 初始化 IRtcEngine。
m_lpAgoraEngine->initialize(ctx);
// 继承 IRtcEngineEventHandler 类中的回调与事件。
class CAGEngineEventHandler :
public IRtcEngineEventHandler
{
public:
CAGEngineEventHandler();
~CAGEngineEventHandler();
void setMainWnd(HWND wnd);
HWND GetMsgReceiver() {return m_hMainWnd;};
// 注册 onJoinChannelSuccess 回调。
// 本地用户成功加入频道时,会触发该回调。
virtual void onJoinChannelSuccess(const char* channel, uid_t uid, int elapsed);
// 注册 onLeaveChannel 回调。
// 本地主播成功离开频道时,会触发该回调。
virtual void onLeaveChannel(const RtcStats& stat);
// 注册 onUserJoined 回调。
// 远端主播成功加入频道时,会触发该回调。
virtual void onUserJoined(uid_t uid, int elapsed) override;
// 注册 onUserOffline 回调。
// 远端主播离开频道或掉线时,会触发该回调。
virtual void onUserOffline(uid_t uid, USER_OFFLINE_REASON_TYPE reason);
private:
HWND m_hMainWnd;
};
加入频道
设置频道场景和用户角色,并使用临时 token 加入频道。
void CLiveBroadcastingDlg::OnBnClickedButtonJoinchannel()
{
if (!m_rtcEngine || !m_initialize)
return;
CString strInfo;
if (!m_joinChannel) {
CString strChannelName;
m_edtChannelName.GetWindowText(strChannelName);
if (strChannelName.IsEmpty()) {
AfxMessageBox(_T("Fill channel name first"));
return;
}
ChannelMediaOptions options;
// 将频道场景设置为 LIVE_BROADCASTING
options.channelProfile = CHANNEL_PROFILE_LIVE_BROADCASTING;
// 设置用户角色为主播
options.clientRoleType = CLIENT_ROLE_TYPE(m_cmbRole.GetCurSel() + 1);
options.autoSubscribeAudio = true;
// 使用你在声网控制台生成的临时 token 加入频道,在这里传入你的项目的 token 和频道名。
if (0 == m_rtcEngine->joinChannel(APP_TOKEN, szChannelId.c_str(), 0, options)) {
strInfo.Format(_T("join channel %s, use ChannelMediaOptions"), getCurrentTime());
m_btnJoinChannel.EnableWindow(FALSE);
}
}
else {
if (0 == m_rtcEngine->leaveChannel()) {
strInfo.Format(_T("leave channel %s"), getCurrentTime());
m_btnJoinChannel.EnableWindow(FALSE);
}
}
m_lstInfo.InsertString(m_lstInfo.GetCount(), strInfo);
}
离开频道
根据场景需要,如结束通话、关闭 App 或 App 切换至后台时,调用 leaveChannel
离开当前通话频道。
void CLiveBroadcastingDlg::UnInitAgora()
{
if (m_rtcEngine) {
if(m_joinChannel)
// 离开频道
m_rtcEngine->leaveChannel();
m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("leaveChannel"));
// 释放 IRtcEngine.
m_rtcEngine->release(true);
m_lstInfo.InsertString(m_lstInfo.GetCount(), _T("release rtc engine"));
m_rtcEngine = NULL;
}
}
在测试或生产环境中,为确保通信安全,声网推荐使用 token 服务器来生成 token,详见使用 Token 鉴权。