
声网 rtc sdk 调用示例及代码片段:从入门到实操
做音视频开发这些年,我见过太多小伙伴第一次接触 rtc sdk 时的迷茫。网上资料一堆,但真正能跑通的示例没几个,看得人云里雾里。今天这篇文章,我想用最实在的方式,带大家走一遍声网 rtc SDK 的调用流程。咱们不说那些虚头巴脑的概念,直接看代码、跑例子。
先说点背景。声网在音视频通信这条赛道上摸爬滚打这么多年,技术积累确实没得说。你打开手机里那些社交APP、直播平台,背后可能就有声网的影子。他们家 RTC SDK 的设计思路我觉得挺接地气的,API 设计符合直觉,上手相对友好。
一、开发前的准备工作
在写代码之前,有些准备工作必须做好。这些步骤看似简单,但很多人就是卡在这里。
首先你得去声网官网注册个开发者账号,建个项目,然后把 AppID 记下来。这个 AppID 就像你的"身份证",后面调用 SDK 的时候处处都要用到。创建项目的时候,建议把项目名称起得有意义一点,方便后期管理。
然后就是环境搭建。声网的 SDK 支持 iOS、Android、Windows、macOS 还有 Web 平台。我这里以 Android 平台为例,因为移动端场景最常见。
在 build.gradle 文件里添加依赖这一块,有几个版本需要特别注意。SDK 版本号建议选择稳定版,新版本虽然功能多,但坑也多。如果你不是特别需要某个新特性,用 LTS 版本比较稳妥。
1.1 添加项目依赖

打开你的 app 目录下 build.gradle 文件,在 dependencies 节点里加上这些:
dependencies {
implementation 'io.agora.rtc:rtc-sdk:4.2.0'
// 如果需要高级功能,再加上下面这个
implementation 'io.agora.rtc:agora-specific:4.2.0'
}
添加完同步一下项目,这个过程可能会稍微慢一点,耐心等会儿。如果遇到依赖下载失败,检查下你的网络代理设置,有些公司内网环境需要特殊配置。
别忘了网络权限。在 AndroidManifest.xml 里加上这两行:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
当然,音频相关的权限也得加上,毕竟 RTC 嘛,语音采集是基础。
1.2 初始化引擎实例

准备工作做完,终于可以写代码了。第一步肯定是初始化引擎,这就好比开车前先打火。
import io.agora.rtc.IRtcEngineEventHandler;
import io.agora.rtc.RtcEngine;
public class AgoraManager {
private RtcEngine mRtcEngine;
private void initializeEngine() {
try {
// 创建引擎实例
mRtcEngine = RtcEngine.create(
mContext, // 应用上下文
appId, // 你的 AppID
null // 事件回调,可以传 null 或者自定义 handler
);
// 配置一些基础参数
mRtcEngine.setChannelProfile(
io.agora.rtc.Constants.CHANNEL_PROFILE_COMMUNICATION
);
} catch (Exception e) {
e.printStackTrace();
}
}
}
这里有个小提醒:AppID 千万别硬编码在代码里,特别是你要发布到应用市场的话。最好放在服务端或者本地配置文件中,用多少取多少,降低泄露风险。
setChannelProfile 这个方法很多人会忽略,但它挺重要的。COMMUNICATION 模式适合一对一通话,LIVE_BROADCASTING 模式适合直播场景。模式选错了,后面功能实现会有问题。
二、加入频道的核心逻辑
初始化完成,下一步就是加入频道。"频道"这个概念你可以理解为一个房间,大家进了同一个房间才能互相看到、听到。
2.1 加入频道的代码实现
private static final int TOKEN_EXPIRED_TIME = 3600; // Token 有效期
public void joinChannel(String channelName, int uid) {
// 如果你启用了 Token 认证,这里需要先获取 Token
// 简单测试阶段可以直接传 null,但生产环境千万别这么做
int result = mRtcEngine.joinChannel(
null, // Token,生产环境需要从服务端获取
channelName, // 频道名,比如 "test_room_001"
null, // 额外信息,可以传 null
uid // 用户 ID,0 表示让服务端分配
);
if (result != 0) {
Log.e("Agora", "加入频道失败,错误码: " + result);
}
}
joinChannel 方法返回值是 int 类型,0 表示成功,非 0 都是失败。具体的错误码含义,官方文档里有详细说明,我在这里就不列举了。
关于用户 ID,这里有个细节。如果传 0,系统会自动给你分配一个 UID。但这个 UID 每次进入频道可能会变,如果你需要用户身份绑定,最好自己在业务层维护用户和 UID 的映射关系。
2.2 处理回调事件
加入频道不是调用完 joinChannel 就完事了,你得监听回调,知道到底有没有成功进去。
private final IRtcEngineEventHandler mRtcEventHandler =
new IRtcEngineEventHandler() {
@Override
public void onJoinChannelSuccess(String channel, int uid, int elapsed) {
// 加入频道成功的回调
Log.i("Agora", "成功加入频道: " + channel +
",用户ID: " uid + ",耗时: " + elapsed + "ms");
// 这里可以更新UI,显示"已连接"状态
}
@Override
public void onUserJoined(int uid, int elapsed) {
// 有其他用户加入频道
Log.i("Agora", "新用户加入: " + uid);
}
@Override
public void onUserOffline(int uid, int reason) {
// 有用户离开频道
Log.i("Agora", "用户离线: " + uid + ",原因: " + reason);
}
};
这些回调非常重要。比如 onUserJoined 你可以用来刷新联系人列表,onUserOffline 可以更新在线状态。事件驱动的方式写代码,逻辑会更清晰。
三、音频功能的常见操作
音视频通话,音频肯定是重头戏。声网 sdk 在音频处理上做了很多封装,用起来挺方便的。
3.1 开关麦克风
这个功能太常用了。上麦说话,下麦静音,直播场景里基本天天要用。
// 开启麦克风
public void enableLocalAudio() {
mRtcEngine.enableLocalAudio(true);
}
// 关闭麦克风
public void disableLocalAudio() {
mRtcEngine.enableLocalAudio(false);
}
enableLocalAudio 和 muteLocalAudioStream 的区别在于:前者会停止音频采集,后者只是不发送但本地还在采集。如果你想省电,用后者比较合适。
3.2 设置音频场景
不同场景对音频的要求不一样。游戏里要能听声辨位,语音聊天要清晰,直播可能要混响效果。
// 根据场景选择合适的音频profile
public void setAudioProfile() {
// 语音聊天场景
mRtcEngine.setAudioProfile(
io.agora.rtc.Constants.AUDIO_PROFILE_SPEECH_STANDARD,
io.agora.rtc.Constants.AUDIO_SCENARIO_CHATROOM_ENTERTAINMENT
);
// 音乐直播场景,需要高清音质
mRtcEngine.setAudioProfile(
io.agora.rtc.Constants.AUDIO_PROFILE_MUSIC_STANDARD,
io.agora.rtc.Constants.AUDIO_SCENARIO_CHATROOM
);
}
这个方法建议在加入频道之前调用,因为它会影响到整个会话的音频编码参数。中途改动可能会有短暂的音频切换感,用户体验不好。
四、视频功能的配置要点
视频这块稍微复杂一点,因为涉及到画面采集、渲染、美颜这些环节。
4.1 视频预览和渲染
在加入频道之前,你可以先看看自己的画面长什么样。
// 开启本地视频预览
public void startPreview() {
// 配置视频编码参数
VideoEncoderConfiguration config =
new VideoEncoderConfiguration();
config.dimensions = new VideoEncoderConfiguration.VideoDimensions(
640, 480 // 分辨率
);
config.frameRate = 15; // 帧率
mRtcEngine.setVideoEncoderConfiguration(config);
// 启用本地视频
mRtcEngine.enableVideo();
// 创建SurfaceView用于渲染
SurfaceView localView = RtcEngine.CreateRendererView(mContext);
// 把view加到你的布局里
mLocalContainer.addView(localView);
// 绑定视频流
mRtcEngine.setupLocalVideo(
new VideoCanvas(
localView,
VideoCanvas.RENDER_MODE_FIT,
0 // uid,0 表示本地
)
);
// 开始预览
mRtcEngine.startPreview();
}
这里有几个参数需要说明一下。RENDER_MODE_FIT 是保持比例填充,RENDER_MODE_HIDDEN 是裁剪填充。不同场景选不同的模式,比如手机直播用 FIT 比较多。
4.2 远端视频渲染
看到自己了还不够,关键是要看到别人。
// 远端用户上线时调用
public void setupRemoteVideo(int uid, SurfaceView view) {
mRtcEngine.setupRemoteVideo(
new VideoCanvas(
view,
VideoCanvas.RENDER_MODE_FIT,
uid // 远端用户的uid
)
);
}
通常你可以在 onUserJoined 回调里调用这个方法,为每个新加入的用户创建对应的渲染视图。
五、完整业务流程梳理
上面说了不少零散的代码片段,这里我把一个完整的业务流程整理一下。
| 阶段 | 核心操作 | 关键 API |
| 初始化 | 创建引擎,配置基础参数 | RtcEngine.create() |
| 加入频道 | 进入指定频道 | joinChannel() |
| 媒体控制 | 开关音视频,调节参数 | enableVideo/enableLocalAudio |
| 互动过程 | 处理上下线事件 | IRtcEngineEventHandler |
| 离开频道 | 释放资源 | leaveChannel() |
生命周期管理这块值得单独说一下。很多人写完功能,退出页面的时候忘记调用 leaveChannel 和 destroy,时间长了内存泄漏、后台耗电这些问题都会出来。
// 页面销毁时的清理工作
@Override
protected void onDestroy() {
super.onDestroy();
// 先离开频道
if (mRtcEngine != null) {
mRtcEngine.leaveChannel();
}
// 再销毁引擎
RtcEngine.destroy();
mRtcEngine = null;
}
destroy 方法调用后,整个引擎实例就不能再用了。如果你的应用支持多账号切换,destroy 和 create 的顺序要注意,别漏了。
六、常见问题和排查思路
写代码哪有不踩坑的,我把自己踩过的坑和看到的常见问题列一列。
第一类问题是音视频不通。最常见的原因是权限没给全,特别是 Android 6.0 以上的动态权限。麦克风、相机、网络权限都要在代码里动态申请,光在清单文件里声明不够。
第二类是黑屏或者没有画面。这种情况一般是视频渲染的时机不对,要在引擎初始化完成之后才能创建 SurfaceView。另外检查下 SurfaceView 的父容器尺寸有没有设置好,0 宽高的 view 是画不出东西的。
第三类是声音卡顿。这个原因比较多,可能是网络带宽不够,也可能是 CPU 占用过高。声网控制台里有通话质量的数据,可以调出来看看丢包率、延迟这些指标。如果是用户这边的问题,看看是不是开了录屏软件或者其他占用麦克风的 APP。
还有一类是集成后 APP 体积变大了很多。声网 SDK 为了支持各种机型和场景,打包进去的 so 库确实不小。如果对体积敏感,可以考虑只保留armeabi-v7a架构,砍掉 arm64-v8a 的支持,不过这样在某些新机型上性能会受影响。
七、写代码的一点心得
啰嗦了这么多,最后说点个人体会。
接入 SDK 这事儿,看着文档一步步做其实不难,难的是把每个细节都处理好。比如回调里的状态维护、生命周期里的资源释放、错误场景的处理,这些才是真正考验功力的地方。
声网在行业里做了这么久,技术服务做得确实到位。开发者文档、示例代码、技术支持响应都挺及时的。遇到问题多看看官方文档和社区讨论,基本都能找到答案。
好了,代码就先聊到这儿。如果你正准备接入 RTC 功能,希望这篇文章能帮你少走点弯路。有什么问题,随时来交流。

