进阶集成指引

  • Android

更新时间不可用

了解 1v1 私密房 RTM 方案在不同平台上的优化 RTM 信令方案集成逻辑方式,包括接入流程、关键配置和平台差异。

使用已初始化过的 rtmClient

在集成 1v1 私密房方案过程中,你可以参考本文对 API 的调用时机、逻辑、参数设置等进行调优。声网 1v1 私密房的 CallAPI 中已经实现了对所需 RTM 服务的封装。如果在集成 1v1 私密房之前,你的项目中已经有 RTM 实例 rtmClient 了,则可以直接使用初始化过的 RTM 实例,然后调用相关功能。

信息

如果你使用自己创建的 rtmClient 实例,则可以自行维持 RTM 的登录状态;你也可以通过我们提供的 CallRtmManager 中的 login 和 logout 方法管理登录和登出。

Kotlin
val rtmConfig = RtmConfig.Builder(appId, userId.toString()).build()
val rtmClient = RtmClient.create(rtmConfig)
rtmClient.login(token, object : ResultCallback<Void?> {
    override fun onSuccess(p0: Void?) {
        // 登录成功即可初始化 CallRtmManager、CallRtmSignalClient、CallApi
    }

    override fun onFailure(p0: ErrorInfo?) {
        // 登录失败
    }
})

切换被叫的发布和订阅时机以节省费用

在收到呼叫后,被叫的发布和订阅时机有两种:

  • 收到呼叫后自动发布音视频流和订阅视频流,这是默认行为。
  • 收到呼叫后,需要被叫接受后再发布音视频流、订阅视频流。

你可以通过 ICallApiListener 中的可选回调 canJoinRtcOnCalling 来设置发布和订阅时机:

  • 如果返回 true,或不实现该回调方法,则使用默认的推流策略,即收到呼叫就发布音视频流和订阅视频流
  • 如果返回 false,则使用接受呼叫后再发布音视频流、订阅视频流的策略
Kotlin
/**
  * 当呼叫时判断是否可以加入Rtc
  * @param eventInfo 收到呼叫时的扩展信息
  * @return true: 可以加入 false: 不可以加入
  */
fun canJoinRtcOnCalling(eventInfo: Map<String, Any>) : Boolean?

手动开启和关闭音视频流发布

由于 CallAPI 内部会在通话时开启、结束通话时关闭采集音视频,因此如果在结束通话后外部需要手动开启音视频采集,例如当 onCallStateChanged 返回 (state: prepared) 时,可以开启采集。

Kotlin
rtcEngine.enableLocalAudio(true)
rtcEngine.enableLocalVideo(true)

消息中携带自定义数据结构

通过在 PrepareConfig 的 userExtension 属性中设置参数,您可以在发送消息给对端时(例如呼叫/取消呼叫/同意/拒绝等)附加额外的用户扩展信息。对端可以通过回调消息接收到这个userExtension,以便在处理消息时获取相关的附加信息。

Kotlin
override fun onCallStateChanged(
    state: CallStateType,
    stateReason: CallStateReason,
    eventReason: String,
    eventInfo: Map<String, Any>
) {
    val userExtension = eventInfo[CallApiImpl.kFromUserExtension] as? Map<String, Any>
    ...
}

通话异常定位

在双端连接过程中(state 为 calling/connecting/connected 时),可以通过 getCallId 方法获取当次通话双端的呼叫 ID。

你还可以通过 CallAPI 内部的日志上报,在声网后台查询到当次通话的各个节点耗时。如果需要使用,可以联系 sales@shengwang.cn 申请开通声网自定义数据上报和分析服务。

监听通话频道的 RTC 回调

为了更好地了解当前通话频道的状态和事件,你还可以监听 RTC 频道的回调。由于 CallAPI 里使用的 joinChannelEx 方式加入 RTC 频道,因此不可以使用 rtcEngine.addHandler 方式,需要通过 rtcEngine.addHandlerEx 并指定对应的频道来添加 delegate:

Kotlin
// 可以在收到呼叫状态时保存呼叫的频道 ID
override fun onCallStateChanged(
        state: CallStateType,
        stateReason: CallStateReason,
        eventReason: String,
        eventInfo: Map<String, Any>
    ) {
    when (state) {
        CallStateType.Calling -> {
          roomId = eventInfo[kFromRoomId] as? String ?: ""
        }
        else -> {}
    }
}

// 在收到 joinRTCStart 事件后通过频道 ID 来设置监听
override fun onCallEventChanged(event: CallEvent, eventReason: String?) {
    when(event) {
        CallEvent.JoinRTCStart -> {
            rtcEngine.addHandlerEx(
                object : IRtcEngineEventHandler() {
                    override fun onJoinChannelSuccess(
                        channel: String?,
                        uid: Int,
                        elapsed: Int
                    ) {
                        super.onJoinChannelSuccess(channel, uid, elapsed)
                        // ...
                    }
                },
                RtcConnection(roomId, currentUid.toInt()) // demo 为了方便将本端uid的字符串作为了频道名
            )
        }
        else -> {}
    }
}

其中,当前 RTC 通话频道的 ID(roomId 参数)可以在 onCallStateChanged 的 state 为 calling 时从 eventInfo 里解析获取。

注意

需要保证加入时已经触发过了 joinRTCStart 事件,在此事件之前调用 rtcEngine.addHandlerEx 会无效。

更新过期 Token

你可以通过如下方式,更新信令和 RTC 的过期 Token。

信令 Token

  1. 监听 RTM Token 是否过期。通过添加并监听 CallRtmManager 状态回调 监听 ICallRtmManagerListener 的 onTokenPrivilegeWillExpire。

    Kotlin
    val listener = object: ICallRtmManagerListener {
        override fun onTokenPrivilegeWillExpire(channelName: String) {
            // Token 过期,需要重新获取 Token
        }
    }
  2. 更新 Token。

    Kotlin
    // 更新 RTC Token
    this.api.renewToken(rtcToken)
    
    // 更新 RTM Token
    this.rtmManager?.renewToken(rtmToken)
    
    // 为确保 RTM 和 RTC Token 同时有效,建议同时更新这两个 Token

RTC Token

  1. 监听 RTC Token 是否过期。

    • 监听进行通话时过期的 Token。

      Kotlin
      val listener = object: ICallApiListener {
          override fun tokenPrivilegeWillExpire() {
              // Token过期,需要重新获取 Token
          }
      }
    • 监听进行通话之前过期的 Token。

      Kotlin
      val listener = object : ICallApiListener {
          override fun onCallError(
              errorEvent: CallErrorEvent,
              errorType: CallErrorCodeType,
              errorCode: Int,
              message: String?
          ) {
              if (
                  errorEvent == CallErrorEvent.RtcOccurError &&
                  errorType == CallErrorCodeType.Rtc &&
                  errorCode == ErrorCode.TokenExpired.value
              ) {
                  // RTC 加入频道失败,需要取消呼叫,并重新获取 Token
                  this.api.cancelCall { err -> }
              }
          }
      }
  2. 更新 Token。

    Kotlin
    // 更新 RTC Token
    this.api.renewToken(rtcToken)
    
    // 更新 RTM Token
    this.rtmManager?.renewToken(rtmToken)
    
    // 为确保 RTM 和 RTC Token 同时有效,建议同时更新这两个 Token

信息

建议给 RTC 和 RTM 配置相同的 Token 过期时间,然后通过信令 Token 方式,借助 RTM 来检测过期并同时更新。