话单
更新时间: 2024/08/23 10:16:57
呼叫组件提供通话话单功能,在一通通话结束后,您会收到对应的通话话单。通话话单是一条事件通知消息,标记此次呼叫的状态。话单以 IM 会话类型消息抄送的形式发送,收到话单后,您可以解析消息体,获得通话时间等通话详情。
下图为常见话单示例,从上至下分别为主叫取消话单、被叫拒绝话单、超时未接听话单、被叫占线话单、正常通话带有时长的话单。
多人通话默认未封装话单功能。若您需要使用话单,请通过其他方式自行实现。
使用云信话单
步骤1 开通话单功能
具体请参见开通服务。
步骤2 发送话单
开通话单功能后,默认发送话单消息。
话单消息共有 5 类,其中 4 类为未接通时的话单,如拒接话单、占线话单、超时未接听话单、主叫取消话单,此类话单均由主叫方客户端发送;另外一类为带有通话时长的正常话单,此类话单为服务端直接发送。话单结构见话单解析部分。
呼叫组件不包含话单接收及解析功能,用户需要参考示例项目源码自行实现。详细说明请参考消息收发。
步骤3 接收并解析话单
话单消息同普通消息一样通过 IM SDK 进行消息接收,示例代码如下:
java/**
* 话单消息接收注册,同正常消息接收一样
*/
private void registerObserver() {
/**
* 注册消息接收观察者。 <br>
* 通知的消息列表中的消息不一定全是接收的消息,也有可能是自己发出去,比如其他端发的消息漫游过来,
*/
NIMClient.getService(MsgServiceObserve.class).observeReceiveMessage(new Observer<List<IMMessage>>() {
@Override
public void onEvent(List<IMMessage> imMessages) {
for (IMMessage item : imMessages) {
parseForNetCall(item);
}
}
}, true);
/**
* 用于发送消息后本地列表解析对应消息
*/
NIMClient.getService(MsgServiceObserve.class).observeMsgStatus(new Observer<IMMessage>() {
@Override
public void onEvent(IMMessage imMessage) {
parseForNetCall(imMessage);
}
}, true);
}
话单消息结构
话单类型:
类型(V1) |
类型(V2) |
话单类型 | 说明 |
---|---|---|---|
NERecordCallStatus.NrtcCallStatusComplete |
NERecordCallStatus.COMPLETE |
1 | 正常通话话单,通话双方都进入音视频通话后进行挂断。由组件服务器发送。 |
NrtcCallStatus.NrtcCallStatusCanceled |
NERecordCallStatus.CANCELED |
2 | 主叫取消话单,主叫呼叫后主动取消的话单。由客户端主叫方发送。 |
NrtcCallStatus.NrtcCallStatusRejected |
NERecordCallStatus.REJECTED |
3 | 被叫拒接话单,被叫拒接接听后的话单。客户端主叫方收到被叫拒接消息后进行发送。 |
NrtcCallStatus.NrtcCallStatusTimeout |
NERecordCallStatus.TIMEOUT |
4 | 超时话单,被叫收到通话邀请后不操作等待超时产生的话单。客户端主叫方发送。 |
NrtcCallStatus.NrtcCallStatusBusy |
NERecordCallStatus.BUSY |
5 | 占线话单(用户忙),当主叫呼叫被叫时,被叫仍处于通话以及呼叫/被叫中,此时被叫会拒绝主叫的通话邀请。客户端主叫收到消息后会发送占线话单。 |
话单以 IM 消息抄送的形式发送,抄送类型为会话类型,即 eventType 为 1。会话类型的消息体中一般包含 eventType、convType、to、fromAccount、msgTimestamp、msgType、msgidClient、msgidServer、attach 等字段,其中:
- 话单消息的 msgType 字段的值 为 NRTC_NETCALL,表示音视频话单消息抄送。
- 话单消息中 attach 字段中包含通话类型、呼叫状态等通话详情。
- 其他字段说明请参考会话类型消息抄送。
attach 字段说明:
字段 | 类型 | 示例 | 说明 |
---|---|---|---|
type |
Number |
1 |
通话类型。
|
channelId | Number | 123 | 房间 ID。 |
status |
Number |
1 |
呼叫状态。
|
durations |
JsonArray |
无 |
通话过程详情,JSON 数组格式,其中包括:
|
收到的话单的 JSON 结构:
json{
"type": 1, //1 表示音频,2 表示视频
"channelId": 123, //G2的channelId
"status": 1, //1 表示正常结束通话话单,对应上表的话单类型
"durations": [
{
"accid":"acc01",
"duration":10
},
{
"accid":"acc02",
"duration":12
}
]
}
接收到消息后进行消息解析。示例代码如下:
java/**
* 解析话单消息数据,一般用于 recyclerView adapter 中渲染
*
* @param message 当前IM消息
*/
private void parseForNetCall(IMMessage message) {
if (message == null) {
return;
}
// 此处只处理话单消息
if (message.getAttachment() instanceof NetCallAttachment) {
NetCallAttachment attachment = (NetCallAttachment) message.getAttachment();
/**
* 消息来源方向详见 {@link MsgDirectionEnum}
*/
MsgDirectionEnum direction = message.getDirect();
// 音频/视频 类型通话
int type = attachment.getType();
// 话单类型
int status = attachment.getStatus();
// 时长列表
List<NetCallAttachment.Duration> durations = attachment.getDurations();
// 按照话单类型解析
switch (attachment.getStatus()) {
case NrtcCallStatus.NrtcCallStatusComplete:
// 成功接听
if (attachment.getDurations() == null) {
break;
}
// 通话时长渲染
for (NetCallAttachment.Duration duration : durations) {
// 参与通话用户
String accId = duration.getAccid();
// 通话时长 单位为 秒
int seconds = duration.getDuration();
}
break;
case NrtcCallStatus.NrtcCallStatusCanceled:
// 主叫用户取消
break;
case NrtcCallStatus.NrtcCallStatusRejected:
// 被叫用户拒接
break;
case NrtcCallStatus.NrtcCallStatusTimeout:
// 被叫接听超时
break;
case NrtcCallStatus.NrtcCallStatusBusy:
// 被叫用户在通话中,占线
break;
}
}
}
自行实现话单逻辑
若组件自带的话单功能无法满足业务需求,可以参考一下步骤自行实现话单。
-
关闭组件自带话单功能。
-
关闭客户端本地发送未接通话单功能。
java
CallKitUIOptions options = new CallKitUIOptions.Builder() ...... .enableOrder(false) ...... .build(); CallKitUI.init(context,options);
至此,通话结束后话单消息将不再下发。
-
确定话单协议,通常用 JSON 表示。
json
{ "type": 1 // 话单类型 "data": ... // 话单消息内容,如通话时长等信息 }
-
参考自定义消息发送与解析,将步骤 3 中确定的话单协议作为自定义内容进行发送与解析。
- V2.0及之后版本
您可以通过设置
NERecordProvider
来发送话单,也可以根据 V1.0的时机自己处理发送。此处仅回调未接通话单,接通话单需要您在通话结束后独立处理。
java
NECallEngine.sharedInstance().setCallRecordProvider(new NERecordProvider() { @Override public void onRecordSend(NERecord record) { // 发送未成功通话话单 } });
NERecord 通话话单字段说明:
字段 类型 示例 accId String 通话对端的 accId callType int 通话类型,包括: NECallType.AUDIO
: 音频通话NECallType.VIDEO
:视频通话
callState int 通话话单类型( NERecordCallStatus
),具体请参见 话单消息结构-
V1.8.2及之前版本
至此,您已经完成自定义话单消息的发送以及解析,各个消息发送实际建议请参考下文。
组件支持的话单种类共有 5 类,分别为:
- 主叫取消话单:主叫方统一发送。主叫取消话单可在主叫调用取消呼叫方法成功后发送。
- 被叫拒绝话单:主叫方统一发送。在收到
NERTCCallingDelegate#onRejectByUserId
回调发送被叫拒绝话单。 - 超时未接听话单:主叫方统一发送。在收到
NERTCCallingDelegate#timeOut
回调发送超时未接听话单。 - 被叫占线话单:主叫方统一发送。在收到
NERTCCallingDelegate#onUserBusy
回调发送被叫占线话单。 - 正常通话带有时长的话单:建议由服务端发送,用户服务器收到云信服务器的 8 房间时长消息抄送时,根据抄送发送时长话单。