Android 快速开始与功能指南
Android:前置条件、安装、Token、加入频道、发布订阅、事件、错误处理与排障;接口名与签名在构建时取自公开 SDK 接口定义。
Android 端是原生引擎形状:RtcEngine 单例 + IRtcEngineEventHandler 回调,而不是 Web 端的 track 对象模型。发布/订阅由 joinChannel 的 ChannelMediaOptions 与 muteLocal* 系列方法控制。
前置条件
- JDK 17、Android SDK 35、Gradle 8.x。
- Min SDK:见库 manifest(采集与屏幕共享用到 MediaProjection,需要 API 21+)。
- 宿主 App 需要在运行时申请
CAMERA、RECORD_AUDIO(库只声明,不代申请)。 - 已拿到
appId与 Token 服务(见 控制台开通服务与获取凭证)。
安装
dependencies {
implementation(project(":sdk:android")) // 代码库中
// 计划 Maven 坐标:implementation("com.nimeet.rtc:nimeet-rtc:0.1.0")
}获取 Token
Android 客户端不能持有 customerSecret。推荐让宿主 App 的后端签发,客户端通过 CallbackTokenProvider(委托给你的登录态接口)或 EndpointTokenProvider(开发期直连,不要把 secret 打进 APK)获取:
val tokenProvider = FallbackTokenProvider(listOf(
CallbackTokenProvider { channel, uid, role -> yourBackend.getRtcToken(channel, uid, role) },
StaticTokenProvider(BuildConfig.NIMEET_TEST_TOKEN), // 仅测试
))加入频道
class MeetingActivity : AppCompatActivity() {
private var rtc: RtcEngine? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
rtc = RtcEngine.create(this, BuildConfig.NIMEET_APP_ID, object : IRtcEngineEventHandler() {
override fun onJoinChannelSuccess(channel: String?, uid: Int, elapsed: Int) {
runOnUiThread { statusText.text = "已加入频道" }
}
override fun onUserJoined(uid: Int, elapsed: Int) {
runOnUiThread { addTile(uid) }
}
override fun onUserOffline(uid: Int, reason: Int) {
runOnUiThread { removeTile(uid) }
}
override fun onTokenPrivilegeWillExpire(token: String?) {
rtc?.renewToken(fetchFreshToken())
}
})
rtc?.apply {
setChannelProfile(Constants.CHANNEL_PROFILE_LIVE_BROADCASTING)
enableVideo()
setupLocalVideo(VideoCanvas(localView))
startPreview()
joinChannel(BuildConfig.RTC_TOKEN, "weekly-sync", "", 10001)
}
}
}joinChannel 有 4 个重载:(token, channelId, optionalInfo, uid)、(token, channelId, uid, options)、(token, channelId, userAccount, options) 等, 完整清单与参数类型见同端 API 参考(构建时从 公开 SDK 接口定义 生成)。
发布与订阅
原生端没有 publish(track):入会后默认按 ChannelMediaOptions 发布摄像头/麦克风,用方法控制开关。
// 静音 / 关摄像头(保持发布能力)
rtc?.muteLocalAudioStream(true)
rtc?.muteLocalVideoStream(true)
// 停止/恢复本地视频采集
rtc?.enableLocalVideo(false)
// 只订阅音频(观众端省流量)
val options = ChannelMediaOptions().apply {
autoSubscribeAudio = true
autoSubscribeVideo = false
clientRoleType = Constants.CLIENT_ROLE_AUDIENCE
}
rtc?.updateChannelMediaOptions(options)事件
回调接口是 IRtcEngineEventHandler(84 个 on* 方法)。常用的一组:
| 回调 | 何时触发 | 典型处理 |
|---|---|---|
onJoinChannelSuccess(channel, uid, elapsed) | 入会成功 | 切 UI、开始计时 |
onUserJoined(uid, elapsed) | 远端用户加入 | 分配画面容器 |
onFirstRemoteVideoDecoded(uid, width, height, elapsed) | 远端首帧解码 | 渲染远端画面 |
onUserOffline(uid, reason) | 远端离开 | 释放容器 |
onTokenPrivilegeWillExpire(token) | 权限将过期 | 续期后 renewToken |
onError(err) | 运行时错误 | 按错误号分流 |
onConnectionStateChanged(state, reason) | 连接状态变化 | RECONNECTING 时不要释放资源 |
错误处理
- 同步方法返回
int:0成功,负值是声网错误号(例如-2参数非法、-110Token 无效)。必须检查返回值。 - 异步错误通过
onError回调返回。 - 未实现的能力返回
-4(ERR_NOT_SUPPORTED),不会静默成功。
val code = rtc?.joinChannel(token, channel, "", uid) ?: -3
if (code < 0) {
showError(RtcError.fromCode(code)) // sdk/ 的 RtcError 会给出 code/sdkCode/message/retryable
}排障
| 现象 | 原因 | 处理 |
|---|---|---|
joinChannel 返回 -2 | 频道名非法或 uid 越界 | 频道名 [A-Za-z0-9_-],uid 1..2147483647 |
返回 -110 | Token 无效/频道不匹配 | 用 GET /v1/tokens/verify 自查 |
| 有声音无画面 | 未 enableVideo() 或未 setupLocalVideo | 按上面的顺序调用,并确保 startPreview() |
| 屏幕共享黑屏 | 未启动 MediaProjection 前台服务 | 走宿主 App 的 MediaProjection 授权流程 |
| 退到后台后断流 | 应用被系统固定 | 使用前台服务;不要依赖后台保活 |
UnsatisfiedLinkError | ABI 不匹配 | 检查 abiFilters 与 so 包 |
下一步
平台信息
| 项 | 值 |
|---|---|
| 平台 | Android |
| 语言 | Kotlin |
| SDK 包 | com.nimeet.rtc |
| 接口版本 | 4.7.0 |
| 兼容参考 | 声网 android 端 API |
本端公开接口与声网 android 端 API 对齐;安装与运行要求见上面前置条件。
可用性
该端 SDK:正式可用。本页代码片段使用公开 API;运行时的能力边界以实际发布的 SDK 包为准。
加入频道链路
下列方法名、参数类型与返回值与同端 API 参考一致。一个平台若有多个重载,这里展示最常用的那一个;完整重载见同端 API 参考页。
| 步骤 | 接口 | 方法 | 重载数 |
|---|---|---|---|
| 创建实例 / 初始化 | IAgoraMusicContentCenter | initialize | 1 |
| 续期 Token | IAgoraMusicContentCenter | renewToken | 1 |
| 订阅远端媒体 | IBaseSpatialAudioEngine | muteRemoteAudioStream | 1 |
| 开启视频与本地预览 | RtcEngine | enableVideo | 1 |
| 加入频道 | RtcEngine | joinChannel | 2 |
| 离开频道 | RtcEngine | leaveChannel | 2 |
| 频道场景 | RtcEngine | setChannelProfile | 1 |
| 切换角色 | RtcEngine | setClientRole | 2 |
| 绑定本地画面 | RtcEngine | setupLocalVideo | 1 |
initialize(configuration: MusicContentCenterConfiguration): int
renewToken(token: String): int
muteRemoteAudioStream(uid: int, mute: boolean): int
enableVideo(): int
joinChannel(token: String, channelId: String, optionalInfo: String, uid: int): int
leaveChannel(): int
setChannelProfile(profile: int): int
setClientRole(role: int): int
setupLocalVideo(local: VideoCanvas): int事件与回调
回调注册在 IRtcEngineEventHandler 上;不同端的命名可能不同,完整清单见同端 API 参考页。
| 回调 | 签名 | 用途 |
|---|---|---|
onConnectionStateChanged | onConnectionStateChanged(state: int, reason: int): void | 入会结果 / 连接状态变化:据此更新 UI 并决定是否重连。 |
onUserJoined | onUserJoined(uid: int, elapsed: int): void | 远端用户加入:分配画面容器。 |
onFirstRemoteVideoDecoded | onFirstRemoteVideoDecoded(uid: int, width: int, height: int, elapsed: int): void | 远端视频状态:首帧解码后即可渲染。 |
onUserOffline | onUserOffline(uid: int, reason: int): void | 远端用户离开:释放容器与订阅。 |
onRequestToken | onRequestToken(): void | Token 即将过期:调用服务端续期后 `renewToken`。 |
onError | onError(err: int): void | 运行时错误:`err` 为声网错误号,按错误码表分流。 |
onNetworkQuality | onNetworkQuality(uid: int, txQuality: int, rxQuality: int): void | 网络质量:上报到水晶球或提示用户。 |
错误码
| 常量 | 值 |
|---|---|
AUTHENTICATION_FAILED | 5 |
INVALID_ARGUMENT | 2 |
INVALID_OPERATION | 3 |
NETWORK_ERROR | 4 |
OK | 0 |
STREAM_NOT_FOUND | 6 |
平台 REST 层用 REST 错误码;SDK 层把连接/鉴权失败映射成声网错误号,映射表见 各端 SDK 错误标识。