产品动态
产品近期公告
关于 TRTC Live 正式上线的公告
关于TRTC Conference 正式版上线的公告
Conference 商业化版本即将推出
关于多人音视频 Conference 开启内测公告
关于音视频通话 Call 正式版上线的公告
关于腾讯云音视频终端 SDK 播放升级及新增授权校验的公告
关于 TRTC 应用订阅套餐服务上线的相关说明

模块 | 功能描述 |
通话视图核心组件。自动监听 CallStore 数据并完成画面渲染,同时提供布局切换、头像与图标配置等 UI 定制化能力。 | |
通话生命周期管理:拨打电话、接通电话、拒接电话、挂断电话。实时获取参与通话人员音视频状态,通话计时、通话记录等数据。 | |
音视频设备控制:麦克风(开关 / 音量)、摄像头(开关 / 切换 / 画质)、屏幕共享,设备状态实时监听。 |
api "io.trtc.uikit:atomicx-core:latest.release" 和 api "com.tencent.imsdk:imsdk-plus:8.7.7201" 依赖,然后执行 Gradle Sync 。dependencies {api 'io.trtc.uikit:atomicx-core:latest.release'api "com.tencent.imsdk:imsdk-plus:8.7.7201"// 其他依赖...}

class MainActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)// CallStore 初始化CallStore.sharedval sdkAppId = 1400000001 // 替换为您的 SDKAppIDval userId = "test_001" // 替换为您的 UserIDval userSig = "xxxxxxxxxxx" // 替换为您的 UserSigLoginStore.shared.login(this,sdkAppId,userId,userSig,object : CompletionHandler {override fun onSuccess() {// 完成 TUICallEngine 的初始化TUICallEngine.createInstance(context).init(GenerateTestUserSig.SDKAPPID, userId, userSig, null)// 登录成功处理Log.d("Login", "login success");}override fun onFailure(code: Int, desc: String) {// 登录失败处理Log.e("Login", "login failed, code: $code, error: $desc");}})}}
参数 | 类型 | 说明 |
userId | String | 当前用户的唯一 ID,仅包含英文字母、数字、连字符和下划线。为避免多端登录冲突,请勿使用 1、123 等简单 ID。 |
sdkAppId | int | |
userSig | String | 用于腾讯云鉴权的票据。请注意: 开发环境:您可以采用本地 GenerateTestUserSig.genTestUserSig 函数生成 userSig 或者通过 UserSig 辅助工具 生成临时的 UserSig。 生产环境:为了防止密钥泄露,请务必采用服务端生成 UserSig 的方式。详细信息请参考 服务端生成 UserSig。 |
import io.trtc.tuikit.atomicxcore.api.view.CallCoreViewclass CallActivity : AppCompatActivity() {private var callCoreView: CallCoreView? = null// 1.创建通话页面容器override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)// 2.通话页面绑定 CallCoreViewcallCoreView = CallCoreView(this)setContentView(callCoreView)}}
功能 | 说明 | 参考文档 |
设置布局模式 | 支持自由切换布局模式。若未设置,将根据通话人数自动适配布局。 | |
设置头像 | 支持通过传入头像资源路径,为特定用户自定义头像。 | |
设置音量提示图标 | 支持根据不同音量等级,配置个性化的音量指示图标。 | |
设置网络提示图标 | 支持根据实时网络质量,配置对应的网络状态提示图标。 | |
设置等待接听用户的动画 | 在多人通话场景下,支持传入 GIF 路径,为待接听状态的用户展示动画。 |
import io.trtc.tuikit.atomicxcore.api.device.DeviceStoreimport io.trtc.tuikit.atomicxcore.api.call.CallStoreclass CallActivity : AppCompatActivity() {private var buttonContainer: LinearLayout? = nullprivate var buttonAccept: Button? = nullprivate var buttonReject: Button? = nulloverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)// 1.创建底部按钮栏容器createButtonContainer()// 2.添加"接听"与"拒接"按钮addRejectAndAcceptButtons()setContentView(buttonContainer)}// 创建底部按钮栏容器private fun createButtonContainer() {buttonContainer = LinearLayout(this).apply {orientation = LinearLayout.HORIZONTALgravity = Gravity.CENTERlayoutParams = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,FrameLayout.LayoutParams.WRAP_CONTENT).apply {gravity = Gravity.BOTTOMbottomMargin = dpToPx(80)}}}// 添加"接听"与"拒接"按钮private fun addRejectAndAcceptButtons() {createAcceptButton()createRejectButton()buttonContainer?.addView(buttonAccept)buttonContainer?.addView(buttonReject)}// 创建接听按钮private fun createAcceptButton() {buttonAccept = Button(this).apply {text = "接听"layoutParams = LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f).apply {marginEnd = dpToPx(8)}setOnClickListener {// 3.接听按钮点击事件绑定 acceptCallStore.shared.accept(null)}}}// 创建拒接按钮private fun createRejectButton() {buttonReject = Button(this).apply {text = "拒接"layoutParams = LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f).apply {marginStart = dpToPx(8)}setOnClickListener {// 3.拒接按钮点击事件绑定 rejectCallStore.shared.reject(null)}}}}
import io.trtc.tuikit.atomicxcore.api.call.CallEndReasonimport io.trtc.tuikit.atomicxcore.api.call.CallListenerimport io.trtc.tuikit.atomicxcore.api.call.CallMediaTypeimport io.trtc.tuikit.atomicxcore.api.call.CallStoreclass CallActivity : AppCompatActivity() {private var callListener: CallListener? = nulloverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)// ... 其他初始化代码// 1.通话结束事件监听addListener()}private fun addListener() {callListener = object : CallListener() {override fun onCallEnded(callId: String, mediaType: CallMediaType, reason: CallEndReason, userId: String) {// 2.通话结束关闭页面finish()}}callListener?.let { CallStore.shared.addListener(it) }}}
参数 | 类型 | 说明 |
callId | String | 此次通话的唯一标识。 |
mediaType | 通话媒体类型,用于指定发起音频通话还是视频通话。 CallMediaType.Video:视频通话。CallMediaType.Audio:语音通话。 | |
reason | 通话结束的原因。 Unknown:未知原因,无法确定结束原因。Hangup:正常挂断,用户主动挂断通话。Reject:拒绝接听,被叫方拒绝来电。NoResponse:无响应,被叫方未在超时时间内接听。Offline:对方离线,被叫方不在线。LineBusy:对方忙线,被叫方正在通话中。Canceled:通话取消,主叫方在对方接听前取消。OtherDeviceAccepted:其他设备已接听,通话已在另一登录设备上接听。OtherDeviceReject:其他设备已拒绝,通话已在另一登录设备上拒绝。EndByServer:服务器结束,通话被服务器终止。 | |
userId | String | 触发结束的用户 ID 。 |
AndroidManifest.xml 文件中声明应用需要的摄像头和麦克风权限。<manifest xmlns:android="http://schemas.android.com/apk/res/android"><!-- 麦克风权限 --><uses-permission android:name="android.permission.RECORD_AUDIO" /><!-- 摄像头权限 --><uses-permission android:name="android.permission.CAMERA" /><application><!-- ... --><activityandroid:name=".CallActivity"android:exported="false"android:screenOrientation="portrait" /></application></manifest>
// 动态申请权限private fun requestAllCallPermissions() {val allPermissions = arrayOf(Manifest.permission.CAMERA,Manifest.permission.RECORD_AUDIO)if (!checkPermissions(allPermissions)) {ActivityCompat.requestPermissions(this, allPermissions, PERMISSION_REQUEST_CODE)}}// 处理权限申请结果override fun onRequestPermissionsResult(requestCode: Int,permissions: Array<out String>,grantResults: IntArray) {super.onRequestPermissionsResult(requestCode, permissions, grantResults)if (requestCode == PERMISSION_REQUEST_CODE) {// 检查是否所有权限都已授予var allGranted = truefor (result in grantResults) {if (result != PackageManager.PERMISSION_GRANTED) {allGranted = falsebreak}}if (allGranted) {Log.d("MainActivity", "权限申请成功")} else {Log.w("MainActivity", "部分权限被拒绝")}}}
CallStore.observerState.selfInfo , 建立当前登录用户信息的响应式监听。SelfInfo.Status) 为等待接听状态(CallParticipantStatus.Waiting)播放铃声或振动,若当前用户的通话状态 (SelfInfo.Status) 为已接听状态(CallParticipantStatus.Accept)停止铃声或振动。import kotlinx.coroutines.CoroutineScopeimport kotlinx.coroutines.Dispatchersimport kotlinx.coroutines.Jobimport kotlinx.coroutines.launchclass MainActivity : AppCompatActivity() {private var stateJob: Job? = nulloverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)// 1.监听当前用户的通话状态observeSelfStatus()}// 监听当前用户的通话状态private fun observeSelfStatus() {stateJob = CoroutineScope(Dispatchers.Main).launch {CallStore.shared.observerState.selfInfo.collect { selfInfo ->// 2.播放/停止来电提示if (selfInfo.status == CallParticipantStatus.Waiting) {// 等待接听时,开始播放来电提示}if (selfInfo.status == CallParticipantStatus.Accept) {// 接听后,停止播放来电提示}}}}}
onCallReceived 事件。import io.trtc.tuikit.atomicxcore.api.device.DeviceStoreimport io.trtc.tuikit.atomicxcore.api.call.CallMediaTypeimport io.trtc.tuikit.atomicxcore.api.call.*class MainActivity : AppCompatActivity() {private var callListener: CallListener? = nulloverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)// ... 其他初始化代码// 1.监听来电事件addListener()}private fun addListener() {callListener = object : CallListener() {override fun onCallReceived(callId: String, mediaType: CallMediaType, userData: String) {super.onCallReceived(callId, mediaType, userData)// 2.根据来电媒体类型打开设备openDeviceForMediaType(mediaType)}}callListener?.let { CallStore.shared.addListener(it) }}private fun openDeviceForMediaType(mediaType: CallMediaType?) {mediaType?.let {DeviceStore.shared().openLocalMicrophone(null)if (mediaType == CallMediaType.Video) {val isFrontCamera = trueDeviceStore.shared().openLocalCamera(isFrontCamera, null)}}}}
参数 | 类型 | 说明 |
callId | String | 此次通话的唯一标识。 |
mediaType | 通话媒体类型,用于指定发起音频通话还是视频通话。 CallMediaType.Video:视频通话。CallMediaType.Audio:语音通话。 |
参数名 | 类型 | 必填 | 说明 |
isFront | Boolean | 是 | 是否开启前置摄像头。 true:开启前置摄像头。false:开启后置摄像头。 |
completion | CompletionHandler | 否 | 操作完成回调,用于返回开启摄像头的结果。若开启失败则会返回错误码和错误信息。 |
参数名 | 类型 | 必填 | 说明 |
completion | CompletionHandler | 否 | 操作完成回调,用于返回开启麦克风的结果。若开启失败则会返回错误码和错误信息。 |
private fun addListener() {callListener = object : CallListener() {override fun onCallReceived(callId: String, mediaType: CallMediaType, userData: String) {super.onCallReceived(callId, mediaType, userData)// 唤起通话页面val intent = Intent(this@MainActivity, CallActivity::class.java)startActivity(intent)}}callListener?.let { CallStore.shared.addListener(it) }}


private fun setIconResourcePath() {val volumeLevelIcons = mapOf(VolumeLevel.Mute to "对应图标资源的路径")val callCoreView = CallCoreView(context)callCoreView.setVolumeLevelIcons(volumeLevelIcons)}
参数 | 类型 | 是否必填 | 说明 |
icons | 是 | 音量等级与图标资源的映射表。 key ( VolumeLevel ) 表示音量等级: VolumeLevel.Mute :表示麦克风关闭,静音状态。VolumeLevel.Low :表示音量范围 (0-25]。VolumeLevel.Medium:表示音量范围 (25-50]。VolumeLevel.High:表示音量范围在 (50-75]。VolumeLevel.Peak:表示音量范围在 (75-100]。Value ( String ) 表示对应音量等级的图标资源路径。 |

private fun setNetworkQualityIcons() {val volumeLevelIcons = mapOf(NetworkQuality.BAD to "对应图标的路径")val callCoreView = CallCoreView(context)callCoreView.setNetworkQualityIcons(volumeLevelIcons)}
参数 | 类型 | 是否必填 | 说明 |
icons | 是 | 网络质量与图标资源的映射表。 Key ( NetworkQuality ):表示网络质量等级。 NetworkQuality.UNKNOWN :未知网络状态。NetworkQuality.EXCELLENT:网络状态极佳。NetworkQuality.GOOD:网络状态较好。NetworkQuality.POOR:网络状态较差。NetworkQuality.BAD:网络状态差。NetworkQuality.VERY_BAD :网络状态极差。NetworkQuality.DOWN :网络断开。Value ( String ):对应网络状态的图标资源路径。 |
图标 | 说明 | 下载地址 |
![]() | 网络较差的提示图标。 您可以将该图标等级设置为 NetworkQuality.BAD、NetworkQuality.VERY_BAD 或 NetworkQuality.DOWN ,当网络较差时显示该图标。 |
private fun setParticipantAvatars() {val avatars: MutableMap<String, ParticipantAvatarInfo> = mutableMapOf()val userId = "" // 用户 IDval avatarPath = "" // 用户默认头像资源的路径avatars[userId] = avatarPathval callCoreView = CallCoreView(context)callCoreView.setParticipantAvatars(avatars)}
参数 | 类型 | 是否必填 | 说明 |
icons | Map<String, String> | 是 | 用户头像映射表。 Key:用户的 userID 。 Value:该用户的头像资源绝对路径。 |
图标 | 说明 | 下载地址 |
![]() | 默认头像。 当用户头像加载失败或无头像时,您可以给该用户设置此默认头像。 |

private fun setWaitingAnimation() {val waitingAnimationPath = "" // 等待动画 GIF 图像资源的路径val callCoreView = CallCoreView(context)callCoreView.setWaitingAnimation(waitingAnimationPath)}
参数 | 类型 | 是否必填 | 说明 |
path | String | 是 | GIF 格式图像资源的绝对路径。 |
图标 | 说明 | 下载地址 |
![]() | 用户等待接听动画。 群组通话时设置的动画。设置后,当用户的状态为等待接听时,显示该动画。 |
CallStore.observerState.activeCall , 建立当前活跃通话的响应式监听。activeCall.duration 字段绑定至 UI 控件。该字段为响应式数据,会自动驱动 UI 实时刷新,无需手动维护定时器。import android.content.Contextimport androidx.appcompat.widget.AppCompatTextViewimport androidx.core.content.ContextCompatimport com.tencent.qcloud.tuicore.util.DateTimeUtilimport io.trtc.tuikit.atomicx.Rimport io.trtc.tuikit.atomicxcore.api.call.CallStoreimport io.trtc.tuikit.atomicxcore.api.call.CallParticipantStatusimport kotlinx.coroutines.CoroutineScopeimport kotlinx.coroutines.Dispatchersimport kotlinx.coroutines.Jobimport kotlinx.coroutines.launchclass TimerView(context: Context) : AppCompatTextView(context) {private var subscribeStateJob: Job? = nulloverride fun onAttachedToWindow() {super.onAttachedToWindow()// 1.数据层订阅 activeCallregisterActiveCallObserver()}override fun onDetachedFromWindow() {super.onDetachedFromWindow()subscribeStateJob?.cancel()}private fun registerActiveCallObserver() {subscribeStateJob = CoroutineScope(Dispatchers.Main).launch {CallStore.shared.observerState.activeCall.collect { activeCall ->// 2.绑定通话计时数据,更新通话计时updateDurationView(activeCall)}}}private fun updateDurationView(activeCall: CallInfo) {val currentDuration = activeCall.durationtext = DateTimeUtil.formatSecondsTo00(currentDuration.toInt())}}
val user = UserProfile()user.userID = "" // 您的 userIduser.avatarURL = "" // 头像的 urluser.nickname = "" // 需要设置的昵称LoginStore.shared.setSelfInfo(user, object : CompletionHandler {override fun onSuccess() {// 设置成功回调}override fun onFailure(code: Int, desc: String) {// 设置失败回调}})
参数 | 类型 | 是否必填 | 说明 |
userProfile | 是 | 用户信息结构体。 userID (String):用户的 ID 。avatarURL (String):用户头像的 url 。nickname (String):用户的昵称。 | |
completion | CompletionHandler | 否 | 操作完成回调,用于返回接通电话的结果。 |
Float 模式 | Grid 模式 | PIP 模式 |
![]() | ![]() | ![]() |
布局逻辑:呼叫等待时全屏显示己方画面;接通后全屏显示对方画面,己方画面以悬浮小窗展示。 交互特性:支持小窗拖拽移动,点击小窗可实现大小画面互换。 | 布局逻辑:所有成员画面呈网格状平铺排列成宫格模式布局,适用 2 人以上通话,支持点击放大画面功能。 交互特性:支持点击特定成员画面放大查看。 | 布局逻辑:1v1 场景固定显示对方画面,多人场景:采用当前发言者(Active Speaker) 策略,自动识别并全屏展示正在说话的用户。 交互特性:等待时显示自己的画面,接通后还会显示通话计时。 |
private fun setLayoutTemplate() {val callCoreView = CallCoreView()val template = CallLayoutTemplate.Grid// 设置布局模式callCoreView.setLayoutTemplate(template)setContentView(callCoreView)}
参数 | 类型 | 是否必填 | 说明 |
template | 是 | CallCoreView 的布局模式。 CallLayoutTemplate.Float:布局逻辑:呼叫等待时全屏显示己方画面;接通后全屏显示对方画面,己方画面以悬浮小窗展示。 交互特性:支持小窗拖拽移动,点击小窗可实现大小画面互换。 CallLayoutTemplate.Grid:布局逻辑:所有成员画面呈网格状平铺排列成宫格模式布局,适用 2 人以上通话,支持点击放大画面功能。 交互特性:支持点击特定成员画面放大查看。 CallLayoutTemplate.Pip:布局逻辑:1v1 场景固定显示对方画面,多人场景:采用当前发言者(Active Speaker) 策略,自动识别并全屏展示正在说话的用户。 交互特性:等待时显示自己的画面,接通后还会显示通话计时。 |
enterPictureInPictureMode 启动画中画模式。private fun enterPictureInPictureModeWithBuild() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && hasPipModePermission()) {val pictureInPictureParams: PictureInPictureParams.Builder = PictureInPictureParams.Builder()val floatViewWidth = resources.getDimensionPixelSize(R.dimen.callkit_video_small_view_width)val floatViewHeight = resources.getDimensionPixelSize(R.dimen.callkit_video_small_view_height)val aspectRatio = Rational(floatViewWidth, floatViewHeight)pictureInPictureParams.setAspectRatio(aspectRatio).build()this.enterPictureInPictureMode(pictureInPictureParams.build())}}
onPictureInPictureModeChanged 回调中,若检测到进入 PiP 模式,请将 CallCoreView 的布局设置为 CallLayoutTemplate.Pip 模式:val callCoreView = CallCoreView(context)override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean) {super.onPictureInPictureModeChanged(isInPictureInPictureMode)if (isInPictureInPictureMode) {callCoreView.setLayoutTemplate(CallLayoutTemplate.Pip)}}
onResume 回调。您可以在该回调中,根据当前通话的人数重新设置布局。若当前为 1v1 通话:设置为 CallLayoutTemplate.Float,多人通话:设置为 CallLayoutTemplate.Grid。val callCoreView = CallCoreView(context)override fun onResume() {super.onResume()val allParticipants = CallStore.shared.observerState.allParticipants.valueif (allParticipants.size > 2) {callCoreView?.setLayoutTemplate(CallLayoutTemplate.Grid)} else {callCoreView?.setLayoutTemplate(CallLayoutTemplate.Float)}}
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON 标志来实现此功能,这是最简单且推荐的方式。class CallActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or // 锁屏时显示WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or // 解锁屏幕WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON or // 保持屏幕常亮WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON // 点亮屏幕)setContentView(R.layout.activity_call)}}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"><uses-permission android:name="android.permission.FOREGROUND_SERVICE" /><uses-permission android:name="android.permission.FOREGROUND_SERVICE_CAMERA" /><uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" /><application><serviceandroid:name=".CallForegroundService"android:enabled="true"android:exported="false"android:foregroundServiceType="camera|microphone" /></application></manifest>
import android.app.Notificationimport android.app.NotificationChannelimport android.app.NotificationManagerimport android.app.Serviceimport android.content.Contextimport android.content.Intentimport android.os.Buildimport android.os.IBinderimport androidx.core.app.NotificationCompatclass CallForegroundService : Service() {companion object {private const val NOTIFICATION_ID = 1001private const val CHANNEL_ID = "call_foreground_channel"fun start(context: Context) {val intent = Intent(context, CallForegroundService::class.java)if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {context.startForegroundService(intent)} else {context.startService(intent)}}fun stop(context: Context) {val intent = Intent(context, CallForegroundService::class.java)context.stopService(intent)}}override fun onCreate() {super.onCreate()createNotificationChannel()// 启动前台通知,确保后台采集权限startForeground(NOTIFICATION_ID, createNotification())}override fun onBind(intent: Intent?): IBinder? = nullprivate fun createNotification(): Notification {return NotificationCompat.Builder(this, CHANNEL_ID).setContentTitle("正在通话中").setContentText("应用正在后台运行以保持通话").setSmallIcon(android.R.drawable.ic_menu_call) // 请替换为您的应用图标.setPriority(NotificationCompat.PRIORITY_HIGH).build()}private fun createNotificationChannel() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {val channel = NotificationChannel(CHANNEL_ID,"通话保活服务",NotificationManager.IMPORTANCE_HIGH)val manager = getSystemService(NotificationManager::class.java)manager.createNotificationChannel(channel)}}}
功能 | 描述 | 集成指引 |
拨打第一通电话 | 助力快速实现呼叫功能。包含发起呼叫、挂断逻辑及音视频采集设备的基本控制。 |
AndroidManifest.xml 声明通话界面的 Activity 为一个独立的任务栈。<activityandroid:name=".view.CallActivity" <!-- 您的通话界面 -->android:launchMode="singleTask"android:taskAffinity="${applicationId}.call" />
文档反馈