Android
这页只覆盖客户端单端视角,目标是尽快跑通“引用 SDK -> 初始化 -> 连接并播放”。
前置条件
环境要求
| 项目 | 要求 |
|---|---|
| Android 版本 | Android 5.0(API Level 21)及以上 |
| 支持架构 | arm64-v8a |
compileSdk | 35 |
1. 引用 SDK
先在 settings.gradle.kts 配置 Maven 仓库:
kotlin
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven {
url = uri("http://repo-sdk.tange-ai.com/repository/maven-public/")
isAllowInsecureProtocol = true
credentials {
username = providers.gradleProperty("TIRTC_PUBLIC_MAVEN_USERNAME").orElse("tange_user").get()
password = providers.gradleProperty("TIRTC_PUBLIC_MAVEN_PASSWORD").orElse("tange_user").get()
}
}
}
}再在 app 模块加入依赖:
kotlin
dependencies {
implementation("com.tange.ai:tirtc-av:<latest-version>")
}版本号从Android SDK 发布说明获取。
2. 初始化 SDK
在创建 TiRtcConn、TiRtcAudioOutput、TiRtcVideoOutput 之前,先初始化一次:
kotlin
class DemoApp : Application() {
override fun onCreate() {
super.onCreate()
TiRtc.initialize(applicationContext)
}
}3. 连接并播放
这份 quick start 按“连上就发”策略保持最短路径。如果你的设备端采用“收到订阅再发”,连接进入 CONNECTED 后再调用 conn.subscribeAudio(streamId = audioStreamId)、conn.subscribeVideo(streamId = videoStreamId),页面离开前再调用 conn.unsubscribeAudio(streamId = audioStreamId)、conn.unsubscribeVideo(streamId = videoStreamId)。
先准备一个视频容器:
xml
<FrameLayout
android:id="@+id/remote_video_container"
android:layout_width="match_parent"
android:layout_height="240dp" />然后按 Activity 生命周期处理播放。
kotlin
class PlayerActivity : AppCompatActivity() {
private companion object {
const val TAG = "TiRtcQuickStart"
}
private val remoteId = "your-remote-id"
private val token = "v1.xxxxxx" // got from backend
private val audioStreamId = yourAudioStreamId
private val videoStreamId = yourVideoStreamId
// 打印基础状态,便于先定位黑屏、无声或断连。
private val conn = TiRtcConn().apply {
onStateChanged = { state ->
Log.i(TAG, "conn state=$state")
}
onDisconnected = { code ->
Log.i(TAG, "conn disconnected code=$code")
}
onError = { code ->
Log.e(TAG, "conn error code=$code")
}
}
private val audioOutput = TiRtcAudioOutput().apply {
onStateChanged = { state ->
Log.i(TAG, "audio state=$state")
}
onError = { code ->
Log.e(TAG, "audio error code=$code")
}
}
private val videoOutput = TiRtcVideoOutput().apply {
onStateChanged = { state ->
Log.i(TAG, "video state=$state")
}
onRenderSizeChanged = { size ->
Log.i(TAG, "video size=${size.width}x${size.height}")
}
onError = { code ->
Log.e(TAG, "video error code=$code")
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_player)
// 绑定画面渲染容器。
videoOutput.attachView(findViewById(R.id.remote_video_container))
}
override fun onResume() {
super.onResume()
// 绑定要播放的远端音视频流,再发起连接。
audioOutput.attach(conn, audioStreamId)
videoOutput.attach(conn, videoStreamId)
val code = conn.connect(remoteId = remoteId, token = token)
if (code != 0) {
Log.e(TAG, "connect request failed code=$code")
}
}
override fun onPause() {
super.onPause()
// 页面不可见时先停播断连。
audioOutput.detach()
videoOutput.detach()
conn.disconnect()
}
override fun onDestroy() {
super.onDestroy()
// 页面销毁时释放对象。
videoOutput.detachView()
audioOutput.release()
videoOutput.release()
conn.release()
}
}