集成测试
评测环境
2G/3G/WiFi网络下:
测评环境 | MAC OS(10.9.2)+ XCode(5.1) + iPhone |
测试对象 | 环信即时通讯云 IOS SDK Version 2.0.9.1 |
测试设备 | iPhone |
系统版本 | IOS SDK 7.1 |
设备网络 | 2G/3G/WIFI |
测试难度 | 一般 |
测试方法 | 客户端运行环信即时通讯云IOS SDK实例 |
测试时间 | 2014-10-01 17:10:00 |
测试时长 | 6个小时 |
基本参数:
是否免费 | 注册用户300万以下或日活30万以下终身免费 |
离线存储空间 | 每个用户100MB |
平台支持 | IOS、Android |
实时语音、视频 | 即将支持 |
单聊 | 支持 |
群聊 | 支持 |
发送文字 | 支持 |
发送表情 | 支持 |
发送语音 | 支持 |
发送地理位置 | 支持 |
发送照片 | 支持 |
发送视频 | 支持 |
离线消息 | 支持 |
存储用户信息 | 不支持,由用户业务服务器负责 |
流量数据统计 | 支持 |
消息发送数量 | 无限制 |
注:具体参数详见: http://www.easemob.com/price/
集成过程
客户端集成
环信即时通讯云IOS SDK的大体开发流程如下:
注册成为开发者=》服务端配置=》创建应用=》下载SDK=》集成开发=》测试应用
1、注册环信账号
登录环信官方首页:http://www.easemob.com/
点击登录,如果没有环信账号需要进行注册,填写用户相关详细信息,如下图所示:
注:企业ID只限于数字、字母、横线,且不能以横线开头和结尾。企业ID会存在于生成的APPKEY中,如:测试demo中 APPKEY为DevStore#chatdemo,则DevStore为填写的企业ID。
如果是个人应用开发的话,企业ID直接写成自己定义的ID就可以。
2、激活账号
注册成功后,会向你填写的邮箱中发送验证信息,请前往邮箱进行账号激活。
3、登录
进行登录:https://console.easemob.com/index.html
4、创建应用
账号成功激活后,登录到环信管理后台的页面,在我的应用中,点击创建应用按钮,如下图:
点击创建应用,填写应用的相关信息。
注: 注册模式中,开放注册:允许在该应用下自由注册新用户,授权注册:只有企业管理员或者应用管理员才能注册用户。
建议在开发测试阶段选择开放注册,这样便于程序的测试。
显示创建应用成功。
5、获取应用的配置信息
保存好应用的基本信息:API KEY以及client_id、client_secret。
注: AppKey作为客户端应用程序的标识,在进行客户端开发的时候会用到。
client_id和client_secret在客户端与服务器进行数据交换时进行鉴权使用,它就是拥有超级权限的一个token,可以调REST接口,来处理管理员做的事情,使用它的人应有最高的权限,所以一般情况下对于普通的客户端来说是用不到的。
6、下载SDK
下载IOS SDK http://www.easemob.com/sdk/
注:目前的最新版本为2.0.9.1
7、SDK集成
1)新建工程
2)添加环信 SDK
直接将环信 SDK拖入到工程中
选择复制
3)添加系统链接库
添加 SystemConfigureation.framework
除此之外,还应依次添加如下库文件:
4)编译环境的设置
设置Linker
向Other Linker Flags 中添加 -ObjC。(如果已有,则不需要再添加)
注:-ObjC就是会加载静态库文件中实现一个类或者分类的所有成员
设置Architectures
5)设置AppKey
设置APNS和AppKey,如下图所示:
注:极力推荐开发者在环信提供的Demo之上进行应用开发,该Demo已经实现了聊天所需的大部分功能,这样可以提高开发效率。
EaseMob作为客户端基本工具类(单例)负责与服务器端交互。
6)注册功能
实现注册功能,添加如下代码:
01 | - (IBAction)doRegister:(id)sender |
05 | [self.view endEditing:YES]; |
06 | if ([self.usernameTextField.text isChinese]) |
08 | UIAlertView *alert = [[UIAlertView alloc] |
09 | initWithTitle:@ "用户名不支持中文" |
12 | cancelButtonTitle:@ "确定" |
13 | otherButtonTitles:nil]; |
19 | [self showHudInView:self.view hint:@ "正在注册..." ]; |
20 | [[EaseMob sharedInstance].chatManager asyncRegisterNewAccount:_usernameTextField.text |
21 | password:_passwordTextField.text |
22 | withCompletion: case EMErrorServerNotReachable: |
23 | TTAlertNoTitle(@ "连接服务器失败!" ); |
25 | case EMErrorServerDuplicatedAccount: |
26 | TTAlertNoTitle(@ "您注册的用户已存在!" ); |
28 | case EMErrorServerTimeout: |
29 | TTAlertNoTitle(@ "连接服务器超时!" ); |
32 | TTAlertNoTitle(@ "注册失败" ); |
IChatManager接口类,它是一个聊天管理器,获取该对象后,可以做登录、聊天、加好友等操作。
在这里使用异步的方法asyncRegisterNewAccount在聊天服务器上创建账号。
进入环信服务管理的后台,查看IM用户
现在已有devstore_test用户,说明注册成功。
7)登录功能
实现登录功能,添加如下代码:
01 | - ( void ) loginWithUsername:(NSString *)username password:(NSString *)password |
04 | [self showHudInView:self.view hint:@ "正在登录..." ]; |
05 | [[EaseMob sharedInstance].chatManager asyncLoginWithUsername:username |
08 | ^(NSDictionary *loginInfo, EMError *error) { |
10 | if (loginInfo && !error) { |
11 | [[NSNotificationCenter defaultCenter] postNotificationName:KNOTIFICATION_LOGINCHANGE object:@YES]; |
13 | switch (error.errorCode) { |
14 | case EMErrorServerNotReachable: |
15 | TTAlertNoTitle(@ "连接服务器失败!" ); |
17 | case EMErrorServerAuthenticationFailure: |
18 | TTAlertNoTitle(@ "用户名或密码错误" ); |
20 | case EMErrorServerTimeout: |
21 | TTAlertNoTitle(@ "连接服务器超时!" ); |
24 | TTAlertNoTitle(@ "登录失败" ); |
IChatManager 接口类,它是一个聊天管理器,获取该对象后,可以做登录、聊天、加好友等操作。
在这里使用异步的方法asyncLoginWithUsername登录聊天服务器。
验证登录功能
8)发送消息功能
发送文字,实现消息发送功能,添加如下代码:
01 | +(EMMessage *)sendTextMessageWithString:(NSString *)str toUsername:(NSString *)username isChatGroup:( BOOL )isChatGroup |
02 | requireEncryption:( BOOL )requireEncryption |
05 | NSString *willSendText = [ConvertToCommonEmoticonsHelper convertToCommonEmoticons:str]; |
06 | EMChatText *text = [[EMChatText alloc] initWithText:willSendText]; |
07 | EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithChatObject:text]; |
09 | EMMessage *retureMsg = [[EMMessage alloc] initWithReceiver:username bodies:[NSArray arrayWithObject:body]]; |
10 | retureMsg.requireEncryption = requireEncryption; |
11 | retureMsg.isGroup = isChatGroup; |
12 | EMMessage *message = [[EaseMob sharedInstance].chatManager asyncSendMessage:retureMsg progress:nil]; |
EMChatText 用于封装要发送消息的具体内容
EMTextMessageBody 对消息内容进行封装的消息体
EMMessage 封装消息,创建EMessage时需要指定消息的接受者和要发送的消息列表。
客户的工具类EaseMob中的聊天管器chatManager中的asyncSendMessage负责发送消息。
验证发送消息功能:
9)接收消息功能
接收文字,实现消息接收功能,添加如下代码:
01 | - ( void )showNotificationWithMessage:(EMMessage *)message |
04 | EMPushNotificationOptions *options = [[EaseMob sharedInstance].chatManager pushNotificationOptions]; |
06 | UILocalNotification *notification = [[UILocalNotification alloc] init]; |
07 | notification.fireDate = [NSDate date]; |
09 | if (options.displayStyle == ePushNotificationDisplayStyle_messageSummary) { |
10 | id<IEMMessageBody> messageBody = [message.messageBodies firstObject]; |
11 | NSString *messageStr = nil; |
12 | switch (messageBody.messageBodyType) { |
13 | case eMessageBodyType_Text: |
15 | messageStr = ((EMTextMessageBody *)messageBody).text; |
18 | case eMessageBodyType_Image: |
23 | case eMessageBodyType_Location: |
28 | case eMessageBodyType_Voice: |
33 | case eMessageBodyType_Video:{ |
41 | NSString *title = message.from; |
42 | if (message.isGroup) { |
43 | NSArray *groupArray = [[EaseMob sharedInstance].chatManager groupList]; |
44 | for (EMGroup *group in groupArray) { |
45 | if ([group.groupId isEqualToString:message.conversation.chatter]) { |
46 | title = [NSString stringWithFormat:@ "%@(%@)" , message.groupSenderName, group.groupSubject]; |
52 | notification.alertBody = [NSString stringWithFormat:@ "%@:%@" , title, messageStr]; |
55 | notification.alertBody = @ "您有一条新消息" ; |
57 | notification.alertAction = @ "打开" ; |
58 | notification.timeZone = [NSTimeZone defaultTimeZone]; |
60 | [[UIApplication sharedApplication] scheduleLocalNotification:notification]; |
61 | UIApplication *application = [UIApplication sharedApplication]; |
62 | application.applicationIconBadgeNumber += 1; |
IEMMessageBody中的messageBodyType用来指定消息的类型
验证接收消息功能:
除此之外,还可以通过网页在环信管理后台进行用户的管理和消息的发送。
主要功能
用户登录
用户注册
在客户端进行注册的时候需要将应用的注册方式改为开发注册。
消息发送与接收
环信客户端支持许多媒体,包括文字、图片、视频、地理位置等。
查找与添加好友
群组管理
删除用户或组
功能特色
1、数据流量统计
环信即时通讯云可以按照IM用户、消息、GET请求次数、POST请求次数、DELETE请求次数、PUT请求次数进行数据统计。同时也支持按照时间段对以上统计项进行查询。
用户数量的统计
消息数量的统计
2、用户信息管理
在环信管理后台可以对当前的用户(环信ID标识)进行管理,包括为用户添加好友、创建组、注册用户、发送消息、批量删除等。
3、客户端设置
环信IOS客户端已经实现了聊天所具有的大部分功能,另外用户也可以根据自己的需要进行相应的设置,包括自动登录、消息推送设置、黑名单以及日志上传等。
DEMO展示
AppDelegate.m
01 | - ( BOOL )application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions |
03 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; |
04 | self.window.backgroundColor = [UIColor whiteColor]; |
05 | apnsCertName = @ "devstorehuanxin" ; |
07 | [[EaseMob sharedInstance] registerSDKWithAppKey:@ "devstore#devstorehuanxin" apnsCertName:apnsCertName]; |
08 | NSLog(@ "注册AppKey......" ); |
11 | [[EaseMob sharedInstance] enableUncaughtExceptionHandler]; |
15 | [[EaseMob sharedInstance] application:application didFinishLaunchingWithOptions:launchOptions]; |
17 | #warning 注册为SDK的ChatManager的delegate (及时监听到申请和通知) |
18 | [[EaseMob sharedInstance].chatManager removeDelegate:self]; |
19 | [[EaseMob sharedInstance].chatManager addDelegate:self delegateQueue:nil]; |
21 | #warning 如果使用MagicalRecord, 要加上这句初始化MagicalRecord |
23 | [MagicalRecord setupCoreDataStackWithStoreNamed:[NSString stringWithFormat:@ "%@.sqlite" , @ "UIDemo" ]]; |
25 | [self loginStateChange:nil]; |
26 | [self.window makeKeyAndVisible]; |
注册用户
01 | - (IBAction)doRegister:(id)sender |
05 | [self.view endEditing:YES]; |
06 | if ([self.usernameTextField.text isChinese]) |
08 | UIAlertView *alert = [[UIAlertView alloc] |
09 | initWithTitle:@ "用户名不支持中文" |
12 | cancelButtonTitle:@ "确定" |
13 | otherButtonTitles:nil]; |
19 | [self showHudInView:self.view hint:@ "正在注册..." ]; |
20 | [[EaseMob sharedInstance].chatManager asyncRegisterNewAccount:_usernameTextField.text |
21 | password:_passwordTextField.text |
22 | withCompletion: case EMErrorServerNotReachable: |
23 | TTAlertNoTitle(@ "连接服务器失败!" ); |
25 | case EMErrorServerDuplicatedAccount: |
26 | TTAlertNoTitle(@ "您注册的用户已存在!" ); |
28 | case EMErrorServerTimeout: |
29 | TTAlertNoTitle(@ "连接服务器超时!" ); |
32 | TTAlertNoTitle(@ "注册失败" ); |
LoginViewController.m
用户登录
01 | - (IBAction)doRegister:(id)sender |
05 | [self.view endEditing:YES]; |
06 | if ([self.usernameTextField.text isChinese]) |
08 | UIAlertView *alert = [[UIAlertView alloc] |
09 | initWithTitle:@ "用户名不支持中文" |
12 | cancelButtonTitle:@ "确定" |
13 | otherButtonTitles:nil]; |
19 | [self showHudInView:self.view hint:@ "正在注册..." ]; |
20 | [[EaseMob sharedInstance].chatManager asyncRegisterNewAccount:_usernameTextField.text |
21 | password:_passwordTextField.text |
22 | withCompletion: case EMErrorServerNotReachable: |
23 | TTAlertNoTitle(@ "连接服务器失败!" ); |
25 | case EMErrorServerDuplicatedAccount: |
26 | TTAlertNoTitle(@ "您注册的用户已存在!" ); |
28 | case EMErrorServerTimeout: |
29 | TTAlertNoTitle(@ "连接服务器超时!" ); |
32 | TTAlertNoTitle(@ "注册失败" ); |
发送文字
01 | +(EMMessage *)sendTextMessageWithString:(NSString *)str |
02 | toUsername:(NSString *)username |
03 | isChatGroup:( BOOL )isChatGroup |
04 | requireEncryption:( BOOL )requireEncryption |
07 | NSString *willSendText = [ConvertToCommonEmoticonsHelper convertToCommonEmoticons:str]; |
08 | EMChatText *text = [[EMChatText alloc] initWithText:willSendText]; |
09 | EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithChatObject:text]; |
11 | EMMessage *retureMsg = [[EMMessage alloc] initWithReceiver:username bodies:[NSArray arrayWithObject:body]]; |
12 | retureMsg.requireEncryption = requireEncryption; |
13 | retureMsg.isGroup = isChatGroup; |
14 | EMMessage *message = [[EaseMob sharedInstance].chatManager asyncSendMessage:retureMsg progress:nil]; |
接收消息
01 | - ( void )showNotificationWithMessage:(EMMessage *)message |
04 | EMPushNotificationOptions *options = [[EaseMob sharedInstance].chatManager pushNotificationOptions]; |
06 | UILocalNotification *notification = [[UILocalNotification alloc] init]; |
07 | notification.fireDate = [NSDate date]; |
09 | if (options.displayStyle == ePushNotificationDisplayStyle_messageSummary) { |
10 | id<IEMMessageBody> messageBody = [message.messageBodies firstObject]; |
11 | NSString *messageStr = nil; |
12 | switch (messageBody.messageBodyType) { |
13 | case eMessageBodyType_Text: |
15 | messageStr = ((EMTextMessageBody *)messageBody).text; |
18 | case eMessageBodyType_Image: |
23 | case eMessageBodyType_Location: |
28 | case eMessageBodyType_Voice: |
33 | case eMessageBodyType_Video:{ |
41 | NSString *title = message.from; |
42 | if (message.isGroup) { |
43 | NSArray *groupArray = [[EaseMob sharedInstance].chatManager groupList]; |
44 | for (EMGroup *group in groupArray) { |
45 | if ([group.groupId isEqualToString:message.conversation.chatter]) { |
46 | title = [NSString stringWithFormat:@ "%@(%@)" , message.groupSenderName, group.groupSubject]; |
52 | notification.alertBody = [NSString stringWithFormat:@ "%@:%@" , title, messageStr]; |
55 | notification.alertBody = @ "您有一条新消息" ; |
57 | notification.alertAction = @ "打开" ; |
58 | notification.timeZone = [NSTimeZone defaultTimeZone]; |
60 | [[UIApplication sharedApplication] scheduleLocalNotification:notification]; |
61 | UIApplication *application = [UIApplication sharedApplication]; |
62 | application.applicationIconBadgeNumber += 1; |
详细实现代码参见环信SDK中的UI实例,里面有详细的说明。
测试日志
测试日志截图:
遇到问题
总体来说使用环信SDK进行客户端集成的难度是比较低的。环信官方提供的IOS 客户端已经实现了聊天的大部分功能,而且客户端的代码是开源的,开发者可以根据自己的需求在此之上进行相应的修改,这样极大的简化了客户端的开发负担。
开发过程中遇到的问题主要集中在配置方面,下面笔者对集成过程中几个重点地方进行一下说明:
1、编译环境配置
设置Linker
在Other Linker Flags 中添加 –ObjC,如下图所示:
设置Architectures
2、AppKey设置
需要注意的是,registerSDKWithAppKey的参数一定要与创建应用时给定的AppKey相一致。
注: AppKey作为客户端应用程序的标识,在进行客户端开发的时候会用到。
client_id和client_secret在客户端与服务器进行数据交换时进行鉴权使用,它就是拥有超级权限的一个token,可以调REST接口,来处理管理员做的事情,使用它的人应有最高的权限,所以一般情况下对于普通的客户端来说是用不到的。
3、环信管理后台的使用
在进行测试开发的时候建议将用户注册模式改为开放注册,这样便于客户端的测试,笔者刚开始未注意到这个问题,导致注册失败。
上手难易
总的来说,笔者认为使用环信IOS SDK进行集成开发是比较容易的,环信官方提供的IOS 客户端已经实现了聊天的大部分功能,主要包括:好友管理、发送接收消息、群组管理以及各种自定义配置选项。而且客户端的代码是开源的,开发者可以根据自己的需求在此之上进行相应的修改,在此强烈建议开发者在官方提供的客户端之上进行相应的开发,这样极大的简化了客户端的开发负担,提高开发效率。
环信即时通讯云服务使用标准的Auth 2.0协议进行身份鉴权,数据访问使用REST API方式。在进行开发之前希望开发者可以学习一下相关的内容,有助于你对环信IOS SDK的使用。
开发文档
1、开发中关于IOS SDK的问题参见IOS 在stack overflow的主页:
http://stackoverflow.com/questions/tagged/ios
2、对于Autho2.0 的原理说明可以参考官方提供的地址 http://www.ruanyifeng.com/blog/2014/05/restful_api.html或者
http://blog.csdn.net/zhangzhebjut/article/details/26006905
RES API介绍参见环信官网:http://www.easemob.com/docs/rest/#rest
3、关于环信IOS SDK集成过程介绍,开发者可以参考官方提供的文档说明:
http://www.easemob.com/docs/ios/
除此之外,开发者也可以参考官方提供的实例以提高开发效率。
4、环信IOS SDK使用的类接口文档说明可以参见:
http://www.easemob.com/apidoc/ios/chat/