android linphone

android sip视频聊天开发
采用的是linphone 5.0.0的版本:'org.linphone:linphone-sdk-android:5.0.0'
我已经实现视频通话,但是在获取当前来电是视频还是普通来电时候遇到问题;
目前是发送端的videoEnabled不论设置true还是false接收端都为默认值true;
自定义头也收不到

//发送端
 params?.enableVideo(true)
//或者
 params?.enableVideo(false)


//接收端始终是true:
  val remoteParams = core.currentCall!!.remoteParams
                    if (remoteParams != null && remoteParams .videoEnabled()) {
                      showLog("视频来电")
                        //answer: video true
                    } else {
                     showLog("普通电话")
                        //answer: video false");
                    }

发送端自定义addCustomHeader

//发送端自定义头
    val headerKey = "X-Custom-Header"
    val headerValue = "Custom Information"
 params!!.addCustomHeader(headerKey, headerValue)


//接收端
 call.currentParams.getCustomHeader(headerKey)  //始终为空

从您的描述来看,此Linphone视频通话实现中存在以下两个问题:

  1. 视频通话参数enableVideo设置不生效,接收端始终获取到的视频状态为true。

  2. 自定义头信息addCustomHeader添加成功,但接收端无法获取该信息。

这两个问题的可能原因有:

  1. 视频通话参数未正确设置或同步。Linphone中视频通话参数的设置涉及两个对象:CallParams和MediaParameters。两者的设置必须一致,否则接收端无法正确获取参数信息。
  2. 自定义头信息未在会话协商之前添加。SIP信令的自定义头信息必须在INVITE请求之前添加和交换,否则接收端无法获取。
  3. Linphone的sdk版本更新导致接口或实现变更。不同版本的SDK,类、方法或接口的使用方式可能会有差异,需要检查版本发布说明。
    所以,初步的解决思路可以是:
  4. 检查CallParams和MediaParameters对象对视频参数enableVideo的设置,确保两者一致,否则接收端无法正确获取。
  5. 确认自定义头信息addCustomHeader是在INVITE请求发送前添加的。可以在inviteWithParams或acceptWithParams等方法调用前添加。
  6. 查看Linphone SDK不同版本的发布说明,检查相关接口或实现是否有变更,并更新您的使用方式。
  7. 也可以尝试使用linphone官方最新版本的SDK,测试相关功能是否正常。如果问题得到解决,则可以判断是由于SDK版本过低导致。

在使用Linphone SDK进行android视频聊天开发时,您需要在SIP消息头中携带信息来标记协商出的音视频策略,这样接收端才能正确识别当前通话是音频还是视频。

Linphone SDK 的默认SIP头部是不支持自定义的,如果您需要发送自定义数据,建议在sdphandler.c文件中进行修改。 在on_sip_request_outgoing()函数中,您可以手动添加 SIP头部:

linphone_sdp_add_custom_header(linphone_sdp, "X-VIDEO_ENABLED: false \r\n");

这里,X-VIDEO_ENABLED头是自定义的SIP头,包含双方是否启用视频的标志位信息。另外,在接收SIP消息时,相应的自定义头应该通过相应的API来读取。

代码示例:

CallParams  callParams = mCore.createCallParams(mCore.getCurrentSelectedAddress());
 callParams.enableVideo(true);
 Call call = mCore.inviteAddressWithParams(mCore.getCurrentSelectedAddress(),callParams);

在发起呼叫时,使用enableVideo函数设置是否启用视频。在接收到SIP消息时,使用linphone_call_params_video_enabled获取视频是否启用标志。

if (call.getRemoteParams() != null && call.getRemoteParams().videoEnabled()) {
      //视频来电
}else{
      //普通来电
}

以上是基于Linphone SDK 5.0.0实现的示例,您可以根据自己的实际情况做出适当修改。

有可能是拨打电话段的参数没有设置好,设置是否是视频通话,通过 CallParams 参数指定, 并通过inviteAddressWithParams方法发起通话,大致代码如下:

CallParams params = core.createCallParams(null);
        params.setMediaEncryption(MediaEncryption.None);
        params.enableVideo(video);
        // Finally we start the call
        core.inviteAddressWithParams(remoteAddress, params);

关于来电是视频还是普通电话的问题,您需要在每次呼入时检查远程参数(remoteParams)中是否设置了 videoEnabled 的值。如果 remoteParams 为 null,则可能意味着您在接听之前就检查了这个值。

请尝试在接收到来电后开始监听远程参数,例如:

// 在接收到来电之后添加远程参数监听器
core.addListener(object : LinphoneCoreListenerBase() {
    override fun callStateChanged(core: LinphoneCore?, call: LinphoneCall?, state: LinphoneCall.State?, message: String?) {
        super.callStateChanged(core, call, state, message)
        if (state == LinphoneCall.State.IncomingReceived && call?.remoteParams != null) {
            val isVideoEnabled = call.remoteParams.videoEnabled()
            if (isVideoEnabled) {
                // 视频来电
                showLog("视频来电")
            } else {
                // 普通电话
                showLog("普通电话")
            }
        }
    }
})

关于自定义头的问题,如果发送方未启用“加密信息头”(encrypt_information_headers),则自定义标题可能会被对端服务器或IDA授权中心拦截。请确保您在初始化时启用了加密信息头,并使用标准SIP header名称而不是像 "X-Custom-Header" 这样的自定义标题。例如:

// 初始化操作
LinphoneCore.setLogLevel(LogCollection.LogLevel.Debug)
factory = Factory.instance()
core = factory.createLinphoneCore(this, null)

// 启用加密信息头并添加自定义标题
core.iterate { // 等待核心启动完成
    core.createProxyConfig()
    val sipHeader = factory.createInfoMessage(null)
    sipHeader.addHeader("Custom-Header", "Custom Information")
    core.setDefaultProxyConfig(core.defaultProxyConfig)
}

接收方使用 currentCall.currentParams.getCustomHeader(headerName) 方法获取标准 SIP header 名称。例如:

// 在获取自定义头之前,确保至少有一个call存在
if (core.callsNb > 0 && core.currentCall != null) {
    val callParams = core.currentCall!!.currentParams
    val customHeaderValue = callParams.getCustomHeader("Custom-Header")?.value
    if (customHeaderValue != null) {
        showLog("Received Custom Header Value: $customHeaderValue")
    }
}

请注意,在生产环境中,可能需要更多的配置和测试才能确保通用性、安全性和可靠性。

网络抓包,看看实际发送请求的数据情况,看下是否与发送端设置的一致