环信移动客服是全球首创的全媒体智能云客服平台。支持全媒体接入,包括网页在线客服、社交媒体客服(微博、微信)和移动端客服等多种渠道。基于环信业界领先的IM长连接技术保证消息必达,并通过独创的智能机器人技术极大降低人工客服工作量。
1.首先打开环信网站:http://www.easemob.com/?utm_source=baidu&utm_medium=sem&utm_term=环信&utm_campaign=PC%2D品牌词&utm_content=环信品牌
2.通过Cocoapods下载地址,导入框架:具体步骤如下:3.使用时必须导入框架:#import <EaseMobSDK/EaseMob.h>
下面是具体简单使用的代码:
#import "AppDelegate.h" #import <UIImageView+WebCache.h> #import <EaseMobSDKFull/EaseMob.h> #import <AVFoundation/AVFoundation.h> @interface AppDelegate ()<UIAlertViewDelegate, EMChatManagerDelegate> @property (nonatomic, copy)NSString *userName; @property (nonatomic, strong)AVPlayer *player; @end @implementation AppDelegate - (void)didReceiveMessage:(EMMessage *)message { NSString *fromUser = message.from; if ([message.messageBodies.firstObject isKindOfClass:[EMTextMessageBody class]]) { [[[UIAlertView alloc] initWithTitle:[NSString stringWithFormat:@"接收到%@消息",fromUser] message:[[message.messageBodies firstObject] text] delegate:nil cancelButtonTitle:@"好的" otherButtonTitles:nil] show]; }else if([message.messageBodies.firstObject isKindOfClass:[EMImageMessageBody class]]){ EMImageMessageBody *body = message.messageBodies.firstObject; NSLog(@"%@, remotePath:%@",body.image, body.thumbnailRemotePath); UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.window.bounds]; [imageView sd_setImageWithURL:[NSURL URLWithString:body.thumbnailRemotePath]]; [self.window addSubview:imageView]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [imageView removeFromSuperview]; }); }else if ([message.messageBodies.firstObject isKindOfClass:[EMVoiceMessageBody class]]){ EMVoiceMessageBody *body = message.messageBodies.firstObject; NSLog(@"%@",body.remotePath); //下载以后再播放 NSLog(@"语音附件是否下载完成:%lu",(unsigned long)body.attachmentDownloadStatus); } } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { //registerSDKWithAppKey:注册的appKey,详细见下面注释。 //apnsCertName:推送证书名(不需要加后缀),详细见下面注释。 [[EaseMob sharedInstance] registerSDKWithAppKey:@"liu123#liujunchendemo" apnsCertName:@"liutest"]; [[EaseMob sharedInstance] application:application didFinishLaunchingWithOptions:launchOptions]; //注册chatManage 监听 [[EaseMob sharedInstance].chatManager addDelegate:self delegateQueue:dispatch_get_main_queue()]; return YES; } //收到好友请求 - (void)didReceiveBuddyRequest:(NSString *)username message:(NSString *)message{ self.userName = username; [[[UIAlertView alloc] initWithTitle:@"添加好友请求" message:[NSString stringWithFormat:@"%@请求添加您为好友",username] delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"同意",@"拒绝", nil] show]; } -(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { if (buttonIndex == 1) { //同意添加 EMError *error = nil; BOOL isSuccess = [[EaseMob sharedInstance].chatManager acceptBuddyRequest:self.userName error:&error]; if (isSuccess && !error) { NSLog(@"发送同意成功"); } }else if (buttonIndex == 2){ //拒绝 EMError *error = nil; BOOL isSuccess = [[EaseMob sharedInstance].chatManager rejectBuddyRequest:self.userName reason:@"111111" error:&error]; if (isSuccess && !error) { NSLog(@"发送拒绝成功"); } } } //别人同意加我为好友 -(void)didAcceptBuddySucceed:(NSString *)username { [[[UIAlertView alloc] initWithTitle:@"添加好友请求" message:[NSString stringWithFormat:@"%@请求添加您为好友",username] delegate:nil cancelButtonTitle:@"取消" otherButtonTitles:@"同意",@"拒绝", nil] show]; } //别人拒绝加我为好友 -(void)didRejectedByBuddy:(NSString *)username{ [[[UIAlertView alloc] initWithTitle:@"拒绝好友请求" message:[NSString stringWithFormat:@"%@拒绝添加您为好友",username] delegate:nil cancelButtonTitle:@"取消" otherButtonTitles:@"好的",@"拒绝", nil] show]; } // App进入后台 - (void)applicationDidEnterBackground:(UIApplication *)application { [[EaseMob sharedInstance] applicationDidEnterBackground:application]; } // App将要从后台返回 - (void)applicationWillEnterForeground:(UIApplication *)application { [[EaseMob sharedInstance] applicationWillEnterForeground:application]; } // 申请处理时间 - (void)applicationWillTerminate:(UIApplication *)application { [[EaseMob sharedInstance] applicationWillTerminate:application]; } #import "LoginViewController.h" #import <EaseMobSDKFull/EaseMob.h> @interface LoginViewController () @property (weak, nonatomic) IBOutlet UITextField *idTextField; @property (weak, nonatomic) IBOutlet UITextField *pswTextFiled; @end @implementation LoginViewController - (void)viewDidLoad { [super viewDidLoad]; } - (IBAction)logIn:(id)sender { [[EaseMob sharedInstance].chatManager asyncLoginWithUsername:self.idTextField.text password:self.pswTextFiled.text completion:^(NSDictionary *loginInfo, EMError *error) { if (!error && loginInfo) { NSLog(@"登陆成功"); //跳转页面 [self performSegueWithIdentifier:@"pushToList" sender:nil]; }else{ NSLog(@"%@",error); } } onQueue:nil]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } /* #pragma mark - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { // Get the new view controller using [segue destinationViewController]. // Pass the selected object to the new view controller. } */ @end #import "RegisterViewController.h" #import <EaseMobSDKFull/EaseMob.h> @interface RegisterViewController () @property (weak, nonatomic) IBOutlet UITextField *idTextField; @property (weak, nonatomic) IBOutlet UITextField *psdTextField; @end @implementation RegisterViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. } - (IBAction)registerClick:(id)sender { [[EaseMob sharedInstance].chatManager asyncRegisterNewAccount:self.idTextField.text password:self.psdTextField.text withCompletion:^(NSString *username, NSString *password, EMError *error) { if (!error) { NSLog(@"注册成功"); }else{ NSLog(@"error:%@",error); } } onQueue:nil]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } /* #pragma mark - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { // Get the new view controller using [segue destinationViewController]. // Pass the selected object to the new view controller. } */ @end #import "FriendsViewController.h" #import <EaseMobSDKFull/EaseMob.h> #import "ChatDetailViewController.h" @interface FriendsViewController ()<UITableViewDelegate, UITableViewDataSource> @property (weak, nonatomic) IBOutlet UITableView *tableView; @property (nonatomic, strong) NSMutableArray *friendsList; @end @implementation FriendsViewController - (void)viewDidLoad { [super viewDidLoad]; self.friendsList = [@[] mutableCopy]; [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cellID"]; [[EaseMob sharedInstance].chatManager asyncFetchBuddyListWithCompletion:^(NSArray *buddyList, EMError *error) { if (!error) { NSLog(@"获取成功 -- %@",buddyList); [self.friendsList addObjectsFromArray:buddyList]; [self.tableView reloadData]; } } onQueue:nil]; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return self.friendsList.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cellID" forIndexPath:indexPath]; EMBuddy *buddy = self.friendsList[indexPath.row]; cell.textLabel.text = buddy.username; return cell; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [self performSegueWithIdentifier:@"pushToDetail" sender:indexPath]; } -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if ([segue.identifier isEqualToString:@"pushToDetail"]) { ChatDetailViewController *detailVC = segue.destinationViewController; EMBuddy *buddy = self.friendsList[[sender row]]; detailVC.userName = buddy.username; } } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } /* #pragma mark - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { // Get the new view controller using [segue destinationViewController]. // Pass the selected object to the new view controller. } */ @end #import "AddFriendViewController.h" #import <EaseMobSDKFull/EaseMob.h> @interface AddFriendViewController () @property (weak, nonatomic) IBOutlet UITextField *idTF; @end @implementation AddFriendViewController - (IBAction)addFriend:(id)sender { EMError *error = nil; BOOL isSuccess = [[EaseMob sharedInstance].chatManager addBuddy:self.idTF.text message:@"我想加您为好友" error:&error]; if (isSuccess && !error) { NSLog(@"添加成功"); }else{ NSLog(@"添加好友失败"); } } - (IBAction)scan:(id)sender { } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } /* #pragma mark - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { // Get the new view controller using [segue destinationViewController]. // Pass the selected object to the new view controller. } */ @end #import "ChatListViewController.h" @interface ChatListViewController ()<UITableViewDelegate, UITableViewDataSource> @property (weak, nonatomic) IBOutlet UITableView *tableView; @end @implementation ChatListViewController - (void)viewDidLoad { [super viewDidLoad]; [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cellID"]; // Do any additional setup after loading the view. } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return 10; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cellID" forIndexPath:indexPath]; return cell; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } /* #pragma mark - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { // Get the new view controller using [segue destinationViewController]. // Pass the selected object to the new view controller. } */ @end #import "ChatDetailViewController.h" #import <EaseMobSDKFull/EaseMob.h> #import <UIImageView+WebCache.h> @interface ChatDetailViewController ()<UITableViewDataSource, UITableViewDelegate> - (IBAction)addBlackList:(id)sender; - (IBAction)deleteFriend:(id)sender; - (IBAction)sendVoice:(id)sender; - (IBAction)sendText:(id)sender; - (IBAction)sendImage:(id)sender; @property (weak, nonatomic) IBOutlet UITableView *tableView; @property (nonatomic, strong)NSMutableArray *chatMessageList; @end @implementation ChatDetailViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. NSLog(@"+++++++++++++:%@", self.userName); //会话 EMConversation *conversation = [[EaseMob sharedInstance].chatManager conversationForChatter:self.userName conversationType:eConversationTypeChat]; NSLog(@"聊天记录:%@", [conversation loadAllMessages]); [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"]; self.chatMessageList = [NSMutableArray arrayWithArray:[conversation loadAllMessages]]; } -(NSInteger )tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return self.chatMessageList.count; } -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath]; // for (id obj in self.chatMessageList) { // NSLog(@"%@",[obj class]); // } EMMessage *message = self.chatMessageList[indexPath.row]; if ([message.messageBodies.firstObject isKindOfClass:[EMTextMessageBody class]]) { EMTextMessageBody *body = message.messageBodies.firstObject; cell.textLabel.text = body.text; }else if ([message.messageBodies.firstObject isKindOfClass:[EMImageMessageBody class]]){ EMImageMessageBody *body = message.messageBodies.firstObject; //加载图片 [cell.imageView sd_setImageWithURL:[NSURL URLWithString:body.thumbnailRemotePath]]; cell.textLabel.text = @"这是图片"; }else if ([message.messageBodies.firstObject isKindOfClass:[EMVoiceMessageBody class]]){ cell.imageView.image = [UIImage imageNamed:@"1.jpg"]; cell.textLabel.text = @"这是语音"; } return cell; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (IBAction)addBlackList:(id)sender { // 将6001加入黑名单 EMError *error = [[EaseMob sharedInstance].chatManager blockBuddy:self.userName relationship:eRelationshipBoth]; if (!error) { NSLog(@"发送成功"); } } - (IBAction)deleteFriend:(id)sender { EMError *error = nil; // 删除好友 BOOL isSuccess = [[EaseMob sharedInstance].chatManager removeBuddy:self.userName removeFromRemote:YES error:&error]; if (isSuccess && !error) { NSLog(@"删除成功"); } [self.tableView reloadData]; //removeBuddy:要删除的用户 //removeFromRemote:是否将自己从对方好友列表中移除 //error:错误信息 // } - (IBAction)sendVoice:(id)sender { NSString *path = [[NSBundle mainBundle] pathForResource:@"爱的供养" ofType:@"mp3"]; EMChatVoice *voice = [[EMChatVoice alloc] initWithFile:path displayName:@"audio"]; voice.duration = 100; EMVoiceMessageBody *body = [[EMVoiceMessageBody alloc] initWithChatObject:voice]; // 生成message EMMessage *message = [[EMMessage alloc] initWithReceiver:self.userName bodies:@[body]]; message.messageType = eMessageTypeChat; // 设置为单聊消息 //message.messageType = eConversationTypeGroupChat;// 设置为群聊消息 //message.messageType = eConversationTypeChatRoom;// 设置为聊天室消息 //发送消息 [[EaseMob sharedInstance].chatManager asyncSendMessage:message progress:nil prepare:^(EMMessage *message, EMError *error) { } onQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) completion:^(EMMessage *message, EMError *error) { [[[UIAlertView alloc] initWithTitle:@"消息发送成功" message:@"" delegate:nil cancelButtonTitle:@"好的" otherButtonTitles:nil] show]; } onQueue:dispatch_get_main_queue()]; } - (IBAction)sendText:(id)sender { EMChatText *txtChat = [[EMChatText alloc] initWithText:@"你好哦"]; EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithChatObject:txtChat]; // 生成message EMMessage *message = [[EMMessage alloc] initWithReceiver:self.userName bodies:@[body]]; message.messageType = eMessageTypeChat; // 设置为单聊消息 //message.messageType = eConversationTypeGroupChat;// 设置为群聊消息 //message.messageType = eConversationTypeChatRoom;// 设置为聊天室消息 //发送消息 [[EaseMob sharedInstance].chatManager asyncSendMessage:message progress:nil prepare:^(EMMessage *message, EMError *error) { } onQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) completion:^(EMMessage *message, EMError *error) { [[[UIAlertView alloc] initWithTitle:@"消息发送成功" message:@"" delegate:nil cancelButtonTitle:@"好的" otherButtonTitles:nil] show]; } onQueue:dispatch_get_main_queue()]; } - (IBAction)sendImage:(id)sender { UIImage *image = [UIImage imageNamed:@"1.jpg"]; EMChatImage *imgChat = [[EMChatImage alloc] initWithUIImage:image displayName:@"displayName"]; EMImageMessageBody *body = [[EMImageMessageBody alloc] initWithChatObject:imgChat]; // 生成message EMMessage *message = [[EMMessage alloc] initWithReceiver:@"6001" bodies:@[body]]; message.messageType = eMessageTypeChat; // 设置为单聊消息 //message.messageType = eConversationTypeGroupChat;// 设置为群聊消息 //message.messageType = eConversationTypeChatRoom;// 设置为聊天室消息 //发送消息 [[EaseMob sharedInstance].chatManager asyncSendMessage:message progress:nil prepare:^(EMMessage *message, EMError *error) { } onQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) completion:^(EMMessage *message, EMError *error) { [[[UIAlertView alloc] initWithTitle:@"消息发送成功" message:@"" delegate:nil cancelButtonTitle:@"好的" otherButtonTitles:nil] show]; } onQueue:dispatch_get_main_queue()]; } @end
该Demo所用到的类如下
注意:该Demo的所有控件都是在storyBoard中实现的