Android技术分享| 一对一音视频呼叫邀请开发流程(一)
此文档基于 Android RTM、RTC SDK,其他平台API 基本一致,可供参考。
RTM:用于搭建呼叫的一整套流程、信令交互
RTC:用于呼叫流程通了之后的音视频交互
考虑到通讯服务功能分为调用与视频通话两大类,在开发过程中需要特别注意这两者的区别
点对点呼叫
点对点通讯即相当于两个人之间的电话沟通,在常见的通讯场景中涉及发起连接(Call Initiation)、拒绝连接(Call Rejection)等操作;此外还包括将视频通话转换为语音接听(Video Call to Voice Answer)以及处理忙音状态(Call Busy)等基本情况。
下面我将一一介绍这几个功能的实现以及需要注意的地方。
以下功能默认默认你已较为熟悉地阅读过 RTM RTC 文档,并成功登录了 RTM SDK;RTC SDK 已经就绪。
主叫
发起呼叫
- 创建 LocalInvitation 对象
val localInvitation = rtmCallManager.createLocalInvitation(userId)
该方法旨在生成一个呼叫对象,并在其中使用参数 userId 来表示对方登录的 RTMsdk 用户的信息。
- 添加自定义信息
在发起呼叫的过程中,一般情况下我们会要求告知对方当前的呼叫类型是视频还是音频,并且需要说明是否有多人同时进行呼叫以及其他与业务相关的详细信息。这时候可以在创建的 localInvitation 对象中加入自定义信息
localInvitation.setContent("自定义的消息体")
//通常我们都会选择发送json格式字符串,例如
"mediaType":0 //0视频 1 音频
"isMeeting":1 //0 多人模式 1 p2p
"rtcChannelId":"10000"//⚠️这个参数尤为重要,这个参数通常都由主叫生成,在呼叫的时候带给被叫。该参数的作用是告诉对方我们这次呼叫将进入哪个 RTC 的频道,两个人进入同一个 RTC 频道时,音视频才会通。
- 发送呼叫
rtmCallManager.sendLocalInvitation(localInvitation, null)
通过以上两步操作后就能发送呼叫了。主叫一旦发送呼叫就会被相应的反馈机制所捕获,并且提醒用户将注释直接复制到代码中即可完成处理。
//对方已收到你的呼叫
void onLocalInvitationReceivedByPeer(LocalInvitation var1);
//对方同意了你的呼叫
void onLocalInvitationAccepted(LocalInvitation var1, String response);
//对方拒绝了你的呼叫
void onLocalInvitationRefused(LocalInvitation var1, String response);
//自己取消了呼叫
void onLocalInvitationCanceled(LocalInvitation var1);
//呼叫失败,可能原因对方一直未接听等..
void onLocalInvitationFailure(LocalInvitation var1, int errorCode);
掌握以上回调的作用在开发过程中至关重要。其中接受和拒绝回调中的第二个 response 属性,在处理通话时我们可以使用。稍后将在'转语音接听'与'处理通话正忙'的章节中介绍。
取消呼叫
rtmCallManager.cancelLocalInvitation(localInvitation,null)
被叫
同意呼叫
在对方发起呼叫后,被叫会收到以下相关回调。
//收到呼叫
void onRemoteInvitationReceived(RemoteInvitation var1);
//你同意了呼叫
void onRemoteInvitationAccepted(RemoteInvitation var1);
//你拒绝了呼叫
void onRemoteInvitationRefused(RemoteInvitation var1);
//对方取消了呼叫
void onRemoteInvitationCanceled(RemoteInvitation var1);
//呼叫邀请失败,可能是长时间未接听等情况,可查看文档
void onRemoteInvitationFailure(RemoteInvitation var1, int var2);
流程图(同意呼叫后)

请特别注意在被调用方回话中涉及的 RemoteInvitation 实例的具体情况,并确保其正确性
String getCallerId() //主叫的userId!!主叫的userId!!
String getContent() //主叫发送的自定义信息
在接收到呼叫时触发的回调函数中, 我们会解析其内容中的JSON数据块, 这从而可判断本次是否为语音或视频型呼叫, 同时还能确定此次通话将被分配至相应的RTC频道. 在此期间, 你可以选择暂时拒绝或接受当前通话请求, 一旦确认通话类型后主叫与被叫双方需执行相关操作以完成这次通话流程, 如需进一步了解, 请参考上文提供的详细注释说明.
另外,RemoteInvitation 还有一个特别实用的方法
void setResponse(String var1)//设置回执消息
这个方法可以用来做什么?请往下看。
视频呼叫转语音接听
视频呼叫转语音接听在视频通话中是普遍存在的现象,在微信平台中也提供了这一便捷的功能选项。实现这一功能相对来说非常简单,并不需要复杂的操作步骤。具体来说,在双方达成一致的情况下(即同意连接的一方),只需为RemoteInvitation对端设置相应的response参数即可完成配置。以下将详细说明操作流程以及所需配置的具体内容。
//收到呼叫转语音 伪代码
fun onRemoteInvitationReceived(RemoteInvitation var1){
val mediaType = var.content.get("mediaType")
if(mediaType==0){//视频呼叫
val remote = var1
remote.setResponse("mediaType:1")//语音
rtmCallManager.acceptRemoteInvitation(remote, null)
}
}
当我们在 RemoteInvitation 对象进行配置并在同意后时,主机会收到相应信息
//对方同意了你的呼叫
void onLocalInvitationAccepted(LocalInvitation var1, String response);
其中第二个参数即为被叫设置所使用的 response。接着,在此进行解析后发现返回的 mediaType 是否与本地发起时的一致。如果返回的 mediaType 与本地发起时的一致,则表示一切正常;如果不一致,则可能是对方将语音转换为了呼叫。
拒绝呼叫/呼叫正忙
流程图(拒绝呼叫)

fun onRemoteInvitationReceived(RemoteInvitation var1){
if(inCalling){//如果我此时正在呼叫(isCalling为自己本地记录,SDK并无判断自己是都在通话中相关方法)
val remote = var1
remote.setResponse("Busy")//正忙
rtmCallManager.rejectRemoteInvitation(remote, null)
}
当我们在 RemoteInvitation 对象上设置 response 并且在拒绝之后时, 主叫将接收到
//对方拒绝了你的呼叫
void onLocalInvitationRefused(LocalInvitation var1, String response);
其中第二个参数即为被叫设置的response。然后我们可以对此进行分析以识别对方拒绝的原因后提供相应的提示信息。
另外一种选择是不进行任何设置,则系统将默认采取正常拒绝行为。这些内容均涉及业务层面的逻辑处理,相关参数可以通过业务需求进行调整
以上就是 RTM 点对点呼叫部分的流程,接下来就是挂断和进入 RTC 频道了。
加入RTC 频道
通常在被叫同意之后, 双方会自动加入RTC频道. 其中, 在主叫端我们已经预先设置好了该频道的ID, 并将其传递给被叫方以作为自定义信息的一部分. 因此, 在相应的回调函数中进行处理时, 我们需要分别执行加入RTC频道的操作即可.
//主叫
void onLocalInvitationAccepted(LocalInvitation var1, String response){
//被叫同意呼叫后,主叫会收到该回调。在这里加入 rtc 频道即可
}
//被叫
void onRemoteInvitationAccepted(RemoteInvitation var1){
//被叫同意呼叫后,会收到该回调。在这里解析RemoteInvitation 对象中的content 字端,获取主叫定义的rtcChannelId,然后加入 rtc 频道即可
}
关于加入 RTC 等音视频处理,本文不做过多介绍。
挂断
需要注意的是,在被叫同意或拒绝时需要注意的是,在此之后RTM的呼叫流程实际上已经完成了工作。当我们在通话中挂断时需要用RTM信号通知对方以完成操作步骤。例如向主叫发送一条信息作为操作指示
rtmClient.sendMessageToPeer()
消息格式也可以自定义,只需要双方约定好即可。比如发送,"CMD:EndCall"
自己发送完和对方收到后,退出 RTC 频道即可,这样就完成了一整套的呼叫。
除此之外还有其他特殊情况需要注意。例如,在个人通话中断时会导致App进程崩溃。这种情况可以通过订阅对方在线状态来实现监控和响应;同时也可以根据实际情况自定义一套完整的异常处理方案。
总结
- RTM与RTC是两个完全独立的功能模块,在功能划分上实现了全面分离。
- 当接通时会触发RemoteInvitation对象(该对象用于接收主叫方的应答信息),LocalInvitation允许用户预先设定特定的信息内容。
- 当主叫方发送应答请求时(此时会触发RemoteInvimation对象),该对象可接收相应的反馈数据并返回给调用方。
在此基础上,我们详细阐述了基于RTMRTC SDK实现的点对点视频通话开发流程,并同时提供了相关的参考示例DEMO。
下一篇将介绍如何实现多人呼叫,中途邀请其他人参与呼叫等例子。

