NIM SDK 使用指南

SDK 概述

网易云信 SDK (NIM SDK) 为移动应用提供完善的 IM 开发框架,屏蔽其内部复杂细节,对外提供较为简洁的 API 接口,方便第三方应用快速集成 IM 功能。SDK 兼容 iOS 7.0+ ,Demo 兼容 iOS 8.0+ 。

开发准备

NIM SDK 提供两种集成方式:您既可以通过 CocoaPods 自动集成我们的 SDK,也可以通过手动下载 SDK, 然后添加到您的项目中。

我们提供两个下载地址。分别为:

手动添加 SDK

通过 CocoaPods 集成

Podfile 文件中加入

  pod 'NIMSDK'

安装

  pod install

如果无法安装 SDK 最新版本,运行以下命令更新本地的 CocoaPods 仓库列表

  pod repo update

SDK 类说明

NIM SDK 主要提供了如下类(协议)与方法

NIMAVChat 主要提供了如下类(协议)与方法

配置 HTTPS 支持

在默认情况下,SDK 认为用户资料头像,群头像,聊天室类用户头像等信息都是默认托管在云信上,所以 SDK 会针对他们自动开启 HTTPS 支持,开发者不需要任何额外配置。

但如果开发者需要将这些信息都托管在自己的服务器上,需要在 NIMSDKConfig.h 中,将

@property (nonatomic,assign)    BOOL    enabledHttpsForInfo

设置为 NO,避免 SDK 自动将开发者设置的 HTTP URL 自动转换为 HTTPS URL

因为苹果的 ATS 政策,如果应用中使用了 HTTP 请求,需要将工程配置文件中的 info.plist 文件,NSAppTransportSecurity 条目中适配好 NSExceptionDomains。需要注意的是,2017 年以后,应用中存在 HTTP 请求会有审核被拒的风险。

初始化 SDK

推荐在 APP 启动时尽快注册 NIM SDK。

登录与登出

在使用 SDK 之前,需要对云信的体系流程有基本的认知,推荐开发者首先阅读这里

手动登录

调用

[[[NIMSDK sharedSDK] loginManager] login:account
                                   token:token
                              completion:^(NSError *error) {}];

error为登录错误信息,成功则为nil。不要在登录完成的回调中直接获取 SDK 缓存数据,而应该在 同步完成的回调里获取数据 或者 监听相应的数据变动回调后获取

注:在不特殊说明的情况下,SDK 的所有回调都是在主线程中发起,无论是以 block 还是 delegate 的形式,也推荐开发者仅在主线程调用 SDK 相关接口。

获取登录帐号的云信 id:

NSString *userID = [NIMSDK sharedSDK].loginManager.currentAccount;

SDK 不支持直接添加云信用户,请参考这里,在您的应用服务器上使用 Http 接口进行添加。

自动登录

NIM SDK 有两种自动登录的场景:

1.SDK 发起的自动登录:登录完毕后因网络发生切换,断网等情况发生而需要重连,SDK 将自动进行重连重登,无需 APP 干预。

2.APP 发起的自动登录:APP 启动时,如果已保存用户名和密码可以选择调用自动登录接口,并立刻打开主界面。此时 APP 可以在无网络,未登录成功的状态下直接访问用户本地数据。

//APP主动发起自动登录
- (void)autoLogin:(NIMAutoLoginData *)loginData

NIMAutoLoginData 中的 forcedMode 为强制模式开关。非强制模式下的自动登录,服务器将检查当前登录设备是否为上一次登录设备,如果不是,服务器将拒绝这次自动登录(返回 error code 为 417 的错误);强制模式下的自动登录,服务器将不检查当前登录设备是否为上一次登录设备,安全性较低,但较为便捷。

和手动登录不同,自动登录通过委托通知登录状态。 APP 需要实现如下回调 (手动登录也会收到同样的委托回调)

- (void)onLogin:(NIMLoginStep)step

自动登录过程不需要 APP 加以干预,SDK 会在有网络的情况下有策略地不断重试直到登录为止。但下面两种异常情况需要 APP 处理:被踢和特殊的登录错误。

-(void)onKick:(NIMKickReason)code 
   clientType:(NIMLoginClientType)clientType

APP收到被踢回调后需要进行注销并切换到登录界面。

- (void)onAutoLoginFailed:(NSError *)error

大部分自动登录回调错误 APP 并不需要关心,只需注意如下两种情况:

1.用户名密码错误导致自动登录失败,error code 为 302。这种情况一般发生于用户在其他设备上修改了密码。

2.已有一端登录导致自动登录失败,error code 为 417。这种情况发生于非强制登录模式下已有一端在线而当前设备进行自动登录(设置为只允许一端同时登录时),出于安全方面的考虑,云信服务器判定当前端需要重新手动输入用户密码进行登录,故拒绝登录。

一旦发生如上情况,APP 同样需要进行注销并切换到登录界面。

登出

调用

[[[NIMSDK sharedSDK] loginManager] logout:^(NSError *error){}];

应用层登出/注销自己的账号时需要调用 SDK 的登出操作,该操作会通知云信服务器进行 APNS 推送信息的解绑操作,避免用户已登出但推送依然发送到当前设备的情况发生。

考虑到用户体验,登出的超时时间会比其他请求短一些。上层应用不管登出请求是否成功,UI 表现上都应该做出登出行为。

多端登录

当用户在某个客户端登录时,其他没有被踢掉的端会触发回调:

- (void)onMultiLoginClientsChanged;

同时,可以查询当前时间登录的设备列表:

- (NSArray<NIMLoginClient *> *)currentLoginClients;

云信内置踢人策略为:移动端(Android,iOS)互踢,桌面端(PC,Web)互踢,移动端和桌面端共存。

如果当前的互踢策略无法满足业务需求的话,可以联系我们取消内置互踢,根据多端登录的回调和当前的设备列表,判断本设备是否需要被踢出。如果需要踢出,直接调用登出接口并在界面上给出相关提示即可。

登录与用户信息同步

NIM SDK 的登录一共有大约十个步骤,包括正在连接,连接成功,正在登录等。详见 NIMLoginStep 枚举。其中重要的两个步骤为:登录成功 (NIMLoginStepLoginOK) 和 同步成功 (NIMLoginStepSyncOK)。

NIM SDK 在登录后会同步群信息,离线消息,漫游消息,系统通知等数据。

基础消息功能

消息功能概述

SDK 中用户与同一个对象的聊天信息集合,称为一个会话,用 NIMSession 来表示。会话有单人会话,群组会话,聊天室会话等类型。

SDK 中用于表示消息的结构为 NIMMessage,目前提供如下几种消息类型,不同的消息类型对应不同的 MessageObject

消息格式 MessageObject
文本消息 nil
图片消息 NIMImageObject
音频消息 NIMAudioObject
视频消息 NIMVideoObject
地理位置消息 NIMLocationObject
通知消息 NIMNotificationObject
提醒消息 NIMTipObject
自定义消息 NIMCustomObject

消息 NIMMessage 定义了一些额外的状态属性,推荐只在主线程对这些属性进行读写

发送消息

1.构造并发送消息

//构造消息
NIMMessage *message = [[NIMMessage alloc] init];
message.text    = text;

//构造会话
NIMSession *session = [NIMSession session:userId type:NIMSessionTypeP2P];

//发送消息
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:nil];
//构造消息
NIMImageObject * imageObject = [[NIMImageObject alloc] initWithImage:image];
NIMMessage *message          = [[NIMMessage alloc] init];
message.messageObject        = imageObject;

//构造会话
NIMSession *session = [NIMSession session:userId type:NIMSessionTypeP2P];

//发送消息
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:nil];
//构造消息
NIMAudioObject *audioObject = [[NIMAudioObject alloc] initWithSourcePath:filePath];
NIMMessage *message        = [[NIMMessage alloc] init];
message.messageObject      = audioObject;

//构造会话
NIMSession *session = [NIMSession session:userId type:NIMSessionTypeP2P];

//发送消息
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:nil];
//构造消息
NIMVideoObject *videoObject = [[NIMVideoObject alloc] initWithSourcePath:filePath];
NIMMessage *message         = [[NIMMessage alloc] init];
message.messageObject       = videoObject;

//构造会话
NIMSession *session = [NIMSession session:userId type:NIMSessionTypeP2P];

//发送消息
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:nil];
//构造消息
//其中,latitude为纬度,longitude为经度,title为位置的描述字段
NIMLocationObject *locationObject = [[NIMLocationObject alloc] initWithLatitude:latitude Longitude:longitude address:title];
NIMMessage *message               = [[NIMMessage alloc] init];
message.messageObject             = locationObject;

//构造会话
NIMSession *session = [NIMSession session:userId type:NIMSessionTypeP2P];

//发送消息
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:nil];
通知类型 NIMNotificationContent
群通知 NIMTeamNotificationContent
网络电话通知 NIMNetCallNotificationContent
聊天室通知 NIMChatroomNotificationContent
未被支持类型通知 NIMUnsupportedNotificationContent

由于系统升级,旧版本的 SDK 可能无法解析新版本数据,所有无法解析的新通知显示为未被支持。

当不需要一些通知时,开发者可以实现 NIMSDKConfig 的委托 delegate,来控制哪些通知需要忽略。

  - (BOOL)shouldIgnoreNotification:(NIMNotificationObject *)notification

当消息将要存储到本地时,会调用此回调,开发者只应该在这个回调里做简单逻辑判断,如果做耗时操作会严重影响存储性能。

不支持从客户端发出通知消息。

//构造消息
NIMTipObject *tipObject = [[NIMTipObject alloc];
NIMMessage *message     = [[NIMMessage alloc] init];
message.messageObject   = tipObject;

//构造会话
NIMSession *session = [NIMSession session:userId type:NIMSessionTypeP2P];

//发送消息
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:nil];

自定义消息用于 APP 拓展自己的消息类型,实现不同业务逻辑。自定义消息的 MessageObject(NIMCustomObject) 仅有一个 id 字段,SDK 会负责透传这个对象序列化后的结果。NIMCustomAttachment 协议包括一个必须实现的序列化接口和三个与上传相关的可选接口。如果需要在自定义消息中上传文件作为附件的一部分,必须实现这三个上传接口,缺一不可。实现自定义消息参考教程

//构造消息
NIMCustomObject *customObject     = [[NIMCustomObject alloc] init]; 
customObject.attachment           = attachment;
NIMMessage *message               = [[NIMMessage alloc] init];
message.messageObject             = customObject;

//构造会话
NIMSession *session = [NIMSession session:userId type:NIMSessionTypeP2P];

//发送消息
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:nil];

2.检查调用状态

正常情况这一步可以省略,但刚开始集成 SDK 时,因为上层开发对 API 不熟悉有可能传入一些无效参数,推荐在开发前期务必检查 sendMessage:toSession:error 的返回值和 error 信息,并以此为依据排查问题。

3.处理回调

在调用完发送消息接口后,通常会收到如下回调

- (void)willSendMessage:(NIMMessage *)message

建议开发者仅在收到这个回调后才将消息加入显示用的数据源中。

- (void)sendMessage:(NIMMessage *)message
           progress:(CGFloat)progress

图片,视频等需要上传附件的消息会有比较详细的进度回调,文本消息则没有这个回调。

- (void)sendMessage:(NIMMessage *)message
didCompleteWithError:(NSError *)error

如果消息发送成功 error 为 nil,反之 error 会被填充具体的失败原因。

4.重发

因为网络原因等导致的发送消息失败而需要重发的情况,直接调用

- (BOOL)resendMessage:(NIMMessage *)message
                error:(NSError **)error

此时如果再次调用 sendMessage,则会被 NIM SDK 认作新消息。

5.消息的发送设置

SDK 提供消息发送设置来满足开发者的对服务器自定义需求,这些设置可以在 NIMMessageNIMMessageSetting 属性中找到。

接收消息

- (void)onRecvMessages:(NSArray<NIMMessage *> *)messages

如果收到的是图片,视频等需要下载附件的消息,在回调的处理中还需要调用

(SDK 默认会在第一次收到消息时自动调用)

- (BOOL)fetchMessageAttachment:(NIMMessage *)message
                         error:(NSError **)error

进行附件的下载,附件的下载过程会通过

- (void)fetchMessageAttachment:(NIMMessage *)message
                      progress:(CGFloat)progress
- (void)fetchMessageAttachment:(NIMMessage *)message
          didCompleteWithError:(NSError *)error;

这两个回调返回进度和结果。

消息转发

除了 通知消息 之外,其他类型消息均支持转发给其他会话。

- (BOOL)forwardMessage:(NIMMessage *)message
             toSession:(NIMSession *)session
                 error:(NSError **)error

这里返回的 error 参数只是表示当前这个函数调用是否成功,需要后续的回调才能够判断消息是否已经发送至服务器。后续回调和普通消息发送流程相同。

已读回执

在会话界面中调用发送已读回执的接口并传入最后一条消息,即表示这之前的消息都已读,对端将收到此回执。

发送已读回执

- (void)sendMessageReceipt:(NIMMessageReceipt *)receipt
                completion:(NIMSendMessageReceiptBlock)completion;

接受已读回执

- (void)onRecvMessageReceipt:(NIMMessageReceipt *)receipt;

在发送端 NIMMessageReceipt 需要通过最后一条消息 NIMMessage 进行初始化并进行发送,而接收端可以通过 NIMMessageReceipt 中的 timestamp 来得知发送端当前已读时间戳。此功能仅在 P2P 消息中有效。重复发送和通过无效消息构造的已读回执都将被 SDK 忽略。

消息撤回

在会话时,允许用户撤回一定时间内发送过的消息。

- (void)revokeMessage:(NIMMessage *)message
           completion:(NIMRevokeMessageBlock)completion;

在撤回消息请求调用成功后, SDK 会先回调给上层成功,再自动将本地的这条消息删除。如果需要在撤回后显示一条已撤回的提示 ( 见 Demo 交互 ) ,开发者可以自行构造一条提醒消息并插入本地数据库。

以下情况消息撤回会失败

当有消息撤回发生时,被撤回方 SDK 会触发回调:

- (void)onRecvRevokeMessageNotification:(NIMRevokeMessageNotification *)notification

SDK 在收到消息撤回后,会先从本地数据库中找到对应消息并进行删除,之后通知上层消息已删除。如果需要在撤回后显示一条已撤回的提示 ( 见 Demo 交互 ) ,开发者在这个回调中自行构造一条提醒消息并插入本地数据库。

由于用户业务场景不一致,在撤回后可能在撤回后用一条提醒消息替代,也有可能不做任何提示,而被撤回的消息本身可能是未读的,这样不同的业务逻辑就造成了未读数的不一致。 在 NIMSDKConfig.h 中统一封装了撤回未读配置 接口:

@property (nonatomic,assign) BOOL shouldConsiderRevokedMessageUnreadCount;

默认为 NO。设置成 YES 的情况下,如果被撤回的消息本地还未读,那么当消息发生撤回时,对应会话的未读计数将减 1 以保持最近会话未读数的一致性。 当不做任何提示时,可以设置为 YES,以保持未读计数的一致性。

最近会话

NIMConversationManager 提供最近消息的本地存储管理功能。

最近会话 NIMRecentSession 用于表示会话列表页的数据模型。当用户发送,收取及删除消息时,都会同时去修改最近会话。

当收到或者一条消息时,会自动生成这个消息对应的最近会话。但值得注意的是最近会话和会话并不是一一对应的关系,删除最近会话并不会影响会话。

- (NSArray<NIMRecentSession *> *)allRecentSessions

NIMConversationManager 提供了最近会话的三个回调通知上层:

分别为增加,修改,删除最近会话的回调:

- (void)didAddRecentSession:(NIMRecentSession *)recentSession
           totalUnreadCount:(NSInteger)totalUnreadCount

- (void)didUpdateRecentSession:(NIMRecentSession *)recentSession
              totalUnreadCount:(NSInteger)totalUnreadCount

- (void)didRemoveRecentSession:(NIMRecentSession *)recentSession
              totalUnreadCount:(NSInteger)totalUnreadCount

开发者无法自己添加最近消息,最近消息会在发送或者收到消息的时候自动添加,并触发增加最近会话的回调。

单条消息的删除

- (void)deleteMessage:(NIMMessage *)message;

调用此方法时,如果删除的是最后一条消息,消息所属的最近会话的 lastMessage 属性会自动变成上一条消息(没有则为空消息),同时触发最近消息修改的回调。

单个会话批量消息删除

- (void)deleteAllmessagesInSession:(NIMSession *)session
               removeRecentSession:(BOOL)removeRecentSession

removeRecentSession 标记了最近会话是否会被保留,会话内消息将会标记为已删除。调用此方法会触发最近消息修改的回调,如果选择保留最近会话, lastMessage 属性将会被置成一条空消息。

- (void)deleteRecentSession:(NIMRecentSession *)recentSession

只会删除最近会话,但保留会话内消息。调用时,总未读消息数会减去当前会话的未读数。调用此方法触发最近消息删除的回调。

- (void)deleteAllMessages:(BOOL)removeRecentSessions

removeRecentSession 标记了最近会话是否会被保留。调用这个接口只会触发 - (void)allMessagesDeleted 回调,其他针对单个 recentSession 的回调都不会被调用。

- (NSInteger)allUnreadCount
- (void)markAllMessagesReadInSession:(NIMSession *)session

调用这个方法时,会将所有属于这个会话的消息都置为已读状态。相应的最近会话(如果有的话)未读数会自动置 0 并且触发最近消息修改的回调

最近会话提供本地扩展能力,可以用来开发 @ 以及 置顶 等功能。

开发者可以通过 RecentSessionlocalExt 接口读取扩展。

并通过调用 NIMConversationManager 修改本地扩展信息

- (void)updateRecentLocalExt:(NSDictionary *)ext
               recentSession:(NIMRecentSession *)recentSession

历史记录

云端记录

NIMConversationManager 支持从云信服务器上远程获取之前的聊天历史记录。

- (void)fetchMessageHistory:(NIMSession *)session
                     option:(NIMHistoryMessageSearchOption *)option
                     result:(NIMFetchMessageHistoryBlock)block;

其中 option 为搜索选项,具体选项如下:

本地记录

语音录制及播放

多媒体管理 NIMMediaManager 提供了音频播放、高清语音录制的功能。需要注意的是 NIM SDK 中的语音播放和录制仅支持 aac 和 amr,如果需要更多格式的支持,APP 需要自己实现,但并不推荐。

播放音频

- (BOOL)switchAudioOutputDevice:(NIMAudioOutputDevice)outputDevice
- (BOOL)isPlaying
- (void)play:(NSString *)filepath;

其中 filePath 为音频文件的路径,该操作会触发以下回调:

初始化工作完成,准备开始播放音频的时候会触发

- (void)playAudio:(NSString *)filePath didBeganWithError:(NSError *)error

音频播放结束的时候会触发

- (void)playAudio:(NSString *)filePath didCompletedWithError:(NSError *)error
- (void)stopPlay

该操作会触发回调:

- (void)playAudio:(NSString *)filePath didCompletedWithError:(NSError *)error

录制音频

- (BOOL)isRecording
- (void)recordForDuration:(NSTimeInterval)duration;

其中 duration 限制了录音的最大时长,该操作会触发以下回调:

初始化工作完成,准备开始录制的时候会触发

- (void)recordAudio:(NSString *)filePath didBeganWithError:(NSError *)error

当到录音时长达到设置的最大时长,或者手动停止录音会触发

- (void)recordAudio:(NSString *)filePath didCompletedWithError:(NSError *)error

按照一定的时间间隔触发

- (void)recordAudioProgress:(NSTimeInterval)currentTime

其中 currentTime 为当前的录音时长,触发该回调的时间间隔可以通过以下属性设置,默认为 0.3 秒

@property (nonatomic, assign) NSTimeInterval recordProgressUpdateTimeInterval

- (void)stopRecord

该操作会触发

- (void)recordAudio:(NSString *)filePath didCompletedWithError:(NSError *)error
- (void)cancelRecord

该操作会触发

- (void)recordAudioDidCancelled

获取峰值

- (float)recordPeakPower

获取平均值

- (float)recordAveragePower

来电打断

- (void)playAudioInterruptionBegin

- (void)recordAudioInterruptionBegin
- (void)playAudioInterruptionEnd

- (void)recordAudioInterruptionEnd

群组功能

群组功能概述

群组功能对应的管理类为 NIMTeamManagerNIMTeamManager 提供了普通群 (Normal) 以及高级群 (Advanced) 两种形式的群聊功能。高级群拥有更多的权限操作,两种群聊形式在共有操作上保持了接口一致。推荐 APP 开发时只选择一种群类型进行开发。普通群和高级群在原则上是不能互相转换的,他们的群类型在创建时就已经确定。在 SDK 2.4.0 版本后,高级群可以拥有普通群的全部功能,推荐使用高级群进行开发。

开发手册中所提及的普通群都等同于 Demo 中的讨论组。普通群没有权限操作,适用于快速创建多人会话的场景。每个普通群只有一个管理员。管理员可以对群进行增减员操作,普通成员只能对群进行增员操作。在添加新成员的时候,并不需要经过对方同意。

高级群在权限上有更多的限制,权限分为群主、管理员、以及群成员。

获取群组

NIM SDK 在程序启动时会对本地群信息进行同步,所以只需要调用本地缓存接口获取群就可以了。 SDK 提供了批量获取自己的群接口、以及根据单个群 id 查询的接口。同样 SDK 也提供了远程获取群信息的接口。

本地获取

- (NSArray<NIMTeam *> *)allMyTeams
- (NIMTeam *)teamById:(NSString *)teamId

远程获取

- (void)fetchTeamInfo:(NSString *)teamId
           completion:(NIMTeamFetchInfoHandler)block;

创建群组

- (void)createTeam:(NIMCreateTeamOption *)option
             users:(NSArray<NSString *> *)users
        completion:(NIMTeamCreateHandler)completion

加入群组

用户可以通过被动接受邀请和主动加入两种方式进入群组。

邀请用户入群

- (void)addUsers:(NSArray<NSString *>  *)users
          toTeam:(NSString *)teamId
      postscript:(NSString *)postscript
      completion:(NIMTeamMemberHandler)completion

请求完成后,如果是普通群,被邀请者将直接入群;如果是高级群,云信服务器会下发一条系统消息到目标用户,目标用户可以选择同意或者拒绝入群。

同意群邀请(仅限高级群)

- (void)acceptInviteWithTeam:(NSString*)teamId
                   invitorId:(NSString*)invitorId
                  completion:(NIMTeamHandler)block

拒绝群邀请(仅限高级群)

- (void)rejectInviteWithTeam:(NSString*)teamId
                   invitorId:(NSString*)invitorId
                rejectReason:(NSString*)rejectReason
                  completion:(NIMTeamHandler)block

主动申请入群(仅限高级群)

- (void)applyToTeam:(NSString *)teamId
            message:(NSString *)message
         completion:(NIMTeamApplyHandler)block

请求完成后,云信服务器会下发一条系统消息给群管理员,管理员可以选择通过或者拒绝申请。

通过申请(仅限高级群)

- (void)passApplyToTeam:(NSString *)teamId
                 userId:(NSString *)userId
             completion:(NIMTeamApplyHandler)block

拒绝申请(仅限高级群)

- (void)rejectApplyToTeam:(NSString *)teamId
                   userId:(NSString *)userId
             rejectReason:(NSString *)rejectReason
               completion:(NIMTeamHandler)block

编辑群组资料

普通成员可以修改自己的群资料,管理员以上权限的群成员可以修改他人群资料以及群组信息。包括:

修改群成员昵称

- (void)updateUserNick:(NSString *)userId
               newNick:(NSString *)newNick
                inTeam:(NSString *)teamId
            completion:(NIMTeamHandler)block

修改群名称

- (void)updateTeamName:(NSString *)teamName
                teamId:(NSString *)teamId
            completion:(NIMTeamHandler)block

修改群头像

- (void)updateTeamAvatar:(NSString *)teamAvatarUrl
                  teamId:(NSString *)teamId
              completion:(NIMTeamHandler) block

修改群介绍

- (void)updateTeamIntro:(NSString *)intro
                 teamId:(NSString *)teamId
             completion:(NIMTeamHandler)block

修改群公告

- (void)updateTeamAnnouncement:(NSString *)announcement
                        teamId:(NSString *)teamId
                    completion:(NIMTeamHandler)block

修改群验证方式

- (void)updateTeamJoinMode:(NIMTeamJoinMode)joinMode
                    teamId:(NSString *)teamId
                completion:(NIMTeamHandler)block

修改被邀请人验证方式

- (void)updateTeamBeInviteMode:(NIMTeamBeInviteMode)beInviteMode
                        teamId:(NSString *)teamId
                    completion:(NIMTeamHandler)block;

修改谁可以邀请其他人入群

- (void)updateTeamInviteMode:(NIMTeamInviteMode)inviteMode
                      teamId:(NSString *)teamId
                  completion:(NIMTeamHandler)block

修改谁可以修改群资料

- (void)updateTeamUpdateInfoMode:(NIMTeamUpdateInfoMode)updateInfoMode
                          teamId:(NSString *)teamId
                      completion:(NIMTeamHandler)block

修改谁可以修改群自定义属性

- (void)updateTeamUpdateClientCustomMode:(NIMTeamUpdateClientCustomMode)clientCustomMode
                                  teamId:(NSString *)teamId
                              completion:(NIMTeamHandler)block

管理群组权限

高级群群主可以对群进行权限管理,权限管理包括:

提升管理员

- (void)addManagersToTeam:(NSString *)teamId
                    users:(NSArray<NSString *>  *)users
               completion:(NIMTeamHandler)completion

移除管理员

- (void)removeManagersFromTeam:(NSString *)teamId
                         users:(NSArray<NSString *>  *)users
                    completion:(NIMTeamHandler)completion

转让群

- (void)transferManagerWithTeam:(NSString *)teamId
                     newOwnerId:(NSString *)newOwnerId
                        isLeave:(BOOL)isLeave
                     completion:(NIMTeamHandler)block

群组成员

获取群成员

- (void)fetchTeamMembers:(NSString *)teamId
              completion:(NIMTeamMemberHandler)block

获取到的群成员只有云信服务器托管的群相关数据,需要开发者结合自己管理的用户数据进行界面显示。

修改自己的群成员自定义属性

- (void)updateMyCustomInfo:(NSString *)newInfo
                    inTeam:(NSString *)teamId
                completion:(NIMTeamHandler)block

修改后,其他在线用户自动同步获得修改后的属性。

用户退群

- (void)quitTeam:(NSString *)teamId
      completion:(NIMTeamHandler)block

用户退群成功后,相关会话信息仍然会保留,但不再能接收关于此群的消息。

禁言用户

- (void)updateMuteState:(BOOL)mute
                 userId:(NSString *)userId
                 inTeam:(NSString *)teamId
             completion:(NIMTeamHandler)block

禁言用户后,云信服务器会下发一条提示该用户被禁言的群组通知消息。

踢出用户

- (void)kickUsers:(NSArray<NSString *> *)users
         fromTeam:(NSString *)teamId
       completion:(NIMTeamHandler)completion

被踢出的用户相关会话信息仍然会保留,但不再能接收关于此群的消息。

解散群

- (void)dismissTeam:(NSString*)teamId
         completion:(NIMTeamHandler)block

群解散后,所有群用户关于此群会话会被保留,但是不能能够在此群会话里收发消息。

群组委托

用户的群信息会在以下条件下更新:

这些操作成功后,云信服务器会推送一条群通知,同时触发 SDK 更新群信息的委托事件:

- (void)onTeamUpdated:(NIMTeam *)team

用户的群信息会在以下条件下移除:

这些操作成功后,云信服务器同样会推送一条群通知,同时触发 SDK 更新群信息的委托事件:

- (void)onTeamRemoved:(NIMTeam *)team

用户的群成员信息会在以下条件下更新

这些操作成功后,云信服务器同样会推送一条群通知,同时触发 SDK 更新群信息的委托事件:

- (void)onTeamMemberChanged:(NIMTeam *)team;

群组通知

群组通知是一种消息类型 ( NIMMessageTypeNotification ) ,用户在创建群或者进入群成功之后,任何关于群的变动,云信服务器都会下发一条群通知消息。群通知消息和其他消息一样,可从 NIMConversationManager 提供的消息查询接口中获取。

群组通知内容 NIMTeamNotificationContent 的字段说明:

群消息推送设置

SDK 提供了修改群消息通知的接口,上层可以通过设置这个选项以影响群消息的通知行为。当设置 notify 为 NO 时,群内消息将不会有 APNS 通知。当然上层也可以使用这一属性来决定收到在线消息时的 APP 表现 (是否响铃等)。

- (void)updateNotifyState:(BOOL)notify
                   inTeam:(NSString *)teamId
               completion:(NIMTeamHandler)block;

群禁言

群组允许管理员将部分成员禁言,或者全体禁言。禁言属于高级功能,需要调用云信服务器接口,客户端 SDK 仅提供查询功能。

自定义拓展

SDK 提供了群信息的拓展接口,开发者可以自行定义内容。

- (void)updateTeamCustomInfo:(NSString *)info
                      teamId:(NSString *)teamId
                  completion:(NIMTeamHandler)block

开发者可以通过 NIMTeam 的两个属性读取拓展信息:

聊天室

在集成聊天室之前,推荐开发者首先阅读这里

聊天室功能概述

聊天室功能对应的管理类为 NIMChatroomManagerNIMChatroomManager 提供了聊天室的业务管理,如进入/退出聊天室,获取相关信息以及权限操作等。目前不支持通过 SDK 接口建立/解散聊天室。

聊天室模型特点:

进入聊天室

用户要在聊天室内说话,必须先调用接口进入此聊天室。用户进入聊天室后,不会收到此聊天室的历史消息推送。如有历史消息需求,可以调用消息查询接口进行显示。

- (void)enterChatroom:(NIMChatroomEnterRequest *)request
           completion:(NIMChatroomEnterHandler)completion;

NIMChatroomEnterRequest 中包含了聊天室的基本数据信息,包括需要进入的聊天室 id 和一些供用户自定义的扩展字段,后续当前用户的所有聊天室消息都会带上登录时设置的扩展字段。

扩展包括:

进入聊天室会建立新的连接,不同的聊天室对应着不同的连接,开发者可以监听连接状态做一些业务处理。

- (void)chatroom:(NSString *)roomId connectionStateChanged:(NIMChatroomConnectionState)state;

当进入聊天室后,再发生掉线问题时,SDK 将自动重连,无需开发者再次调用进入房间接口。

在重连时,可能遇到一些特殊网络错误(如聊天室用户被封禁,聊天室状态异常),会触发以下回调,开发者应该在这个回调中退出聊天室界面。

- (void)chatroom:(NSString *)roomId autoLoginFailed:(NSError *)error;

离开聊天室

离开聊天室时,会断开聊天室对应的连接,并不再收到关于此聊天室的任何消息。

- (void)exitChatroom:(NSString *)roomId
          completion:(NIMChatroomHandler)completion;

当用户被踢或者聊天室关闭时,会触发被踢回调,这个时候也会断开聊天室对应的连接:

- (void)chatroom:(NSString *)roomId beKicked:(NIMChatroomKickReason)reason;

聊天室消息收发

聊天室消息收发接口与普通消息收发统一,在发送消息时指定会话类型为聊天室即可。会话 id 即为聊天室 id。

查询聊天室消息历史

进入聊天室时,不会下发关于聊天室的历史消息,可以通过下面的接口查询聊天室消息历史。

- (void)fetchMessageHistory:(NSString *)roomId
                     option:(NIMHistoryMessageSearchOption *)option
                     result:(NIMFetchChatroomHistoryBlock)completion;

获取聊天室信息

此接口可以远程获取聊天室信息,NIM SDK 不会缓存聊天室信息,开发者需要根据业务自己做好缓存。

- (void)fetchChatroomInfo:(NSString *)roomId
               completion:(NIMChatroomInfoHandler)completion;

修改聊天室信息

此接口可以修改聊天室信息,调用完这个接口后,开发者应该自己修改内存缓存的 NIMChatroom 对象。

此接口需要生成 NIMChatroomUpdateRequest 对象来完成请求。

NIMChatroomUpdateRequest中的 needNotify 参数可以设置成功修改信息后云信服务器是否推送一条修改的聊天室消息通知。

NIMChatroomUpdateRequest中的 notifyExt 参数可以设置推送的聊天室消息通知里带的自定义扩展字段。

- (void)updateChatroomInfo:(NIMChatroomUpdateRequest *)request
                completion:(nullable NIMChatroomHandler)completion;

获取聊天室成员

此接口可以远程获取聊天室成员列表,NIM SDK 不会缓存聊天室成员列表,开发者需要根据业务自己做好缓存。 NIM SDK 提供两种方式获取聊天室成员:

修改自己的聊天室成员信息

此接口可以修改聊天室成员信息,调用完这个接口后,开发者应该自己修改内存缓存的 NIMChatroomMember 对象。

此接口需要生成 NIMChatroomMemberInfoUpdateRequest 对象来完成请求。

NIMChatroomMemberInfoUpdateRequest中的 needNotify 参数可以设置成功修改信息后云信服务器是否推送一条修改的聊天室消息通知。

NIMChatroomMemberInfoUpdateRequest中的 notifyExt 参数可以设置推送的聊天室消息通知里带的自定义扩展字段。

- (void)updateMyChatroomMemberInfo:(NIMChatroomMemberInfoUpdateRequest *)request
                        completion:(nullable NIMChatroomHandler)completion;

聊天室权限管理

聊天室可以调整成员的类型,分固定成员和非固定成员两种,固定成员又分为创建者、管理员、普通成员和受限成员四种。禁言用户和拉黑用户都属于受限用户。

踢出成员

创建者或管理员可以将权限比自己低的用户踢出聊天室

- (void)kickMember:(NIMChatroomMemberKickRequest *)request
        completion:(NIMChatroomHandler)completion;

聊天室通知消息

在聊天室中所有的通知都以消息 NIMMessage 的形式展示,内部 messageObjectNIMNotificationTypeChatroom 类型的 NIMNotificationObject。上层开发在收到具体消息需要进行过滤和显示。目前支持的聊天室消息事件定义在 NIMChatroomEventType 枚举里,具体有:

解析聊天室通知消息的详细步骤:

  1. 判断消息是否为通知消息

    • 判断 NIMMessagemessageType 字段是否为 NIMMessageTypeNotification
  2. 判断通知消息是否为聊天室通知

    • NIMMessagemessageObject 字段强类型转换为 NIMNotificationObject
    • 判断转换后的 NIMNotificationObjectnotificationType 字段是否为 NIMNotificationTypeChatroom
  3. 解析聊天室通知的具体内容

    • NIMNotificationObjectcontent 字段强类型转换为 NIMChatroomNotificationContent
    • 查看转换后 NIMChatroomNotificationContent 的具体字段。

聊天室通知内容 NIMChatroomNotificationContent 的字段说明:

聊天室禁言

聊天室允许管理员将部分成员禁言,或者全体禁言。禁言属于高级功能,需要调用云信服务器接口,客户端 SDK 仅提供聊天室禁言的通知功能。

聊天室禁言通知类型被同样定义在了 NIMChatroomEventType 中,分别为

具体解析步骤请参考之前小节 聊天室通知消息

系统通知

除消息通道外,NIM SDK 还提供系统通知这种通道用于消息之外的通知分发。目前有两种类型:内置系统通知和自定义系统通知。

内置

这是由 NIM SDK 预定义的通知类型,目前仅支持几种群操作的通知,如被邀请入群,SDK 负责这些通知的持久化。所有的内置系统通知都是通过

-(void)onReceiveSystemNotification:(NIMSystemNotification *)notification;

下发给 APP。为了保证整个程序逻辑的一致性,APP 需要针对不同类型的系统通知进行相应的操作。

内置系统通知的本地存储:(以下接口分为全量和过滤,过滤接口需要传入过滤器 NIMSystemNotificationFilter,可以按类型选择获取内置系统通知)

自定义

除内置系统通知外,NIM SDK 也额外提供自定义系统给开发者,方便开发者进行业务逻辑的通知。这个通知既可以由客户端发起也可以由开发者服务器发起。

注意:自定义通知和自定义消息的不同之处在于,自定义消息归属于 NIM SDK 消息体系内,适用于会话,由 SDK 存储在消息数据库中,与 NIM SDK 其他内建消息类型一同展现给用户。而自定义通知主要用于第三方的一些事件状态通知,SDK 不存储,也不解析这些通知。SDK 仅仅负责替第三方传递和通知这些事件,起到透传的作用,收到自定义通知后的持久化工作需要由上层开发负责。

发送自定义通知(客户端)

- (void)sendCustomNotification:(NIMCustomSystemNotification *)notification
                     toSession:(NIMSession *)session
                    completion:(NIMSystemNotificationHandler)completion

客户端发起的自定义通知目前支持自定义如下字段:通知内容(推荐使用 json 组织),推送文案(如果没有则不进行 APNS 推送),是否只发给在线用户。最后一个字段的意义在于区分自定义通知的使用场景。选择只发给在线用户,当目标用户不在线时这条通知会被云信服务器丢弃,这种实现比较适合发送即时通知,如正在输入。反之云信服务器会缓存当前通知(有上限),并在目标用户上线后推送给目标用户。

接收自定义通知

- (void)onReceiveCustomSystemNotification:(NIMCustomSystemNotification *)notification;

APNS 推送

前期准备

[[NIMSDK sharedSDK] registerWithAppID:您的APPKEY
                              cerName:您的推送证书名];
- (void)registerAPNs
{
    if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerForRemoteNotifications)])
    {
        UIUserNotificationType types = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound |      UIRemoteNotificationTypeAlert;
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:types
        categories:nil];
        [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
        [[UIApplication sharedApplication] registerForRemoteNotifications];
    }
    else
    {
        UIRemoteNotificationType types = UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound |        UIRemoteNotificationTypeBadge;
        [[UIApplication sharedApplication] registerForRemoteNotificationTypes:types];
    }
}
- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    [[NIMSDK sharedSDK] updateApnsToken:deviceToken];
}

推送时机

开发者在 发送消息自定义系统通知 时,可以指定是否同时进行推送服务。为了节省不必要的流量开销,只有当接收者的应用切换到后台时,云信推送服务才会开启;如果应用在前台,则不会有推送通知。如果有应用前台通信需求,建议开发者使用 自定义系统通知 ,并监听回调:

- (void)onReceiveCustomSystemNotification:(NIMCustomSystemNotification *)notification;

属性设置

NIM SDK 提供全局 APNS 属性设置,用于设置免打扰时间和推送样式,详细内容可以参考 NIMPushNotificationSetting

NIMPushNotificationSetting *setting =  [[[NIMSDK sharedSDK] apnsManager] currentSetting];
[[[NIMSDK sharedSDK] apnsManager] updateApnsSetting:setting
completion:^(NSError *error) {}];

APNS 多端设置 NIMPushNotificationMultiportConfig

- (NIMPushNotificationMultiportConfig *)currentConfig;
- (void)updateConfig:(NIMPushNotificationMultiportConfig *)config
          completion:(NIMApnsHandler)completion;

当桌面端在线时,可以通过设置 shouldPushNotificationWhenPCOnline 字段,控制是否需要发推送给手机端。

消息推送内容设置

用户在发送消息的时候,设置 NIMMessageapnsContent 属性进行消息推送内容设置。如果不设置 apnsContent 属性,将使用云信内置文案。设置 NIMMessageapnsPayload 可以自定义推送参数。

示例代码:

NIMAudioObject *audioObject = [[NIMAudioObject alloc] initWithSourcePath:filePath];
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = audioObject;
message.apnsContent = @"发来了一段语音";    //对方收到的推送文案

用户在发送自定义系统通知的时候,设置 NIMCustomSystemNotificationapnsContent 属性来定制消息推送内容,同时可以设置 apnsPayload 来配置推送参数。

消息的成员推送选项

用户在发消息的时候,可以通过配置 NIMMessage 里的 apnsMemberOption 字段实现更为复杂的推送逻辑,目前这个字段只能在群会话中生效。

推送问题排查方案

推送配置后在后台仍收不到通知栏提醒可检查如下步骤:

云信IOS推送收不到问题排查方案

用户资料托管

NIMUserManager 提供了用户帐号资料管理。以下几个接口仅当选择云信托管用户资料时有效,如果开发者不希望云信获取自己的用户数据,则需自行维护用户资料。

NIMUserManager 里,使用 NIMUser 对用户进行封装。其中用户信息为 NIMUserInfo 属性。 具体的信息字段由 NIMUserInfoUpdateTag定义。 NIMUserInfoUpdateTag内置了多个常用信息字段(有格式校验)和一个拓展字段 NIMUserInfoUpdateTagEx 供开发者自行拓展。

获取本地用户资料

- (NIMUser *)userInfo:(NSString *)userId;

用户资料除自己之外,不保证其他用户资料实时更新。其他用户数据更新时机为:

获取服务器用户资料

- (void)fetchUserInfos:(NSArray<NSString *> *)users
            completion:(NIMUserInfoBlock)completion

此接口可以批量从服务器获取用户资料,出于用户体验和流量成本考虑,不建议应用频繁调用此接口。对于用户数据实时性要求不高的页面,应尽量调用读取本地缓存接口。

编辑用户资料

- (void)updateMyUserInfo:(NSDictionary *)values completion:(NIMUserBlock)block;

只允许用户编辑自己的资料。此接口可以一次性编辑多个属性。如昵称,头像等,传入的数据键值对是 {@(NIMUserInfoUpdateTag) : NSString},无效数据将被过滤。一些字段有修改格式校验。具体限制为:

属性名 具体字段 类型限制 格式校验
用户昵称 NIMUserInfoUpdateTagNick NSString
用户头像 NIMUserInfoUpdateTagAvatar NSString
用户签名 NIMUserInfoUpdateTagSign NSString
用户性别 NIMUserInfoUpdateTagGender NIMUserGender 只支持指定枚举
用户邮箱 NIMUserInfoUpdateTagEmail NSString 只支持合法邮箱
用户生日 NIMUserInfoUpdateTagBirth NSString yyyy-MM-dd
用户手机 NIMUserInfoUpdateTagBirth NSString 合法手机号 如13588888888、+(86)-13055555555
拓展字段 NIMUserInfoUpdateTagExt NSString

当修改用户资料成功后,会触发回调:

- (void)onUserInfoChanged:(NIMUser *)user;

用户关系托管

NIMUserManager 提供了用户用户关系管理,以及对用户会话的消息设置。在云信中,不是好友也允许聊天。用户关系如果不托管给云信,开发者需要自己在应用服务器维护。

好友关系

黑名单

云信中,黑名单和好友关系是互相独立的,即修改好友关系不会影响黑名单关系,同时,修改黑名单也不会对好友关系进行操作。

- (NSArray<NIMUser *> *)myBlackList;

黑名单列表有本地缓存,缓存会在手动/自动登录后与服务器自动进行同步更新。接口返回的是 NIMUser 列表。 NIMUser 封装了开发者向云信托管的好友ID,对此好友的会话设置(是否需要消息提醒,是否是拉黑用户等), 以及用户的详细信息 NIMUserInfo (需要将用户信息交给云信托管)。

- (void)addToBlackList:(NSString *)userId
            completion:(NIMUserBlock)block;

拉黑成功后,会同时修改本地缓存,并触发回调:

- (void)onBlackListChanged;
- (void)removeFromBlackBlackList:(NSString *)userId
                      completion:(NIMUserBlock)block;

移除成功后,会同时修改本地缓存,并触发回调:

- (void)onBlackListChanged;
- (BOOL)isUserInBlackList:(NSString *)userId;

此接口是根据本地缓存数据来判断是否拉黑的,在调用时请保证本地缓存是正确的(登录后有正常完成数据同步)。

消息提醒

云信中,可以单独设置是否开启某个用户的消息提醒,即对某个用户静音。静音关系和好友关系是互相独立的,修改好友关系不会影响静音关系,同时,修改静音关系也不会对好友关系进行操作。

- (NSArray<NIMUser *> *)myMuteUserList;

静音列表有本地缓存,缓存会在手动/自动登录后与服务器自动进行同步更新。接口返回的是 NIMUser 列表。 NIMUser 封装了开发者向云信托管的好友ID,对此好友的会话设置(是否需要消息提醒,是否是拉黑用户等), 以及用户的详细信息 NIMUserInfo (需要将用户信息交给云信托管)。

- (void)updateNotifyState:(BOOL)notify
                  forUser:(NSString *)userId
               completion:(NIMUserBlock)block;

设置成功之后,同时更新本地缓存数据。

- (BOOL)notifyForNewMsg:(NSString *)userId;

此接口是根据本地缓存数据来判断是否有消息提醒的,在调用时请保证本地缓存是正确的(登录后有正常完成数据同步)。

当修改用户资料成功后,会触发回调:

- (void)onUserInfoChanged:(NIMUser *)user;

文档转码

文档转码功能可以在 PC 端提交文件转码任务,将 ppt 和 pdf 等文档转码为各种清晰度的图片存储在云端,在移动端获取、下载使用或者删除转码后的文档。

文档转码接口

- (void)fetchMyDocsInfo:(nullable NSString *)lastDocId
                  limit:(NSUInteger)limit
             completion:(nullable NIMDocTranscodingFetchCompleteBlock)completion

在 PC 端提交文档转码任务后,该用户可以通过该接口获取自己的转码文档列表。

其中:

lastDocId 最后一个文档的锚点,不包括此文档。填 nil 会从最新提交的转码文档开始往前查询。

limit 是拉取文档的最大个数,每次拉取的个数不能超过 30。

拉取的结果通过 completion 回调给应用,其声明如下:

typedef void(^NIMDocTranscodingFetchCompleteBlock)(NSError * __nullable error, NSArray<NIMDocTranscodingInfo *> * __nullable infos)

如果拉取成功则 error 为 nil,可以通过 infos 获取拉取到的文档列表。

- (void)inquireDocInfo:(NSString *)docId
            completion:(nullable NIMDocTranscodingInquireCompleteBlock)completion

文档的提交者和其他用户可以通过文档转码任务提交时 SDK 返回的文档 id docId 查询该文档的转码信息。

查询的结果通过 completion 回调给应用,其声明如下:

typedef void(^NIMDocTranscodingInquireCompleteBlock)(NSError * __nullable error, NIMDocTranscodingInfo * __nullable info)

如果查询成功则 error 为 nil,可以通过 info 获取查询到的文档信息。

拉取或查询到的文档信息都在 NIMDocTranscodingInfo 中。

可以查询到转码文档的 id,名称,源文档类型、大小、下载路径,转码目标图像的类型,转码状态等。发起文档转码时的附带信息 ext 是 PC 端提交文档转码任务时传入的额外信息。

如果文档转码失败,可以通过 transcodingFlag 定位具体失败原因。

如果文档转码成功,可以通过指定清晰度、页码等获得如下几个信息:

某清晰度的转码后文件总尺寸

- (UInt64)transcodedTotalSize:(NIMDocTranscodingQuality)quality

返回转码后某清晰度的所有图片的总尺寸,单位是字节;

某清晰度转码后图片的长宽信息

- (CGSize)transcodedImagesSize:(NIMDocTranscodingQuality)quality

返回转码后某清晰度的图片的长宽信息;

转码后某清晰度的文件页码对应的下载 url

- (nullable NSString *)transcodedUrl:(NSUInteger)pageNumber
                           ofQuality:(NIMDocTranscodingQuality)quality

返回的 url 可以直接下载使用。

- (void)deleteDoc:(NSString *)docId
       completion:(nullable NIMDocTranscodingDeleteCompleteBlock)completion

文档转码任务的提交者可以通过该接口删除云端的转码文档,删除的结果通过 completion 回调给应用,其声明如下:

typedef void(^NIMDocTranscodingDeleteCompleteBlock)(NSError * __nullable error)

如果删除成功则 error 为 nil。

音视频网络通话

SDK 的音视频网络通话管理类是 NIMNetCallManager,提供基于网络的点对点视频通话和语音通话功能,还提供多人视频和音频会议功能,支持通话中音视频设备控制和实时音视频模式切换,支持音视频采集数据回调以实现美颜和变声等自定义功能。

音视频网络通话流程

- (void)start:(NSArray<NSString *> *)callees
         type:(NIMNetCallMediaType)type
       option:(NIMNetCallOption *)option
   completion:(NIMNetCallStartHandler)completion

当前只支持点对点通话,callees 只接收一个被叫。

发起通话需要指定类型,在成功建立通话之前不允许进行通话类型切换。

发起通话相关参数在 option 中指定,其中:

发起结果由 NIMNetCallStartHandler 返回:

typedef void(^NIMNetCallStartHandler)(NSError *error, UInt64 callID)

如果发起成功,返回的 error 为 nil,callID 用于唯一标识一通网络通话,后续的操作及回调均由此区分不同通话。

- (void)onReceive:(UInt64)callID
             from:(NSString *)caller
             type:(NIMNetCallMediaType)type
          message:(NSString *)extendMessage

在成功建立通话之前不允许进行通话类型切换。

其中 extendMessage 透传主叫发起通话时携带的额外信息。

- (void)response:(UInt64)callID
          accept:(BOOL)accept
          option:(NIMNetCallOption *)option
      completion:(NIMNetCallResponseHandler)completion

可以通过 option 指定期望的发送视频清晰度和设置裁剪开关。

响应结果由 NIMNetCallStartHandler 返回:

typedef void(^NIMNetCallResponseHandler)(NSError *error, UInt64 callID)

如果响应成功,返回的 error 为 nil。

在多端登录情况下,如果该通话已被该帐号其他端处理,error 携带错误码NIMLocalErrorCodeNetCallOtherHandled

- (void)onResponse:(UInt64)callID
              from:(NSString *)callee
          accepted:(BOOL)accepted
- (void)onResponsedByOther:(UInt64)callID
                  accepted:(BOOL)accepted

对于已经被其他端处理过的通话,本端不能再做接听、拒绝或挂断操作。

- (void)onCall:(UInt64)callID
        status:(NIMNetCallStatus)status

收到 NIMNetCallStatusDisconnect 时无需调用 hangup: 挂断该通话。

- (void)control:(UInt64)callID
           type:(NIMNetCallControlType)type

通话控制信息用于方便通话双方沟通,可以选择性使用

控制字段 含义
NIMNetCallControlTypeOpenAudio 通知对方本端取消了静音
NIMNetCallControlTypeCloseAudio 通知对方本端开启了静音
NIMNetCallControlTypeOpenVideo 通知对方本端打开了摄像头
NIMNetCallControlTypeCloseVideo 通知对方本端关闭了摄像头
NIMNetCallControlTypeToVideo 请求对方切换到视频模式
NIMNetCallControlTypeAgreeToVideo 同意切换到视频模式,用于切到视频模式需要对方同意的场景
NIMNetCallControlTypeRejectToVideo 拒绝切换到视频模式,用于切到视频模式需要对方同意的场景
NIMNetCallControlTypeToAudio 通知对方本端切换到了音频模式
NIMNetCallControlTypeBusyLine 被叫通知主叫本端占线,用于主叫需要播放忙音的场景
NIMNetCallControlTypeNoCamera 通知对方本端摄像头不可用
NIMNetCallControlTypeBackground 通知对方本端切换到了后台
NIMNetCallControlTypeFeedabck 被叫通知主叫已经收到了通话请求,用于主叫需要确认被叫收到请求再播放回铃音的场景
- (void)onControl:(UInt64)callID
             from:(NSString *)user
             type:(NIMNetCallControlType)control
- (void)hangup:(UInt64)callID

在发起通话请求时,如果 SDK 尚未返回 callID,可传入 0 挂断该通话。

被叫在响应呼叫之前不要调用挂断接口。

- (void)onHangup:(UInt64)callID
              by:(NSString *)user

收到该回调后无需调用 hangup: 结束通话

当前通话信息

- (UInt64)currentCallID

如果没有正在进行中的通话 SDK 返回 0。

- (void)onNetStatus:(NIMNetCallNetStatus)status
               user:(NSString *)user

通常用于在 UI 上展现网络信号。user 表示本端对应于该用户的下行网络状况。如果 user 是自己,表示自己的上行网络状况。

- (NIMNetCallNetStatus)netStatus:(NSString *)user

如果没有正在进行中的通话,则返回值没有参考意义。

- (void)onLocalPreviewReady:(CALayer *)layer

本地摄像头初始化完成时返回 layer,可以用如下示例代码展现本地预览画面:

- (void)onLocalPreviewReady:(CALayer *)layer
{
    if (self.localVideoLayer) {
        [self.localVideoLayer removeFromSuperlayer];
    }
    self.localVideoLayer = layer;
    layer.frame = self.localView.bounds;
    [self.localView.layer addSublayer:layer];
}
- (CALayer *)localPreviewLayer

当没有进行中的网络通话,或者摄像头尚未初始化完成时返回 nil。

- (void)onRemoteYUVReady:(NSData *)yuvData
                   width:(NSUInteger)width
                  height:(NSUInteger)height
                    from:(NSString *)user

每获取到一帧对端画面都会回调,其中yuvData是紧凑的 YUV 数据 (stride 与画面宽度相同)。

可以通过user区分不同的对端用户。

将 YUV 数据直接用 OpenGL 渲染,比从 onRemoteImageReady: 得到的 image 贴图节省 CPU 资源。

- (void)onRemoteImageReady:(CGImageRef)image

如果实现了该委托,每获取到一帧对端画面都会回调,可以将 image 转换成 UIImage 后直接在 UIImageView 里面填充。

如果已经使用 onRemoteYUVReady:width:height:from 得到的 YUV 数据渲染画面,不要再实现该委托以优化性能。

- (void)onNetCallRecordingInfo:(NIMNetCallRecordingInfo *)info

提供服务器录制的音频文件和视频文件信息。

-(void)onMyVolumeUpdate:(UInt16)volume
- (void)onSpeakingUsersReport:(nullable NSArray<NIMNetCallUserInfo *> *)report

如果 report 为空,表示没有说话的人。

话单通知

当结束网络通话后,云信服务器会下发一条话单通知,用来表示这次通话的信息。 其中定义了:

解析话单通知消息的详细步骤:

  1. 判断消息是否为通知消息

    • 判断 NIMMessagemessageType 字段是否为 NIMMessageTypeNotification
  2. 判断通知消息是否为话单通知

    • NIMMessagemessageObject 字段强类型转换为 NIMNotificationObject
    • 判断转换后的 NIMNotificationObjectnotificationType 字段是否为 NIMNotificationTypeNetCall
  3. 解析话单通知的具体内容

    • NIMNotificationObjectcontent 字段强类型转换为 NIMNetCallNotificationContent
    • 查看转换后 NIMNetCallNotificationContent 的具体字段。其中,callType 字段为话单通知的具体通话类型。 eventType 字段表示具体的通话事件类型。

多人会议

与点对点通话的流程不同,多人会议暂不支持呼叫、推送和挂断等服务,只提供基本的预订、加入和离开会议接口。

- (void)reserveMeeting:(NIMNetCallMeeting *)meeting
            completion:(NIMNetCallMeetingHandler)completion

需要先预订,本人和其他人才能加入会议。

会议通过 meetingname 字段做标识;可以通过 meeting 的 扩展字段 ext 在会议的创建和加入之间传递额外信息。

同一个会议名称,只在会议使用完以后才可以重复使用,开发者需要保证不会出现重复预订某会议名称而不使用的情况。

预订会议的结果通过 completion 返回。

- (void)joinMeeting:(NIMNetCallMeeting *)meeting
         completion:(NIMNetCallMeetingHandler)completion

会议通过 meetingname 字段做标识。

可以通过 actor 指定加入时的角色,非发言者 (观众)不发送音视频数据。

加入成功以后,可以通过 callID 获取当前通话的 call id 。

meetingtypepreferredVideoQuality 等参数含义与点对点通话相同。

加入会议的结果通过 completion 返回。

- (void)leaveMeeting:(NIMNetCallMeeting *)meeting

当所有加入的人都离开了某会议以后,该会议对应的名称才可以被重复预订。

- (BOOL)setMeetingRole:(BOOL)actor
- (BOOL)setAudioMute:(BOOL)mute 
             forUser:(NSString *)uid

静音后将听不到该用户的声。

需要在用户加入以后才能进行设置,该接口也可用于点对点双人通话。

- (BOOL)setVideoMute:(BOOL)mute 
             forUser:(NSString *)uid

拒绝后将没有该用户视频数据回调。

需要在用户加入以后才能进行设置,该接口也可用于点对点双人通话。

- (void)onUserJoined:(NSString *)uid
             meeting:(NIMNetCallMeeting *)meeting

通知上层有其他用户加入了会议。

- (void)onUserLeft:(NSString *)uid
           meeting:(NIMNetCallMeeting *)meeting

通知上层有其他用户离开了会议。

- (void)onMeetingError:(NSError *)error
               meeting:(NIMNetCallMeeting *)meeting

一些异常情况可能会引起会议出错,请在收到该回调以后主动离开会议。

通话中的设备控制

- (BOOL)setMute:(BOOL)mute

静音后对端将听不到本端的声音。

- (BOOL)setSpeaker:(BOOL)useSpeaker

用于在扬声器和听筒间切换。

- (void)switchCamera:(NIMNetCallCamera)camera

用于在前后摄像头之间切换。

摄像头切换完成后,SDK通过以下回调通知应用:

- (void)onCameraSwitchedTo:(NIMNetCallCamera)camera

如果应用开启了视频采集数据回调,需要自己实现处理后的画面的绘制,则需要在该回调中对前置摄像头的画面做水平镜像翻转。

- (BOOL)setCameraDisable:(BOOL)disable

关闭摄像头以后对方将收不到自己的视频画面。

- (void)switchType:(NIMNetCallMediaType)type

用于在语音模式和视频模式之间切换。如果需要对方接受才能切换,请使用 control:typeonConrtol:from:type 进行协商,达成一致后再调用该接口进行切换。

通话中的编解码控制

- (BOOL)setVideoMaxEncodeBitrate:(NSUInteger)bitrate

可以在视频通话过程中实时改变视频编码码率,以满足不同网络状况和使用场景需求。如果用户尚未加入通话,则无法设置。

- (BOOL)switchVideoEncoder:(NIMNetCallVideoCodec)codec
- (BOOL)switchVideoDecoder:(NIMNetCallVideoCodec)codec

可以在视频通话过程中实时切换软硬件编解码器。硬件编解码设置仅在 iOS 8.0 及以上系统有效。如果用户尚未加入通话,则无法设置。

- (BOOL)switchVideoQuality:(NIMNetCallVideoQuality)quality

可以在视频通话过程中实时切换视频质量。如果用户尚未加入通话,则无法设置。

通话中音视频录制

通话建立以后,SDK 支持将本端与对端的音视频图像和声音录制下来,保存成本地 mp4 格式文件。

- (BOOL)startRecording:(nullable NSURL *)filePath
          videoBitrate:(UInt32)videoBitrate
                   uid:(NSString *)userId

只有通话连接建立以后才允许开始录制。

可以指定录制文件的路径 filePath,SDK 不负责创建目录,请确保文件路径的合法性;也可以不指定,由 SDK 自己选择文件路径。

如果对录制文件大小有要求,可以指定录制文件的视频码率 videoBitrate;也可以不指定,由 SDK 自己选择合适的码率。

需要指定开始录制用户的 ID userId

- (BOOL)stopRecordingWithUid:(NSString *)userId

需要指定结束录制用户的 ID userId

- (void)onRecordStarted:(UInt64)callID
                fileURL:(NSURL *)fileURL
                    uid:(NSString *)userId

表示本地录制成功开始,携带录制对应的网络通话 ID 和录制文件路径以及用户 ID 信息。

- (void)onRecordError:(NSError *)error
               callID:(UInt64)callID
                  uid:(NSString *)userId

表示本地录制发生了错误。

- (void)onRecordStopped:(UInt64)callID
                fileURL:(NSURL *)fileURL
                    uid:(NSString *)userId

表示本地录制成功结束,携带录制对应的网络通话 ID 和录制文件路径以及用户 ID 信息。

通话录音

通话建立以后,SDK 支持录制通话中所有参与者的声音,包含混音任务播放的声音,保存成本地 aac 或 wav 格式文件。

- (BOOL)startAudioRecording:(nullable NSURL *)filePath
                      error:(NSError * __nullable *)error

可以指定录音文件的路径 filePath,不包含文件类型后缀。包含文件类型后缀的完整文件路径可以在开始录制以后通过 currentAudioRecordingFilePath 查询。

SDK 不负责创建目录,请确保文件路径的合法性;也可以不指定,由 SDK 自己选择文件路径。

如果开始通话录音失败,error 回填错误码。

- (void)stopAudioRecording
- (nullable NSURL *)currentAudioRecordingFilePath

如果没有进行中的通话录音则返回 nil。

音视频采集数据回调与发送

SDK 支持音视频采集数据回调与发送,可供应用实现美颜和变声等自定义功能。

在加入多人会议房间时,在 meetingoption 参数中指定视频采集数据回调 block videoHandler,SDK 采集到的视频画面都会通过它回调给应用。videoHandler 的类型声明如下:

typedef void(^NIMNetCallVideoSampleBufferHandler)(CMSampleBufferRef sampleBuffer)

回调的 sampleBuffer 携带时间戳和 kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange 格式的 CVPixelBuffer 图像。

应用可以获取图像数据进行预处理,不允许更改图像的尺寸。

应用处理完的视频画面效果无法通过 onLocalPreviewReady: 中的 layer 自动绘制,因为该 layer 只展现摄像头采集的原始画面效果。应用需要自己实现处理后数据的绘制,并在 onCameraSwitchedTo: 回调中处理前置摄像头的镜像翻转问题。

处理完的图像和回调的时间戳一起封装为 CMSampleBufferRef 格式的数据,调用以下接口发送出去:

- (nullable NSError *)sendVideoSampleBuffer:(CMSampleBufferRef)buffer

注意:处理完的画面封装为 CMSampleBufferRef 时,需要填入回调时该画面对应的时间戳,否则对端的视频播放时序会被破坏。

注意:SDK 只接受 sampleBuffer 为封装了 kCVPixelFormatType_32BGRA 或者 kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange 的 CVPixelBuffer 的视频画面发送。

iOS网络通话本地回调画面(美颜)相关的格式转换

在加入多人会议或者互动直播房间时,在 meetingoption 参数中指定视频采集数据回调block audioHandler,SDK 采集到的音频数据都会通过它回调给应用。audioHandler 的类型声明如下:

typedef NSUInteger(^NIMNetCallAudioSamplesHandler)(SInt16 *audioSamples, NSUInteger samplesNumber, Float64 sampleRate)

其中 audioSamples 是麦克风采集到的语音原始 PCM 采样数据,应用处理完的数据也需要通过该字段回填,回填的数据的采样点数通过该回调的返回值告知 SDK。

注意:回填数据采样点数不允许超过回调的数据采样点数;如果需要发送较多数据,可以在每次回调中发送最多 samplesNumber 个采样点数据。

建议异步地处理语音数据,并且在改回调中发送之前已经异步处理完的语音数据。

文件混音

文件混音是在音视频通话和互动直播过程中,将本地的音频文件与本端采集的声音数据混音后发送出去,同时在本端播放出来的功能。

该功能可以处理系统原生支持语音播放的音频文件类型,如 aac、mp3、mp4 和 wav 等。

该功能支持设置文件播放次数、发送音量和播放音量,支持通话中开始、暂停、恢复、更新及停止文件混音。

混音任务的具体设置通过 NIMNetCallAudioFileMixTask 指定。

播放文件的路径通过实例化接口传递:

- (instancetype)initWithFileURL:(NSURL *)url

通过 numberOfLoops 指定该文件循环播放次数,负数表示无限循环,非负数表示总共播放 numberOfLoops + 1 次,可以实时更新,更新后重新计数。

通过 sendVolume 指定混音时的发送语音音量, 接受输入值为 0.0 到 1.0,可以实时更新。

通过 playbackVolume 指定混音时的播放语音音量, 接受输入值为 0.0 到 1.0,可以实时更新。

将实例化的文件混音任务通过以下接口开始任务:

- (nullable NSError *)startAudioMix:(NIMNetCallAudioFileMixTask *)task

如果成功开始混音任务了, 返回 nil。开始新的任务会结束正在进行中的任务。

任务成功开始后,可以实时获取当前任务信息:

- (nullable NIMNetCallAudioFileMixTask *)currentAudioMixTask

如果没有进行中的任务则返回 nil。

可以在任务进行中通过更新接口实时更新文件播放次数、发送音量和播放音量等:

- (nullable NSError *)updateAudioMix:(NIMNetCallAudioFileMixTask *)task

如果成功更新了任务, 返回 nil。更新循环播放次数后,SDK 重新计算播放次数。

- (BOOL)pauseAudioMix

任务暂停以后,通过该接口从暂停处恢复任务:

- (BOOL)resumeAudioMix

通过该接口停止进行中的任务:

- (BOOL)stopAudioMix

混音任务完成后,通过以下接口通知应用:

- (void)onAudioMixTaskCompleted

本地视频截图

本地截图,截取自己下一帧待发送的画面

- (void)snapshotFromLocalVideoCompletion:(void(^)(UIImage * __nullable image))result;

result 为返回的截图结果,如果截图失败 result 中 image 为 nil。

网络探测

网络探测是一个辅助的诊断工具,可探测音视频通话网络的连通性、丢包率和延迟等信息。

网络探测通过 NIMAVChatNetDetectManager 管理类提供服务。

- (UInt64)startDetectTask:(nullable NIMAVChatNetDetectCompleteBlock)completion

该接口返回任务 id,可以用来标识或停止已经开始的任务。

网络探测结果通过 completion 回调给应用。

网络探测结果回调声明如下:

typedef void(^NIMAVChatNetDetectCompleteBlock)(NIMAVChatNetDetectResult *result)

返回的 result 中:

taskId 是任务标识,与开始任务接口返回的 id 对应;

error 是任务执行的结果,如果执行成功为 nil,如果执行失败,result 中的 taskId 以外的其他字段均无意义;

lossRate 是丢包率百分比;

rttMaximal 是 rtt 最大值;

rttMinimal 是 rtt 最小值;

rttAverage 是 rtt 平均值;

rttMeanDeviation 是 rtt 偏差值 mdev;

expandInfo 是 扩展信息。

在上述返回的字段中,lossRate、rttAverage、rttMeanDeviation这三个值最能反应当前客户端的实际网络情况。由这三个值可以计算出当前的网络状况指数:

网络状况指数 = (lossRate/20)*50% +(rttAverage/1200)*25% +(rttMeanDeviation/150)*25%

经过我们的反复测试,现提供三个网络状况指数节点

网络状况指数节点 lossRate(%) rttAverage(ms) rttMeanDeviation(ms) 网络状况指数
A 3 500 50 0.2625
B 10 800 80 0.55
C 20 1200 150 1

备注:

1.当网络状况指数≤0.2625时,网络状况非常好,音视频通话流畅;

2.当0.2625<网络状况指数≤0.55时,网络状况好,音视频通话偶有卡顿;

3.当0.55<网络状况指数≤1时,网络状况差,音频通话流畅;

4.当网络状况指数>1时,网络状况非常差,音频通话偶有卡顿。

可以通过开始任务接口返回的 id 停止一个正在进行的任务:

- (void)stopDetectTask:(UInt64)taskId

网络探测日志记录在单独的文件中,通过以下接口获取该文件路径:

- (NSString *)logFilepath

互动直播

云信提供音视频直播与实时互动连麦功能:

互动直播相关概念

互动直播接入流程

云信提供简单的互动直播和连麦接口,只需要创建并加入互动房间即可以实现直播推流;连麦者使用相同的房间名加入互动房间即可以实现实时连麦互动。

互动直播相关接口都由 NIMNetCallManager 提供。

用创建接口创建一个互动直播房间:

- (void)reserveMeeting:(NIMNetCallMeeting *)meeting
            completion:(NIMNetCallMeetingHandler)completion

需要在 meeting 参数中指定互动直播的唯一标识 房间名称 name

房间创建成功后,主播首先使用加入接口进入房间:

- (void)joinMeeting:(NIMNetCallMeeting *)meeting
         completion:(NIMNetCallMeetingHandler)completion

主播加入时需要在 meetingoption 参数中打开互动直播开关 enableBypassStreaming,并指定推流地址 bypassStreamingUrl(指定推流地址的一端被认为是互动的主播)。

主播可以设置互动直播视频画面混屏模式 bypassStreamingVideoMixMode,在预设的几种直播混频模式 NIMNetCallVideoMixMode 中选择一种,图文介绍

主播可以开启互动直播的服务器录制 bypassStreamingServerRecording。该功能需要开通才能使用。

主播加入房间的 completion 正常返回后,即可以在观众端使用直播拉流播放器观看主播直播。

连麦者使用主播相同的房间名加入房间,需要打开互动直播开关 enableBypassStreaming,不要指定推流地址,调用加入接口 joinMeeting: completion: 进入房间。连麦者成功加入房间后,观众端就可以观看到双人实时连麦互动直播了。

连麦双方需要实现本地画面和远端画面的渲染:

onLocalPreviewReady: 回调时渲染本地画面;

onRemoteYUVReady:width:height:from: 回调时渲染远端画面。

请参考网络通话相关章节和云信 Demo 源码的实现。

主播可以调用切换直播推流地址接口,实时切换推流地址,适配某些视频流平台的防盗链机制。

- (BOOL)switchBypassStreamingUrl:(NSString *)url
- (BOOL)setBypassStreamingEnabled:(BOOL)enabled

设置结果通过以下回调通知应用:

- (void)onSetBypassStreamingEnabled:(BOOL)enabled result:(nullable NSError *)result

如果没有错误, result 为 nil。

加入房间以后,收到其他用户加入的回调 onUserJoined:meeting:,表示连麦正式开始。

房间里的用户收到其他用户离开的回调 onUserLeft:meeting:,表示连麦结束,此时连麦者应该主动退出房间,主播不要退出房间。

一些异常情况可能会引起互动直播出错,请在收到 onMeetingError:meeting:回调以后主动离开,或者重新加入房间。

调用 leaveMeeting: 接口退出互动直播房间。

当所有加入房间的用户都已离开,就可以复用该房间名重新创建了。

实时会话 (白板)

SDK 的实时会话管理类是 NIMRTSManager,提供数据通道 (可靠 TCP 传输通道/语音通道) 以满足实时会话的需求,用于在线白板教学和文件传输等实时场景,其中 TCP 通道可以同时存在多个,语音通道全局只能有一个,并且与网络通话功能互斥。

实时会话流程

- (NSString *)requestRTS:(NSArray<NSString *> *)callees
                services:(NSUInteger)types
                  option:(NIMRTSOption *)option
              completion:(NIMRTSRequestHandler)completion

需要在 callees 中指定被叫用户列表,当前只支持一个被叫。

需要指定服务类型,为 NIMRTSService 的组合,如果要同时发起可靠传输通道和音频通话,使用 NIMRTSServiceReliableTransfer | NIMRTSServiceAudio

可以指定发起会话附带选项 option:

每一通发起请求都会返回会话 ID sessionID,用于后续操作和回调中唯一标识这通请求。

发起结果由 NIMRTSRequestHandler返回:

typedef void(^NIMRTSRequestHandler)(NSError * __nullable error,NSString * __nullable sessionID,UInt64 channelID)

如果发起成功,返回的 error 为 nil。

- (void)onRTSRequest:(NSString *)sessionID
                from:(NSString *)caller
            services:(NSUInteger)types
             message:(NSString *)extendMessage

用户每收到一个实时会话请求都由唯一的 sessionID 标识,用于后续操作和回调中指定这通请求。

extendMessage 是主叫传递过来的附加信息。

- (void)responseRTS:(NSString *)sessionID
             accept:(BOOL)accept
             option:(NIMRTSOption *)option
         completion:(NIMRTSResponseHandler)completion

用于接受或拒绝一通实时会话请求。

在开启了服务器录制功能的 APP 中, 可用 option 中的 disableRecord 选项禁用该通实时会话的录制功能。

响应结果由 NIMRTSResponseHandler 返回:

typedef void(^NIMRTSResponseHandler)(NSError * __nullable error,NSString * __nullable sessionID,UInt64 channelID)

如果响应成功,返回的 error 为 nil。

- (void)onRTSResponse:(NSString *)sessionID
                 from:(NSString *)callee
             accepted:(BOOL)accepted

被叫拒绝接听时,主叫不需要再调用 terminateRTS: 接口。

- (void)onRTSResponsedByOther:(NSString *)sessionID
                     accepted:(BOOL)accepted

对于已经被其他端处理过的实时会话请求,本端不能再做接听、拒绝或挂断操作。

- (void)onRTS:(NSString *)sessionID
      service:(NIMRTSService)type
       status:(NIMRTSStatus)status
        error:(NSError *)error;

如果该实时会话包含多个服务,会有多个回调分别表示各个服务的状态。

- (BOOL)sendRTSData:(NSData *)data
               from:(NSString *)sessionID
                 to:(NSString *)userID
               with:(NIMRTSService)service

发送的数据长度不允许超过 50 KB,推荐不超过 4 KB。

发送数据的周期建议控制在 50 ms 以上,否则可能引起延迟增大等问题。

可以指定发送数据的目标用户 ID,也可以不指定用户表示广播给所有其他用户。

需要指定发送数据的服务通道,现在只支持 TCP 通道。

- (void)onRTSReceive:(NSString *)sessionID
                data:(NSData *)data
                from:(NSString *)user
              withIn:(NIMRTSService)channel
- (void)sendRTSControl:(NSString *)controlInfo
            forSession:(NSString *)sessionID

实时会话控制指令用于方便双方沟通信息,可以选择性使用。

- (void)onRTSControl:(NSString *)controlInfo
                from:(NSString *)user
          forSession:(NSString *)sessionID
- (void)onRTSRecordingInfo:(NIMRTSRecordingInfo *)info
                forSession:(NSString *)sessionID;

包含了一通实时会话的服务器录制文件信息,仅在启用了服务器录制的 APP 中有效。

- (void)terminateRTS:(NSString *)sessionID

被叫在响应请求之前不要调用挂断接口。

- (void)onRTSTerminate:(NSString *)sessionID
                    by:(NSString *)user

音频控制

- (BOOL)setMute:(BOOL)mute

静音后对端将听不到本端的声音。

- (BOOL)setSpeaker:(BOOL)useSpeaker

用于在扬声器和听筒间切换。

服务器录制文件格式

在开启了相关功能后,服务器为实时会话中的每个成员发送的所有数据录制一个单独的文件,其中写入数据的格式根据云信客户端 SDK 版本的不同有所区别:

用户发送的数据包直接被写入文件,不包含任何数据包头

用户发送每一个数据包前增加包头(包长字段和时间戳字段)后再写入录制文件,每一个写入文件的包格式如下:

| 包长 | 时间戳 | 数据 |

包长:4字节,写入文件的整个包的字节长度,包含包长和时间戳字段的长度

时间戳:4字节,从会话开始到服务器收到该数据经历的相对时间,单位是毫秒

数据:客户端调用 SDK 发送的实时会话数据

多人实时会话

与点对点实时会话的流程不同,多人实时会话暂不支持呼叫、推送和挂断等服务,只提供基本的预订、加入和离开会话接口。

多人实时会话也不配套提供语音通话通道,如果需要,可以与多人会议功能组合使用。

多人实时会话服务由 NIMRTSConferenceManager 提供,基本的流程如下:

多人实时会话流程

- (nullable NSError *)reserveConference:(NIMRTSConference *)conference

需要先预订,本人和其他人才能加入多人实时会话。

多人实时会话通过 conferencename 字段做标识;可以通过 conference 的扩展字段 ext 在多人实时会话的创建和加入之间传递额外信息。

同一个会话名称,只在会话使用完以后才可以重复使用,开发者需要保证不会出现重复预订某会话名称而不使用的情况。

该接口的返回值只是表示 SDK 是否接受本次预订的请求,并不表示预订是否成功,预订结果通过以下接口回调:

- (void)onReserveConference:(NIMRTSConference *)conference
                     result:(nullable NSError *)result

如果预订成功, result 为 nil。

- (nullable NSError *)joinConference:(NIMRTSConference *)conference

多人会话的操作对象为 conference

会话通过 name 字段做标识。

需要指定接收数据的 dataHandler 以接收其他用户发来的实时会话数据。

可以通过 serverRecording 开启本次实时会话的服务器的数据录制。该功能需要服务器提前开启才能使用。录制文件的格式与点对点实时会话相同。

加入成功以后,可以通过 channelID 获取当前通话对应的服务器的频道 id,可以通过 serverRecordName 获取服务器录制的文件名称。

该接口的返回值只是表示 SDK 是否接受本次加入的请求,并不表示加入是否成功,加入结果通过以下接口回调:

- (void)onJoinConference:(NIMRTSConference *)conference
                  result:(nullable NSError *)result

如果预订成功, result 为 nil。

- (BOOL)sendRTSData:(NIMRTSConferenceData *)data

其中 data 的:

conference 字段是需要发送数据的实时会话。

data 字段是需要发送的数据。数据长度不允许超过50KB,推荐不超过4KB,发送数据的周期建议控制在50ms以上。

uid 字段是发送的目标,如果需要广播发送,请把该字段留空。

接收数据通过加入会话时 conferencedataHandler 回调。回调的 data 中:

conference 字段是数据来自的会话。

data 字段是接收到数据。

uid 字段是发送者的 id。

- (void)onLeftConference:(NIMRTSConference *)conference
                   error:(NSError *)error

当某些异常情况发生导致会话断开时,SDK 通过该回调通知应用。

- (void)onUserJoined:(NSString *)uid
          conference:(NIMRTSConference *)conference

当有用户加入会话时,已经在会话中的用户会收到该回调。

- (void)onUserLeft:(NSString *)uid
        conference:(NIMRTSConference *)conference
            reason:(NIMRTSConferenceUserLeaveReason)reason

当会话中的用户主动或异常离开时,其他用户会收到该回调。

- (nullable NSError *)leaveConference:(NIMRTSConference *)conference

当所有加入的人都离开了某会话以后,该会话对应的名称才可以被重复预订。

API 文档