12 KiB
SellyRTC Android SDK 接入文档
本文档用于指导 Android App 开发者 快速接入 SellyRTC,完成一对一或多人实时音视频通话能力。
SDK 核心以 InteractiveRtcEngine 为中心,通过 InteractiveRtcEngineEventHandler 回调通话状态、用户事件、音视频状态及异常。
目录
- 准备工作
- 快速开始
- 基础通话流程
- 常用功能
- 屏幕分享
- 视频帧前后处理
- 事件回调(EventHandler)
- 通话统计
- Token 机制
- 代理地址配置
- 常见问题(FAQ)
准备工作
1. 环境要求
- Android 8.0+(Demo
minSdk为 26) - 需真机运行(摄像头 / 麦克风)
2. 权限配置(AndroidManifest.xml)
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
快速开始
1. SDK 初始化
在使用音视频通话功能前,需先初始化 SDK:
SellyCloudManager.initialize(
context = applicationContext,
appId = "your-app-id"
)
initialize的appId参数为权威值。可选传入SellyCloudConfig配置vhost、logEnabled等,详见推拉流文档。
2. 代理地址设置(可选)
若需通过代理(如洋葱盾)连接信令服务器,在创建引擎前设置:
SellyCloudManager.setProxyAddress("http://127.0.0.1:12345")
SDK 内部通过代理地址解析真实信令服务器 IP。不设置则使用直连。详见「代理地址配置」章节。
3. 创建引擎
val appId = getString(R.string.signaling_app_id)
val token = getString(R.string.signaling_token).takeIf { it.isNotBlank() }
val rtcEngine = InteractiveRtcEngine.create(
InteractiveRtcEngineConfig(
context = applicationContext,
appId = appId,
defaultToken = token
)
).apply {
setEventHandler(eventHandler)
setClientRole(InteractiveRtcEngine.ClientRole.BROADCASTER)
setVideoEncoderConfiguration(
InteractiveVideoEncoderConfig(
width = 640,
height = 480,
fps = 20,
minBitrateKbps = 150,
maxBitrateKbps = 850
)
)
setDefaultAudioRoutetoSpeakerphone(true)
}
InteractiveRtcEngineConfig 参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
context |
Context | 应用上下文 |
appId |
String | 应用 ID |
defaultCallType |
CallType | 默认通话类型,默认 ONE_TO_ONE |
defaultToken |
String? | 默认 Token |
signalingUrlPrefix |
String | 信令 URL 前缀,默认 ws:// |
signalingUrlSuffix |
String | 信令 URL 后缀,默认 /ws/signaling |
完整 Demo 见
example/src/main/java/com/demo/SellyCloudSDK/interactive/InteractiveLiveActivity.kt。
4. 设置本地/远端画布
val localRenderer = SurfaceViewRenderer(this)
rtcEngine.setupLocalVideo(InteractiveVideoCanvas(localRenderer, userId))
val remoteRenderer = SurfaceViewRenderer(this)
rtcEngine.setupRemoteVideo(InteractiveVideoCanvas(remoteRenderer, remoteUserId))
5. 加入通话
val options = InteractiveChannelMediaOptions(callType = CallType.ONE_TO_ONE)
rtcEngine.joinChannel(
token = token,
channel = callId,
userId = userId,
options = options,
tokenSecret = tokenSecret,
tokenExpiresAtSec = tokenExpiresAtSec,
tokenTtlSeconds = tokenTtlSeconds
)
结束通话:
rtcEngine.leaveChannel()
销毁引擎:
InteractiveRtcEngine.destroy(rtcEngine)
6. 进阶配置(Demo 未覆盖)
6.1 InteractiveChannelMediaOptions 订阅控制
val options = InteractiveChannelMediaOptions(
callType = CallType.GROUP,
autoSubscribeAudio = true,
autoSubscribeVideo = false
)
6.2 InteractiveVideoEncoderConfig 更多参数
可选项(按需设置):
codecType:编码类型bitrateMode:码率控制模式minBitrateKbps/maxBitrateKbps:码率范围orientationMode:画面方向策略degradationPreference:弱网降级策略mirrorMode:镜像策略
基础通话流程
- 初始化 SDK(
SellyCloudManager.initialize) - 设置代理地址(可选,
SellyCloudManager.setProxyAddress) - 创建
InteractiveRtcEngine - 设置
EventHandler - 配置
InteractiveVideoEncoderConfig - 设置本地画布
setupLocalVideo joinChannel加入频道onUserJoined后设置远端画布- 通话中进行音视频控制
leaveChannel并释放资源
常用功能
本地音视频控制
rtcEngine.enableLocalVideo(true)
rtcEngine.enableLocalAudio(false)
切换摄像头
rtcEngine.switchCamera()
音频输出(扬声器 / 听筒)
rtcEngine.setDefaultAudioRoutetoSpeakerphone(true)
发送自定义消息
rtcEngine.sendMessage("hello") { error ->
// error == null 表示成功
}
按用户静音远端音频/视频
rtcEngine.muteRemoteAudioStream(remoteUserId, true)
rtcEngine.muteRemoteVideoStream(remoteUserId, true)
全量静音远端音视频(Demo 未覆盖)
rtcEngine.muteAllRemoteAudioStreams(true)
rtcEngine.muteAllRemoteVideoStreams(true)
清理远端画布(Demo 未覆盖)
rtcEngine.clearRemoteVideo(remoteUserId)
向指定用户发送消息(Demo 未覆盖)
rtcEngine.sendMessage("hello", targetUserId) { error ->
// error == null 表示成功
}
屏幕分享
val started = rtcEngine.startScreenShare(
resultCode = resultCode,
data = data,
width = 720,
height = 1280,
fps = 15
)
rtcEngine.stopScreenShare()
val isSharing = rtcEngine.isScreenSharing()
Android 14+ 屏幕捕获需要前台服务(Demo 使用
InteractiveForegroundService处理)。
视频帧前后处理
rtcEngine.setCaptureVideoFrameInterceptor { frame ->
// 在此处理美颜/滤镜,返回新的 frame
frame
}
rtcEngine.setRenderVideoFrameInterceptor { frame, userId ->
// 远端渲染前处理,返回 true 表示继续渲染
true
}
Demo 中的美颜示例见:
example/src/main/java/com/demo/SellyCloudSDK/beauty/FuVideoFrameInterceptor.kt
事件回调(EventHandler)
val eventHandler = object : InteractiveRtcEngineEventHandler {
override fun onJoinChannelSuccess(channel: String, userId: String, code: Int) {}
override fun onLeaveChannel(durationSeconds: Int) {}
override fun onUserJoined(userId: String, code: Int) {}
override fun onUserLeave(userId: String, code: Int) {}
override fun onConnectionStateChanged(state: InteractiveConnectionState, reason: Int, userId: String?) {}
override fun onMessageReceived(message: String, userId: String?) {}
override fun onError(code: String, message: String) {}
override fun onTokenWillExpire(token: String?, expiresAt: Long) {}
override fun onTokenExpired(token: String?, expiresAt: Long) {}
override fun onLocalVideoStats(stats: InteractiveStreamStats) {}
override fun onRemoteVideoStats(stats: InteractiveStreamStats) {}
override fun onDuration(durationSeconds: Long) {}
override fun onRemoteVideoEnabled(enabled: Boolean, userId: String?) {}
override fun onRemoteAudioEnabled(enabled: Boolean, userId: String?) {}
override fun onStreamStateChanged(peerId: String, state: RemoteState, code: Int, message: String?) {}
}
通话统计
InteractiveStreamStats 常用字段:
- width / height
- fps
- videoBitrateKbps / audioBitrateKbps
- rttMs
- videoCodec / audioCodec
Token 机制
Token 来源
- 业务侧服务端生成 Token 并下发
- Demo 可在
strings.xml配置signaling_token或signaling_secret进行本地生成
Token 过期处理
onTokenWillExpire/onTokenExpired回调提示即将过期或已过期- 建议获取新 Token 并 重新 joinChannel
Token 续期接口(Demo 未覆盖):
rtcEngine.renewToken(newToken, expiresAtSec)
代理地址配置
SDK 支持通过外部代理(如洋葱盾等安全加速服务)连接信令服务器。代理地址由业务方在 SDK 外部获取,然后注入 SDK。
设置方式
// 设置代理地址(在 joinChannel 之前)
SellyCloudManager.setProxyAddress("http://127.0.0.1:12345")
// 清除代理(恢复直连)
SellyCloudManager.setProxyAddress(null)
// 查询当前代理地址
val proxy = SellyCloudManager.getProxyAddress() // null 表示未设置
格式要求
- 必须以
http://或https://开头 - 传
null或空字符串表示清除代理 - 格式不合法时抛出
IllegalArgumentException
生效范围
设置后,SDK 内部通过代理地址解析真实信令服务器 IP,对上层接口透明。
时机要求
- 必须在
joinChannel()之前 设置 - 通话过程中修改代理地址,需
leaveChannel后重新joinChannel才能生效
Demo 中的接入示例
Demo 使用 KiwiHelper 封装洋葱盾的初始化与代理获取,采用三阶段模式:
// 阶段 1:Application.onCreate() 异步初始化
KiwiHelper.initializeAsync()
// 阶段 2:Activity 初始化时启动代理获取(非阻塞)
KiwiHelper.startProxySetup(enableKiwi = true, rsName = "your-rs-name")
// 阶段 3:joinChannel 前确保代理已就绪
lifecycleScope.launch {
KiwiHelper.awaitProxyReady()
rtcEngine.joinChannel(...)
}
KiwiHelper内部通过SellyCloudManager.setProxyAddress()将代理地址传给 SDK。 详见example/src/main/java/com/demo/SellyCloudSDK/KiwiHelper.kt。
更多 API 速览(含 Demo 未覆盖)
引擎创建与销毁:
InteractiveRtcEngine.create(config):创建引擎InteractiveRtcEngine.destroy(engine)/engine.destroy():释放引擎
SDK 初始化与代理:
SellyCloudManager.initialize(context, appId, config):初始化 SDKSellyCloudManager.setProxyAddress(address):设置代理地址SellyCloudManager.getProxyAddress():获取当前代理地址
通话控制:
setEventHandler(handler):设置事件回调setClientRole(role):设置角色(主播/观众)setVideoEncoderConfiguration(config):设置编码参数setDefaultAudioRoutetoSpeakerphone(true/false):设置音频输出joinChannel(...)/leaveChannel():加入 / 离开频道
本地与远端控制:
setupLocalVideo(canvas)/setupRemoteVideo(canvas):设置画布clearRemoteVideo(userId):清理远端画面enableLocalVideo(true/false)/enableLocalAudio(true/false):开关本地音视频muteRemoteAudioStream(userId, true/false)/muteRemoteVideoStream(userId, true/false):按用户静音muteAllRemoteAudioStreams(true/false)/muteAllRemoteVideoStreams(true/false):全量静音switchCamera():切换摄像头
帧处理与屏幕共享:
setCaptureVideoFrameInterceptor(...):采集前帧处理setRenderVideoFrameInterceptor(...):渲染前帧处理startScreenShare(...)/stopScreenShare()/isScreenSharing():屏幕共享
消息与 Token:
sendMessage(message, targetUserId, callback):发送消息(targetUserId可为空)renewToken(newToken, expiresAtSec):续期 Token
常见问题(FAQ)
Q:远端画面不显示?
- 是否设置了正确的
remoteUserId - 是否在
onUserJoined后调用setupRemoteVideo - 远端是否关闭了视频
Q:加入频道失败?
- 检查
signaling_app_id是否正确 - Token 是否为空或已过期
- 网络是否受限
- 若使用代理,检查代理地址是否已正确设置
Q:屏幕分享失败?
- 是否已获取
MediaProjection授权 - Android 14+ 是否启动前台服务
Q:如何接入代理/加速服务?
SDK 本身不集成任何第三方代理 SDK。业务方需在外部完成代理初始化,获取本地代理地址后,通过 SellyCloudManager.setProxyAddress() 注入。详见「代理地址配置」章节。