帮你快速理解、总结文档立即下载

Android

最近更新时间:2026-09-23 17:57:06
我的收藏
本文将介绍如何快速接入音视频通话 Demo。您可以在 10 分钟内完成以下关键步骤,并最终体验一个包含完备 UI 界面的 1v1 视频交友功能。


快速接入

为方便您快速上线,您可以直接集成 Demo 中的 UI 组件完成 1v1 聊天、通话等核心功能 。

步骤 1: 集成组件

1. 从 GitHub 仓库下载 VideoChat Demo 源码,并拷贝 video-chat 和 tuikit 组件复制到您的工程目录下:

2. 在 settings.gradle 中添加以下代码,完成功能接入。
// 引入上层应用模块
include ':app'

// 引入 1v1 视频交友界面模块
include ':video-chat'

// 引入公共模块
include(":atomic_x")
project(":atomic_x").projectDir = file("./tuikit/atomic_x")

// 引入会话模块
include ':chat'
project(':chat').projectDir = file("./tuikit/chat")

// 引入美颜功能模块
include ':tebeautykit'
project(':tebeautykit').projectDir = file("./tuikit/tebeautykit")

// 引入特效播放器模块
include ':tceffectplayerkit'
project(':tceffectplayerkit').projectDir = file("./tuikit/tceffectplayerkit")

步骤 2: 完成登录

登录鉴权后才能正常使用组件的功能。调用 LoginStore 的 login 接口,传入上文获取的 sdkAppID、userID、userSig 进行登录鉴权:

import io.trtc.tuikit.atomicxcore.api.CompletionHandler
import io.trtc.tuikit.atomicxcore.api.login.LoginStore

LoginStore.shared.login(
context,
sdkAppID, // Int,控制台获取
userID, // String
userSig, // String,控制台或服务端生成
object : CompletionHandler {
override fun onSuccess() {
// 登录成功,可跳转会话列表或聊天页
}
override fun onFailure(code: Int, desc: String) {
// 登录失败,可弹框报错
}
}
)
注意:
在正式的生产环境中,建议在您的服务端生成 UserSig,在需要时由 App 向业务服务器发起请求获取动态 UserSig 进行鉴权。详见 服务端生成 UserSig。

步骤 3: 构建推荐用户列表界面


1. 添加界面:在您的项目中添加 “推荐的人列表 (MeetPage)”:
import io.trtc.uikit.videochat.page.meet.MeetPage

class MeetPageFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
addMeetPage()
}
private fun addMeetPage() {
val meetPage = MeetPage(requireContext())
val container = findViewById<FrameLayout>(R.id.meet_container)
container.addView(meetPage, MATCH_PARENT, MATCH_PARENT)
}
}
2. 输入数据:您可以通过 setPageUsers 输入推荐用户列表,并监听上拉刷新(onLoadMoreRequested)在尾部追加用户数据、下拉刷新回调(onRefreshRequested)全量更新用户数据。
import io.trtc.uikit.videochat.page.meet.MeetPage

meetPage.setListener(object : MeetPage.Listener {
// 下拉刷新时触发该回调
override fun onRefreshRequested() {
// 全量更新用户列表
fetchUsers { users, hasMore ->
// 输入用户列表
meetPage.setPageUsers(users, hasMore)
}
}
// 上拉刷新时触发该回调。
override fun onLoadMoreRequested() {
// 尾部追加新用户列表
fetchNextPage { users, hasMore ->
// 输入用户列表
meetPage.setPageUsers(users, hasMore)
}
}
})
setPageUsers 详细说明:
fun setPageUsers(users: List<V2TIMUserFullInfo>, hasMore: Boolean)
参数
类型
说明
users
用户列表,V2TIMUserFullInfo 为包含用户的 ID、昵称、头像、性别等重要信息的结构体。
hasMore
Boolean
表示是否还有下一页:
true: 还有下一页,滚到底会继续触发 onLoadMoreRequested()
false:已无更多数据,滚到底不再触发回调
3. 切换布局(可选):MeetPage 提供了“卡片”和“列表”两种布局模式,您可以通过 setLayoutTemplate 选择您喜欢的布局。
import io.trtc.uikit.videochat.page.meet.MeetPage

class MeetPageFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
addMeetPage()
}
private fun addMeetPage() {
val meetPage = MeetPage(requireContext())
// 设置布局
meetPage.setLayoutTemplate(MeetPage.Template.LIST) // 设置布局为列表布局(默认)
// meetPage.setLayoutTemplate(MeetPage.Template.GRID) // 设置布局为卡片布局
val container = findViewById<FrameLayout>(R.id.meet_container)
container.addView(meetPage, MATCH_PARENT, MATCH_PARENT)
}
}
setLayoutTemplate 详细说明:
fun setLayoutTemplate(template: MeetPage.Template)
参数
类型
说明
template
MeetPage.Template
布局的类型:
MeetPage.Template.LIST :列表布局。
MeetPage.Template.GRID :卡片布局。

步骤 4: 构建会话列表界面

会话列表使用 ConversationPage,它会从数据库读取最近会话并展示列表。当用户点击某个会话时,通过 onConversationClick 回调把会话 ID 抛给您,由您决定跳转到聊天界面(聊天 Activity 位于您的 App 层,需由您注入)。

示例代码如下:
val conversationPage = ConversationPage().apply {
onConversationClick = { conversationID ->
ChatActivity.start(context, conversationID)
}
}

// R.id.container 为您的布局中容纳会话列表 Fragment 的 FrameLayout
supportFragmentManager.beginTransaction()
.add(R.id.container, conversationPage)
.commit()
说明:
onConversationClick 回调参数为完整的会话 ID,直接透传给聊天页即可,无需自行拼接。

步骤 5: 构建聊天界面

聊天界面用于展示和收发消息。您可以通过如下方法传入会话 ID 完成初始化。



示例代码如下:建议用一个 Activity 承载 ChatPageView,通过 Intent 把会话 ID 传入。
class ChatActivity : AppCompatActivity() {
private lateinit var chatPageView: ChatPageView

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val conversationID = intent.getStringExtra("conversationID") ?: run { finish(); return }

chatPageView = ChatPageView(this)
setContentView(chatPageView)

chatPageView.setup(
conversationID = conversationID,
onUserClick = { userID -> /* 可跳转用户资料页 */ }
)
}

companion object {
fun start(context: Context, conversationID: String) {
context.startActivity(
Intent(context, ChatActivity::class.java)
.putExtra("conversationID", conversationID)
)
}
}
}
如何获取 conversationID 打开聊天页:
方法一:从会话列表进入:会话 ID 由步骤 4 的 onConversationClick 回调直接返回,无需自己拼接,透传即可
onConversationClick = { conversationID -> ChatActivity.start(context, conversationID)}
方法二:从用户资料页 / 联系人 / 搜索结果进入:此时您手上只有对方的 userID(或群的 groupID),需按格式拼接会话 ID —— 单聊为 c2c_ + userID,群聊为 group_ + groupID:
// 打开与某用户的单聊
ChatActivity.start(context, "c2c_$userID")
// 打开某群聊
ChatActivity.start(context, "group_$groupID")

步骤 6: 音视频通话

在社交娱乐场景中,由于通话需求复杂多样,我们推荐您使用 AtomicxCore SDK 来灵活定制您的通话场景。以 video-chat 模块的通话界面(VideoCallPage)为例,它基于 SDK 的 CallStore 模块构建,内部已深度集成了美颜、关注操作以及对方信息展示等核心 UI 元素。您既可以将其作为源码参考,也可以直接接入项目中,从而快速搭建出专属的通话界面。

发起视频通话示例代码:您可通过 CallStore.calls 发起视频通话,并在成功回调中拉起通话界面。
// 通过 AtomicxCore SDK 的通话模块 CallStore.calls 发起视频通话。
CallStore.shared.calls(list, mediaType, params, object : CompletionHandler {
override fun onFailure(code: Int, desc: String) {
completion?.onFailure(code, desc)
}

override fun onSuccess() {
completion?.onSuccess()
// 通话成功,拉起 VideoCallPage 通话界面
val intent = Intent(context, VideoCallPage::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
context.startActivity(intent)
}
})
AtomicxCore SDK 通话模块核心 API 说明:
模块
功能描述
通话视图核心组件。自动监听 CallStore 数据并完成画面渲染,同时提供布局切换、头像与图标配置等 UI 定制化能力。
CallStore
通话生命周期管理:拨打电话、接通电话、拒接电话、挂断电话。实时获取参与通话人员音视频状态,通话计时、通话记录等数据。
音视频设备控制:麦克风(开关 / 音量)、摄像头(开关 / 切换 / 画质)、屏幕共享,设备状态实时监听。

更多功能

您可以接入以下功能提高您 App 的核心竞争力,为您的用户带来更佳体验。
功能
描述
接入文档
通话计费
我们为您提供了精准的服务端通话状态回调,您可以监听通话开始和通话结束的服务端回调完成通话计费功能。
接入美颜
我们提供了两种美颜特效方案:基础美颜(内置)和高级美颜(需额外集成和付费)。您可以根据自己的需求选择合适的方案。
接入美声
TRTC 音频美声功能的实现方法和应用场景,帮助开发者为用户打造丰富多彩的音频互动体验。
接入 AI 实时翻译
应用出海必备功能,帮助您为用户打破语言壁垒。
音视频内容审核
1v1 社交娱乐应用必备功能,帮助您审核音视频媒体流、文字内容信息是否违规,防止应用被下架。

常见问题

为什么 Demo 的美颜不生效?

Demo 默认集成了美颜功能,但需要 License 鉴权。请您检查 video-chat-solution/android/app/src/main/java/io/trtc/uikit/demo/debug/GenerateTestUserSig.java 中的 LicenseURL、LicenseKey 是否正确。获取可参考 License 指引。


如何自定义 UI ?

若您的 UI 定制需求极高,我们推荐您:
1. 通话模块:您可以使用 AtomicxCore SDK (示例代码可参考:无 UI 接入)完成通话模块的界面定制,其核心模块如下:
模块
说明
登录管理类,用于处理用户登录、登出及用户信息管理等业务逻辑。 LoginStore 提供了一套完整的登录管理 API,包括用户登录、登出、设置个人信息等功能。 通过该类,可以管理用户的登录状态和用户资料。
通话视图核心组件。自动监听 CallStore 数据并完成画面渲染,同时提供布局切换、头像与图标配置等 UI 定制化能力。
CallStore
通话生命周期管理:拨打电话、接通电话、拒接电话、挂断电话。实时获取参与通话人员音视频状态,通话计时、通话记录等数据。
音视频设备控制:麦克风(开关 / 音量)、摄像头(开关 / 切换 / 画质)、屏幕共享,设备状态实时监听。
2. 聊天互动模块可参考:IM SDK 无 UI 接入。

如何自定义聊天通话消息上屏?

当通话状态发生改变时,IM 将下发通话状态变更的消息,信令协议如下,根据您是否使用我们提供的 UI 代码,您可以有两种解决方案:
问题
说明
如何判断 “发起通话”
actionType = 1 且 cmd = 'videoCall' 或 'audioCall'
如何判断 “已接听”
actionType = 3
如何判断 “通话已结束”,“通话时长是多少”
actionType = 1 且 cmd = 'hangup',通话时长取 call_end 字段,单位:秒
如何判断 “取消通话”
actionType = 2
如何判断 “拒绝通话”
actionType = 4
如何判断对端忙线产生的 “拒绝通话”
actionType = 4 且 cmd = "line_busy"
如何被叫判断 “超时未接听”
actionType = 5
您可以设置 IM 消息监听器 实现通话状态消息上屏,示例代码如下:
// 设置消息监听器
V2TIMManager.getMessageManager().addAdvancedMsgListener(advancedMsgListener)

/**
* 收到新消息
* @param msg 消息
*/
override fun onRecvNewMessage(msg: V2TIMMessage) {
// 获取信令信息,非信令消息返回 null
val signalingInfo = V2TIMManager.getSignalingManager().getSignalingInfo(msg)
?: return

// 只处理 1v1 单聊(groupID 为空表示单聊,非空表示群聊)
if (!signalingInfo.groupID.isNullOrEmpty()) {
return
}

// 解析信令的 data 字段(JSON 格式)
val gson = Gson()
val jsonData: Map<String, Any> = try {
gson.fromJson(signalingInfo.data, object : TypeToken<Map<String, Any>>() {}.type)
} catch (e: Exception) {
return
}

// 校验 businessID,确认是通话信令消息
val businessId = jsonData["businessID"] as? String
if (businessId != "av_call" && businessId != "tuikit_calling") {
return
}

// 提取 data 子对象中的 cmd
val dataMap = jsonData["data"] as? Map<*, *>
val cmd = dataMap?.get("cmd") as? String

// 根据 actionType 判断通话状态
when (signalingInfo.actionType) {

// ========== actionType = 1:发起邀请 ==========
V2TIMSignalingInfo.SIGNALING_ACTION_TYPE_INVITE -> {
when (cmd) {
// 发起视频通话
"videoCall" -> {
val mediaType = "video"
Log.i(TAG, "发起通话 | 类型: $mediaType, 主叫: ${msg.sender}")
}
// 发起语音通话
"audioCall" -> {
val mediaType = "audio"
Log.i(TAG, "发起通话 | 类型: $mediaType, 主叫: ${msg.sender}")
}
// 挂断(通话结束)
"hangup" -> {
// 通话时长从顶层 call_end 字段获取,单位:秒
val duration = jsonData["call_end"]
?.toString()?.toDoubleOrNull()?.toInt() ?: 0
Log.i(TAG, "通话结束 | 时长: ${duration}秒")
}
}
}

// ========== actionType = 2:取消通话(主叫取消) ==========
V2TIMSignalingInfo.SIGNALING_ACTION_TYPE_CANCEL_INVITE -> {
Log.i(TAG, "通话已取消 | 主叫: ${msg.sender}")
}

// ========== actionType = 3:接听通话(被叫接受) ==========
V2TIMSignalingInfo.SIGNALING_ACTION_TYPE_ACCEPT_INVITE -> {
Log.i(TAG, "通话已接听")
}

// ========== actionType = 4:拒绝通话(被叫拒绝) ==========
V2TIMSignalingInfo.SIGNALING_ACTION_TYPE_REJECT_INVITE -> {
// 判断是否为忙线拒绝:顶层 JSON 包含 "line_busy" 字段
if (jsonData.containsKey("line_busy")) {
Log.i(TAG, "对方忙线拒绝")
} else {
Log.i(TAG, "通话被拒绝")
}
}

// ========== actionType = 5:超时未接听 ==========
V2TIMSignalingInfo.SIGNALING_ACTION_TYPE_INVITE_TIMEOUT -> {
Log.i(TAG, "超时未接听")
}
}
}

提高通话触达率?

1. 接入离线推送提高通话触达率:
中国大陆:接入 Notification
海外:接入 FCM
2. 提供推送控制:根据我们的经验,超过 90% 的用户接不到通话通知的原因是手动关闭了应用的通知权限。为确保通话可达率,我们强烈建议:
审慎发送通知:避免向用户推送低质量或无关联的通知,减少用户因骚扰而关闭通知权限的可能性。
提供精细控制:借鉴微信等优秀应用的做法,在应用设置内为用户提供独立的开关,分别控制“Notification”和“FCM Data Message”,而非引导用户去系统设置中一刀切地关闭所有通知。


联系我们

如果您在使用过程中,有什么建议或者意见,可以 联系我们,感谢您的反馈。