前一篇我们使用腾讯封装的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。