容聯(lián): IM+短信驗(yàn)證+語(yǔ)音驗(yàn)證碼....功能
容聯(lián)iOS開發(fā)指南
http://www.yuntongxun.com/api/im/iosWiki#point_box
1、iOS集成指南
1.1、導(dǎo)入sdk
開發(fā)者集成云通訊sdk,需要:
(1)先下載sdk,解壓之后目錄如圖所示例:
Yuntx_IMLib_V5.0.1r.a庫(kù)是靜態(tài)庫(kù),Manager文件夾是主調(diào)函數(shù)聲明,Delegate文件夾是回調(diào)函數(shù)聲明。
(2)然后導(dǎo)入sdk。將解壓后的文件夾(Yuntx_IMLib_SDK)拖入您的工程中,并勾選上Destination,如圖所示:
點(diǎn)擊finish,完成SDK添加,工程目錄如下圖所示:
注意:由于iOS編譯的特殊性,靜態(tài)庫(kù)中包含i386、x86_64、armv7、arm64平臺(tái),導(dǎo)致SDK的靜態(tài)庫(kù)(.a文件)會(huì)比較大,但您實(shí)際集成編譯出ipa后,只會(huì)增加2MB左右。
1.2、設(shè)置工程屬性
向Build Phases -> Link Binary With Libraries 中添加系統(tǒng)依賴庫(kù),操作步驟如下所示:
按照上圖,點(diǎn)擊加號(hào)后,顯示下圖:在搜索框中輸入需要的依賴庫(kù)名稱,如添加sqlite庫(kù),按圖步驟,點(diǎn)擊Add添加依賴庫(kù)成功
SDK需要添加系統(tǒng)依賴庫(kù)如下:
libicucore.dylib
libsqlite3.dylib
libz.dylib
CoreTelephony.framework
MediaPlayer.framework
CFNetwork.framework
SystemConfiguration.framework MobileCoreServices.framework
AudioToolbox.framework
CoreGraphics.framework
AVFoundation.framework
添加完依賴庫(kù)之后,第一步即完成,可以進(jìn)行下一步了。
編譯設(shè)置:
因?yàn)镾DK采用的是C代碼編寫,所以需要應(yīng)用設(shè)置混編設(shè)置:
1、如圖選擇stdlibc++模式編譯
2、在第一次調(diào)用的地方,如demo中,更改AppDelegate.m文件的后綴為.mm如果不設(shè)置這兩項(xiàng),編譯時(shí)出現(xiàn)std::錯(cuò)誤。
2、開發(fā)指南
2.1、請(qǐng)求回調(diào)和通知回調(diào)
SDK中和服務(wù)端的交互采取異步回調(diào)方法,有兩種異步回調(diào)方法,一種是請(qǐng)求回調(diào)方法,一種是通知回調(diào)方法,詳細(xì)介紹如下:
(1)請(qǐng)求回調(diào)方法:即由用戶主動(dòng)發(fā)出一個(gè)操作請(qǐng)求,請(qǐng)求的結(jié)果在回調(diào)中返回。具體說(shuō)就是在調(diào)用sdk的方法時(shí),sdk的方法參數(shù)中有回調(diào)方法,請(qǐng)求的結(jié)果直接在參數(shù)的回調(diào)方法中處理。例如發(fā)送消息的方法,包含獲知消息是否發(fā)送成功的回調(diào),此方法就是請(qǐng)求回調(diào)方法。
(2)通知回調(diào)方法:通知回調(diào)是指由云通訊服務(wù)端主動(dòng)給客戶端發(fā)送的信令或業(yè)務(wù)消息,如接收消息,就是由服務(wù)端通知應(yīng)用來(lái)收消息,此方法就是通知回調(diào)方法。
2.2初始化、登陸及登出
? 在程序入口初始化SDK并設(shè)置代理
//設(shè)置回調(diào)代理
[ECDevice sharedInstance].delegate = [DeviceDelegateHelper sharedInstance];```
代理類示例:
DeviceDelegateHelper.h文件
@interface DeviceDelegateHelper : NSObject <ECDeviceDelegate>
/** *@brief 獲取DeviceDelegateHelper單例句柄 /
+(DeviceDelegateHelper)sharedInstance;
@end ```
DeviceDelegateHelper.m文件
@implementation DeviceDelegateHelper
+(DeviceDelegateHelper*)sharedInstance{
static DeviceDelegateHelper *devicedelegatehelper;
static dispatch_once_t devicedelegatehelperonce;
dispatch_once(&devicedelegatehelperonce, ^{
devicedelegatehelper = [[DeviceDelegateHelper alloc] init];
});
return devicedelegatehelper;
}
/**
@brief 連接狀態(tài)接口
@discussion 監(jiān)聽與服務(wù)器的連接狀態(tài) V5.0版本接口
@param state 連接的狀態(tài)
@param error 錯(cuò)誤原因值
*/
-(void)onConnectState:(ECConnectState)state failed:(ECError*)error{
switch (state) {
case State_ConnectSuccess:
//連接成功 break;
case State_Connecting:
//連接中; break;
case State_ConnectFailed:
//與服務(wù)器斷開連接break;
default: break;
}
}
/**
@brief 個(gè)人信息版本號(hào)
@param version服務(wù)器上的個(gè)人信息版本號(hào)
*/
-(void)onServicePersonVersion:(unsigned long long)version{
}
/**
@brief 接收即時(shí)消息代理函數(shù)
@param message 接收的消息
*/
-(void)onReceiveMessage:(ECMessage*)message{
}
/**
@brief 離線消息數(shù)
@param count 消息數(shù)
*/
-(void) onOfflineMessageCount:(NSUInteger)count{
}
/**
@brief 需要獲取的消息數(shù)
@return 消息數(shù) -1:全部獲取 0:不獲取
*/
-(NSInteger) onGetOfflineMessage{
}
/**
@brief 接收離線消息代理函數(shù)
@param message 接收的消息
*/
-(void) onReceiveOfflineMessage:(ECMessage*)message{
}
/**
@brief 離線消息接收是否完成
@param isCompletion YES:拉取完成 NO:拉取未完成(拉取消息失敗)
*/
-(void) onReceiveOfflineCompletion:(BOOL)isCompletion{
}
/**
@brief 客戶端錄音振幅代理函數(shù)
@param amplitude 錄音振幅
*/
-(void)onRecordingAmplitude:(double) amplitude{
}
/**
@brief 接收群組相關(guān)消息
@discussion 參數(shù)要根據(jù)消息的類型,轉(zhuǎn)成相關(guān)的消息類; 解散群組、收到邀請(qǐng)、申請(qǐng)加入、退出群組、有人加入、移除成員等消息
@param groupMsg 群組消息
*/
-(void)onReceiveGroupNoticeMessage:(ECGroupNoticeMessage *)groupMsg{}
@end ```
###? 登錄—具體代碼如下:
//默認(rèn)模式、只對(duì)AppKey、AppToken和userName鑒權(quán)
ECLoginInfo * loginInfo = [[ECLoginInfo alloc] init];
loginInfo.username = @"用戶名";//用戶登錄app的用戶id即可。
loginInfo.appKey = @"appid";
loginInfo.appToken = @"apptoken";
loginInfo.authType = LoginAuthType_NormalAuth;//默認(rèn)方式登錄
loginInfo.mode = LoginMode_InputPassword;
[[ECDevice sharedInstance] login:loginInfo completion:^(ECError *error){
if (error.errorCode == ECErrorType_NoError) {
//登錄成功
}else{
//登錄失敗 }
}];
//密碼模式、對(duì)AppKey、userName和userPassword鑒權(quán)
ECLoginInfo * loginInfo = [[ECLoginInfo alloc] init];
loginInfo.username = @"用戶名";
loginInfo.appKey = @"appid";
loginInfo. userPassword= @"用戶密碼";
loginInfo.authType = LoginAuthType_PasswordAuth;//密碼方式登錄
loginInfo.mode = LoginMode_InputPassword;
[[ECDevice sharedInstance] login:loginInfo completion:^(ECError *error){
if (error.errorCode == ECErrorType_NoError) {
//登錄成功 }
else
{ //登錄失敗 }
}];
###? 登出
退出當(dāng)前賬號(hào),具體代碼如下:
[[ECDevice sharedInstance] logout:^(ECError *error) {
//登出結(jié)果
}];
2.3、單聊
###? 發(fā)送文本\圖片\附件—我們假設(shè)Tony給John發(fā)送文本消息,則代碼如下:
//發(fā)送圖片
ECImageMessageBody *messageBody = [[ECImageMessageBody alloc] initWithFile:@"圖片文件本地絕對(duì)路徑" displayName:@"文件名稱"];
//發(fā)送文件
ECFileMessageBody *messageBody = [[ECFileMessageBody alloc] initWithFile:@"文件本地絕對(duì)路徑" displayName:@"文件名稱"];
//發(fā)送文本
ECTextMessageBody *messageBody = [[ECTextMessageBody alloc] initWithText:@"你好,歡迎來(lái)到云通訊"];
初始化消息, 并指定發(fā)送的內(nèi)容
ECMessage *message = [[ECMessage alloc] initWithReceiver:@"John的賬號(hào)Id" body:messageBody];
// 取本地時(shí)間
NSDate* date = [NSDate dateWithTimeIntervalSinceNow:0];
NSTimeInterval tmp =[date timeIntervalSince1970]*1000;
message.timestamp = [NSString stringWithFormat:@"%lld", (long long)tmp];
[[ECDevice sharedInstance].messageManager sendMessage:message progress:nil completion:^(ECError *error, ECMessage *amessage) {
if (error.errorCode == ECErrorType_NoError) {
//發(fā)送成功
}else if(error.errorCode == ECErrorType_Have_Forbid || error.errorCode == ECErrorType_File_Have_Forbid) {
//您已被群組禁言
}else{
//發(fā)送失敗
}
}];
###? 發(fā)送語(yǔ)音—我們假設(shè)Tony給John發(fā)送語(yǔ)音消息,則代碼如下:
//開始錄音
-(void)startRecord{
ECVoiceMessageBody * messageBody = [[ECVoiceMessageBody alloc] initWithFile:@"語(yǔ)音文件路徑.arm" displayName:@"文件名.arm"];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
[[ECDevice sharedInstance].messageManager startVoiceRecording:messageBody error:^(ECError *error, ECVoiceMessageBody messageBody) {
if (error.errorCode == ECErrorType_RecordTimeOut) {
//錄音超時(shí),立即發(fā)送;應(yīng)用也可以選擇不發(fā)送
ECMessage message = [[ECMessage alloc] initWithReceiver:@"John的賬號(hào)Id" body:messageBody];
NSDate date = [NSDate dateWithTimeIntervalSinceNow:0];
NSTimeInterval tmp =[date timeIntervalSince1970]1000;
message.timestamp = [NSString stringWithFormat:@"%lld", (long long)tmp];
[[ECDevice sharedInstance].messageManager sendMessage:message progress:nil completion:^(ECError *error, ECMessage *amessage) {
if (error.errorCode == ECErrorType_NoError) {
//發(fā)送成功
}else if(error.errorCode == ECErrorType_Have_Forbid || error.errorCode == ECErrorType_File_Have_Forbid){
//您已被群組禁言
}else{
//發(fā)送失敗
}
}];
}
}];
}
//停止錄音
-(void)stopRecord {
[[ECDevice sharedInstance].messageManager stopVoiceRecording:^(ECError *error, ECVoiceMessageBody messageBody) {
if (error.errorCode == ECErrorType_NoError) {
ECMessage message = [[ECMessage alloc] initWithReceiver:@"John的賬號(hào)Id" body:messageBody]; NSDate date = [NSDate dateWithTimeIntervalSinceNow:0];
NSTimeInterval tmp =[date timeIntervalSince1970]1000;
message.timestamp = [NSString stringWithFormat:@"%lld", (long long)tmp];
[[ECDevice sharedInstance].messageManager sendMessage:message progress:nil completion:^(ECError *error, ECMessage *amessage) {
if (error.errorCode == ECErrorType_NoError) {
//發(fā)送成功
}else if(error.errorCode == ECErrorType_Have_Forbid || error.errorCode == ECErrorType_File_Have_Forbid){
//您已被群組禁言
}else{
//發(fā)送失敗
}
}];
} else if (error.errorCode == ECErrorType_RecordTimeTooShort) {
//錄音時(shí)間過(guò)短
}
}];
}
###? 接收消息—我們假設(shè)John收到Tony發(fā)送過(guò)來(lái)的消息,則代碼如下:
/**
@該通知回調(diào)接口在代理類里面
@brief 接收即時(shí)消息代理函數(shù)
@param message 接收的消息
/
-(void)onReceiveMessage:(ECMessage)message{
NSLog:(@"收到%@的消息,屬于%@會(huì)話", message.from, message.sessionId);
switch(message.messageBody.messageBodyType){
case MessageBodyType_Text:{
ECTextMessageBody *msgBody = (ECTextMessageBody *)message.messageBody;
NSLog(@"收到的是文本消息------%@,msgBody.text");
break;
}
case MessageBodyType_Voice:{
ECVoiceMessageBody *msgBody = (ECVoiceMessageBody *)message.messageBody;
NSLog(@"音頻文件remote路徑------%@",msgBody. remotePath);
break;
}
case MessageBodyType_Video:{
ECVideoMessageBody *msgBody = (ECVideoMessageBody *)message.messageBody;
NSLog(@"視頻文件remote路徑------%@",msgBody. remotePath);
break;
}
case MessageBodyType_Image:{
ECImageMessageBody *msgBody = (ECImageMessageBody *)message.messageBody;
NSLog(@"圖片文件remote路徑------%@",msgBody. remotePath);
NSLog(@"縮略圖片文件remote路徑------%@",msgBody. thumbnailRemotePath);
break;
}
case MessageBodyType_File:{
ECFileMessageBody *msgBody = (ECFileMessageBody *)message.messageBody;
NSLog(@"文件remote路徑------%@",msgBody. remotePath);
break;
}
default: break;
}
}
2.5、群組操作
###? 創(chuàng)建群組—我們假設(shè)Tony要?jiǎng)?chuàng)建一個(gè)名為"出彩中國(guó)人"具體代碼如下:
ECGroup * newgroup = [[ECGroup alloc] init];
newgroup.name = @"出彩中國(guó)人";
newgroup.declared = @"歡迎來(lái)到容聯(lián)云通訊";
[[ECDevice sharedInstance].messageManager createGroup:newgroup completion:^(ECError *error, ECGroup *group) {
if (error.errorCode == ECErrorType_NoError) {
NSLog(@"創(chuàng)建群組成功 群組ID:%@", group.groupId);
} else{
NSLog(@"創(chuàng)建群組失敗 errorCode:%d\r\nerrorDescription:%@", (int)error.errorCode,error.errorDescription);
}
}];```
? 主動(dòng)加入—只要知道群組id,就可以主動(dòng)加入群組。
1、我們假設(shè)"出彩中國(guó)人"群組已經(jīng)有Tony和John兩位成員,現(xiàn)在Smith要加入"出彩中國(guó)人"群組,則代碼如下:
[[ECDevice sharedInstance].messageManager joinGroup:@"出彩中國(guó)人群組ID" reason:@"我要參加出彩中國(guó)人" completion:^(ECError *error, NSString *groupId) {
__strong __typeof(weakSelf)strongSelf = weakSelf;
if (error.errorCode==ECErrorType_Have_Joined) {
NSLog(@"您已經(jīng)在群組%@", groupId);
}else if(error.errorCode==ECErrorType_NoError){
if(strongSelf.applyGroup.mode == ECGroupPermMode_DefaultJoin) {
NSLog(@"加入群組%@成功!", groupId);
}else{
NSLog(@"申請(qǐng)加入已發(fā)出,請(qǐng)等待群主同意請(qǐng)求");
} }else{
NSLog(@"加入群組失敗 errorCode:%d\r\nerrorDescription:%@", (int)error.errorCode,error.errorDescription);
}
}];```
注意:如果群組"出彩中國(guó)人"是公開群組,則smith直接被允許加入。如果群組"出彩中國(guó)人"是私有群組,則smith加入需要群主Tony的的同意。Tony首先收到Smith加入的請(qǐng)求,代碼如下:
/**
@該通知回調(diào)接口是代理類里面統(tǒng)一的關(guān)于群組的"群組通知回調(diào)接口"—onReceiveGroupNoticeMessage
@brief 接收群組相關(guān)消息
@discussion 參數(shù)要根據(jù)消息的類型,轉(zhuǎn)成相關(guān)的消息類; 解散群組、收到邀請(qǐng)、申請(qǐng)加入、退出群組、有人加入、移除成員等消息
@param groupMsg 群組消息
*/
-(void)onReceiveGroupNoticeMessage:(ECGroupNoticeMessage *)groupMsg{
if (groupMsg.messageType == ECGroupMessageType_Propose) {
ECProposerMsg * message = (ECProposerMsg *)groupMsg;
NSString *declared = @"";
if (message.declared.length>0) {
declared = [NSString stringWithFormat:@",理由:%@",message.declared];
}
NSLog(@"\"%@\" 昵稱:\"%@\" 申請(qǐng)加入討論組\"%@\"%@",message.proposer,message.nickName, message.groupId, declared);
}
}```
Tony同意Smith加入的請(qǐng)求,代碼如下:
/**
@brief 管理員驗(yàn)證用戶申請(qǐng)加入群組
@param groupId 申請(qǐng)加入的群組id
@param memberId 申請(qǐng)加入的成員id
@param type 是否同意
@param completion 執(zhí)行結(jié)果回調(diào)block
*/
[[ECDevice sharedInstance].messageManager ackJoinGroupRequest:@"出彩中國(guó)人群組ID" member:@" Smith的賬號(hào)Id" ackType:EAckType_Agree completion:^(ECError *error, NSString *gorupId, NSString *memberId) {
if (error.errorCode == ECErrorType_NoError || error.errorCode == ECErrorType_Have_Joined) {
NSLog(@"加入群組");
}else{
NSLog(@"errorCode:%d\rerrorDescription:%@",(int)error.errorCode,error.errorDescription);
}
}];
Smith加入成功后,群組中成員Tony和John收到的通知回調(diào)方法代碼如下:
/**
@該通知回調(diào)接口是代理類里面統(tǒng)一的關(guān)于群組的"群組通知回調(diào)接口"—onReceiveGroupNoticeMessage
@brief 接收群組相關(guān)消息
@discussion 參數(shù)要根據(jù)消息的類型,轉(zhuǎn)成相關(guān)的消息類; 解散群組、收到邀請(qǐng)、申請(qǐng)加入、退出群組、有人加入、移除成員等消息
@param groupMsg 群組消息
*/
-(void)onReceiveGroupNoticeMessage:(ECGroupNoticeMessage *)groupMsg{
if (groupMsg.messageType == ECGroupMessageType_ReplyJoin) {
ECReplyJoinGroupMsg *message = (ECReplyJoinGroupMsg *)groupMsg;
NSLog(@"討論組\"%@\"%@\"%@\"的加入申請(qǐng)",message.groupId,message.confirm==2?@"同意":@"拒絕", message.member);
}
} ```