前一篇我们使用腾讯封装的TRTCCalling接入了1v1的音视频通话,今天还是使用此模块进行实现多人音视频通话及其常用TRTCSDK的API。
多人语音通话
使用API发起通话
在TRTCCalling中可以看到1v1语音通话和多人语音通话有不同的API使用,分别为
/// 发起1v1通话接口
/// @param userID 被邀请方ID
/// @param type 通话类型:视频/语音
- (void)call:(NSString *)userID
type:(CallType)type
NS_SWIFT_NAME(call(userID:type:));
和
/// 发起多人通话
/// @param userIDs 被邀请方ID列表
/// @param type 通话类型:视频/语音
/// @param groupID 群组ID,可选参数
- (void)groupCall:(NSArray *)userIDs
type:(CallType)type
groupID:(NSString * _Nullable)groupID
NS_SWIFT_NAME(groupCall(userIDs:type:groupID:));
从API中可以看出对人通话需要传入被邀请方的ID是一个数组类型,数组内部存放被邀请人的ID,groupID-群组ID为一个可选参数,此参数为发起邀请所在的群,如果不是在一个IM群里发起的,groupID可以传一个空字符串。
当调用发起多人语音邀请后,先判断了当前是否在通话中,如果没有在通话中,则记录当前通话的邀请者、通话类型、群组ID、设置当前为通话中后组装进房参数。在自己进入房间后,在更新新添加的邀请人,并发起通话邀请(此内部实现逻辑可根据自己需求实现)。
- (void)call:(NSArray *)userIDs groupID:(NSString *)groupID type:(CallType)type {
if (!self.isOnCalling) {
self.curLastModel.inviter = [TRTCCallingUtils loginUser];
self.curLastModel.action = CallAction_Call;
self.curLastModel.calltype = type;
self.curRoomID = [TRTCCallingUtils generateRoomID];
self.curGroupID = groupID;
self.curType = type;
self.isOnCalling = YES;
[self enterRoom];
}
// 不在当前邀请列表,新增加的邀请
NSMutableArray *newInviteList = [NSMutableArray array];
for (NSString *userID in userIDs) {
if (![self.curInvitingList containsObject:userID]) {
[newInviteList addObject:userID];
}
}
[self.curInvitingList addObjectsFromArray:newInviteList];
// 更新已经回复的列表,移除正在邀请的人
NSMutableArray *rmRespList = [NSMutableArray array];
for (NSString *userID in self.curRespList) {
if ([self.curInvitingList containsObject:userID]) {
[rmRespList addObject:userID];
}
}
[self.curRespList removeObjectsInArray:rmRespList];
//通话邀请
if (self.curGroupID.length > 0 && newInviteList.count > 0) {
self.curCallID = [self invite:self.curGroupID action:CallAction_Call model:nil];
} else {
for (NSString *userID in newInviteList) {
self.curCallID = [self invite:userID action:CallAction_Call model:nil];
}
}
}
最后跟代码发现发起语音通话的信令是通过TXIMSDK进行。
通话邀请回调
当我们被邀请时SDK会回调以下方法,在此方法中我们可自定义处理此邀请的交互,比如presentVC、pushVC以及默认接听或判断为某个用户默认挂断等。
/// 被邀请通话回调 | invitee callback
/// - Parameter userIds: 邀请列表 (invited list)
-(void)onInvited:(NSString *)sponsor
userIds:(NSArray<NSString *> *)userIds
isFromGroup:(BOOL)isFromGroup
callType:(CallType)callType
NS_SWIFT_NAME(onInvited(sponsor:userIds:isFromGroup:callType:));
接受邀请
[[TRTCCalling shareInstance] accept];
接受邀请之后,组件会执行进入房间的音频采集传输操作以及通过IM通知接收方接受邀请。
[self enterRoom];
/**
* IMSDK方法
* 接收方接受邀请
* @note 不能接受不是针对自己的邀请,请在收到 onReceiveNewInvitation 回调的时候先判断 inviteeList 有没有自己,如果没有自己,不能 accept 邀请。
*/
- (void)accept:(NSString *)inviteID data:(NSString *)data succ:(V2TIMSucc)succ fail:(V2TIMFail)fail;
拒绝通话
[[TRTCCalling shareInstance] reject];
拒绝通话内部实现方法
//调用组件的以下方法,并传入cation的值为CallAction_Reject
- (NSString *)invite:(NSString *)receiver action:(CallAction)action model:(CallModel *)model;
//最终调用IMSDK的
/**
* 接收方拒绝邀请
*
* @note 不能拒绝不是针对自己的邀请,请在收到 onReceiveNewInvitation 回调的时候先判断 inviteeList 有没有自己,如果没有自己,不能 reject 邀请。
*/
- (void)reject:(NSString *)inviteID data:(NSString *)data succ:(V2TIMSucc)succ fail:(V2TIMFail)fail;
接收、邀请超时
当邀请发起后一段时间(默认30秒)没有回复的时候,接收方会通过组件回调
/// 通话超时的回调 | timeout callback
-(void)onCallingTimeOut;
邀请方会通过组件调用
/// 无回应回调-仅邀请者受到通知,其他用户应使用 onUserEnter |
/// no response callback only worked for Sponsor, others should use onUserEnter)
/// - Parameter uid: userid
-(void)onNoResp:(NSString *)uid
如果通话邀请方在多个接收均未应答时会回调
/// 主动挂断通话
- (void)hangup;
并且每个接收方都会通过组件回调
/// 当前通话被取消回调 | current call had been canceled callback
-(void)onCallingCancel:(NSString *)uid
NS_SWIFT_NAME(onCallingCancel(uid:));
中途加入与离开
如果需要离开当前多人通话可以调用
/// 主动挂断通话
- (void)hangup;
如果通话中有用户中途加入或离开,那么其他用户均会接收到以下两个回调
/// 进入通话回调 | user enter room callback
/// - Parameter uid: userid
-(void)onUserEnter:(NSString *)uid
/// 离开通话回调 | user leave room callback
/// - Parameter uid: userid
-(void)onUserLeave:(NSString *)uid
NS_SWIFT_NAME(onUserLeave(uid:));
多人视频通话
对人视频通话与多人语音通话流程基本一致,在组件中调用的API是一致的,需要注意传入的callType类型为CallType_Video。
/// 发起多人通话
/// @param userIDs 被邀请方ID列表
/// @param type 通话类型:视频/语音
/// @param groupID 群组ID,可选参数
- (void)groupCall:(NSArray *)userIDs
type:(CallType)type
groupID:(NSString * _Nullable)groupID
NS_SWIFT_NAME(groupCall(userIDs:type:groupID:));
在收到邀请后同语音回调相同会走以下方法,并同样使用语音的接受、拒绝邀请方法。
/// 被邀请通话回调 | invitee callback
/// - Parameter userIds: 邀请列表 (invited list)
-(void)onInvited:(NSString *)sponsor
userIds:(NSArray<NSString *> *)userIds
isFromGroup:(BOOL)isFromGroup
callType:(CallType)callType
NS_SWIFT_NAME(onInvited(sponsor:userIds:isFromGroup:callType:));
如果对方接受邀请后打开了摄像头会回调以下方法
- (void)onUserVideoAvailable:(NSString *)uid available:(BOOL)available;
这时即可观看对方视频画面,可使用
[[TRTCCalling shareInstance] startRemoteView:uid view:renderView];
停止观看视频,可使用
[[TRTCCalling shareInstance] stopRemoteView:uid];
如需要更加详细的TRTCSDK的API可在SDK内查找TRTCCloud文件及查看或者看在线文档,并根据自己的需求对其进行封装等。
离线接听
以上均为在线场景的接听功能,如果离线要如何做呢?
这就需要用前面文章配置的推送了。
- 申请 Apple 推送证书,具体操作请参见 Apple 推送证书申请。
- 在后台及客户端配置离线推送,具体操作请参见 离线推送(iOS)。
- 修改 login 函数中的
param.busiId
为对应证书 ID。