环信的简单接入

我是直接用的 环信的EaseUI的 UI, 关于导入就不多言了,添加了官网让添加的第三方库
然后运行没有报错
下面开始接入

1.注册和通知

在- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 方法中添加

 //注册环信
EMOptions *options = [EMOptions optionsWithAppkey:@"app 的 key"];
options.apnsCertName = @"上传的推送证书的名字";
[[EMClient sharedClient] initializeSDKWithOptions:options];
options.enableDeliveryAck = YES;
//添加监听在线推送消息
[[EMClient sharedClient].chatManager addDelegate:self delegateQueue:nil];

(注:要让 AppDelegate遵循EMChatManagerDelegate协议)
注:环信的通知只有在完全杀死 app 的情况下才会推送 如果只是app 在后台 是不会发推送通知的 所以要监听在线推送消息来发本地推送
下面来实现监听在线推送消息的方法
//监听环信在线推送消息
- (void)messagesDidReceive:(NSArray *)aMessages {
for (EMMessage *message in aMessages) {
EMMessageBody *msgBody = message.body;
switch (msgBody.type) {
case EMMessageBodyTypeText: {
// 收到的文字消息
EMTextMessageBody *textBody = (EMTextMessageBody *)msgBody;
NSString *txt = textBody.text;
UIApplicationState state = [UIApplication sharedApplication].applicationState;
//判断 app 是不是在后台
if (state == UIApplicationStateBackground) {
UILocalNotification *localNote = [[UILocalNotification alloc] init];
//设置通知发出的时间
localNote.fireDate = [NSDate dateWithTimeIntervalSinceNow:5.0];
//设置通知的内容
localNote.alertBody = txt;
//设置锁屏界面的文字
localNote.alertAction = txt;
//设置锁屏界面alertAction是否有效
localNote.hasAction = YES;
//设置应用程序图标右上角的数字
localNote.applicationIconBadgeNumber = 1;
// 调度通知
[[UIApplication sharedApplication] scheduleLocalNotification:localNote];
} else {
// 如果是在前台,这里可以选择增加角标或者其他提示
}
}
break;
case EMMessageBodyTypeImage: {
// 得到一个图片消息body
EMImageMessageBody *body = ((EMImageMessageBody *)msgBody);
UIApplicationState state = [UIApplication sharedApplication].applicationState;
if (state == UIApplicationStateBackground) {
UILocalNotification *localNote = [[UILocalNotification alloc] init];
//设置通知发出的时间
localNote.fireDate = [NSDate dateWithTimeIntervalSinceNow:5.0];
//设置通知的内容
localNote.alertBody = @"收到一张图片";
//设置锁屏界面的文字
localNote.alertAction = @"收到一张图片";
//设置锁屏界面alertAction是否有效
localNote.hasAction = YES;
//设置应用程序图标右上角的数字
localNote.applicationIconBadgeNumber = 1;
//调度通知
[[UIApplication sharedApplication] scheduleLocalNotification:localNote];
}
}
break;
case EMMessageBodyTypeLocation: {
EMLocationMessageBody *body = (EMLocationMessageBody *)msgBody;
NSLog(@"纬度-- %f",body.latitude);
NSLog(@"经度-- %f",body.longitude);
NSLog(@"地址-- %@",body.address);
UIApplicationState state = [UIApplication sharedApplication].applicationState;
if (state == UIApplicationStateBackground) {
UILocalNotification *localNote = [[UILocalNotification alloc] init];
//设置通知发出的时间
localNote.fireDate = [NSDate dateWithTimeIntervalSinceNow:5.0];
//设置通知的内容
localNote.alertBody = @"收到一条消息";
//设置锁屏界面的文字
localNote.alertAction = @"收到一条消息";
//设置锁屏界面alertAction是否有效
localNote.hasAction = YES;
//设置应用程序图标右上角的数字
localNote.applicationIconBadgeNumber = 1;
// 调度通知
[[UIApplication sharedApplication] scheduleLocalNotification:localNote];
}
}
break;
case EMMessageBodyTypeVoice: {
// 音频sdk会自动下载
EMVoiceMessageBody *body = (EMVoiceMessageBody *)msgBody;
NSLog(@"音频remote路径 -- %@" ,body.remotePath);
NSLog(@"音频local路径 -- %@" ,body.localPath); // 需要使用sdk提供的下载方法后才会存在(音频会自动调用)
NSLog(@"音频的secret -- %@" ,body.secretKey);
NSLog(@"音频文件大小 -- %lld" ,body.fileLength);
NSLog(@"音频文件的下载状态 -- %u" ,body.downloadStatus);
NSLog(@"音频的时间长度 -- %u" ,body.duration);
UIApplicationState state = [UIApplication sharedApplication].applicationState;
if (state == UIApplicationStateBackground) {
UILocalNotification *localNote = [[UILocalNotification alloc] init];
//设置通知发出的时间
localNote.fireDate = [NSDate dateWithTimeIntervalSinceNow:5.0];
//设置通知的内容
localNote.alertBody = @"收到一条消息";
//设置锁屏界面的文字
localNote.alertAction = @"收到一条消息";
//设置锁屏界面alertAction是否有效
localNote.hasAction = YES;
//设置应用程序图标右上角的数字
localNote.applicationIconBadgeNumber = 1;
//调度通知
[[UIApplication sharedApplication] scheduleLocalNotification:localNote];
}
}
break;
case EMMessageBodyTypeVideo: {
//视频消息
EMVideoMessageBody *body = (EMVideoMessageBody *)msgBody;
}
break;
case EMMessageBodyTypeFile: {
// 文件消息
EMFileMessageBody *body = (EMFileMessageBody *)msgBody;
}
break;
default:
break;
}
}
}

这里因为我是没有用到视频和文件的功能,所以这里收到之后并没有做处理

//当程序关闭后 通过点击推送弹出的通知
// iOS 10 支持的方法
- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler {
//在这个方法中实现点击消息进入 app 之后的方法
//我这里是写了一个通知 让 app 进入消息列表界面
[[NSNotificationCenter defaultCenter] postNotificationName:@"jumpToChatListView" object:nil];
}
这里需要注意一点 导出 p12证书上传到环信的时候一定要设置密码 上传的时候的包名要写 app 的 boundleID 要不然接收不到通知

2.开始聊天

我这里做的是每次开始聊天都要登陆一下 ,也可以选择在用户登陆 app 的时候 或者在 appdelegate 里面登陆
EMError *error = [[EMClient sharedClient] loginWithUsername:@"用户名" password:@"密码"]; if (!error) {//我在这里做了一个只要和他说话就添加他为好友 这样在后面获取好友列表的时候就有好友啦 MYFMRequestBean* bean = [MyHttpRequest addFriendWithUserId:对方 id currntUserId:自己的 id]; [bean connect:nil success:^(id responseObject) { } failure:^(NSError *error) { }];

//这里自定义了一个聊天页面 继承于EaseMessageViewController 定义了两个属性 一个是 talkImg 是对方的头像 一个是 talkName 对方的名字 这个从当前页面就能获取到
ChatViewController *chatController = [[ChatViewController alloc] initWithConversationChatter:对方的环信 idconversationType:EMConversationTypeChat]; chatController.talkImg = 对方的头像的 url 地址; chatController.talkName = 对方的名字; chatController.hidesBottomBarWhenPushed=YES;//跳转时隐藏 tabbar [self.navigationController pushViewController:chatController animated:YES]; } else { [SVProgressHUD showErrorWithStatus:@"连接失败,请稍后重试"]; }

3.聊天页面

自定义了一个ChatViewController
.h 文件就是
@interface ChatViewController : EaseMessageViewController @property (nonatomic, copy)NSString *talkName; @property (nonatomic, copy)NSString *talkImg; @end

.m 文件:
//遵循EaseMessageViewController的 DataSource 协议
@interface ChatViewController ()<EaseMessageViewControllerDataSource>
@end
@implementation ChatViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.dataSource = self;
[self.navigationItem setTitle:self.talkName];
}
//这里实现EaseMessageViewController的 DataSource 方法 来改变对方和自己的昵称和头像
- (id<IMessageModel>)messageViewController:(EaseMessageViewController *)viewController
modelForMessage:(EMMessage *)message
{
//用户可以根据自己的用户体系,根据message设置用户昵称和头像
id<IMessageModel> model = nil;
//EaseMessageModel是环信EaseUI提供的model
model = [[EaseMessageModel alloc] initWithMessage:message];
//分两种情况 一种是当为当前用户的时候
if ([model.nickname isEqualToString:[EMClient sharedClient].currentUsername]) {
//默认图
// model.avatarImage = [UIImage imageNamed:@"baseInfo"];
//网络图
model.avatarURLPath = [UserManager userImg];
model.nickname = [UserManager userName];
} else {//当为对方的时候
model.avatarURLPath = _talkImg;//网络图
// model.avatarImage = [UIImage imageNamed:@"baseInfo"];//默认图
model.nickname = _talkName;//用户昵称
}
return model;
}

4.消息列表

自定义了一个ChatListViewController 继承于环信的EaseConversationListViewController
.h文件:
@interface ChatListViewController : EaseConversationListViewController
-(void)reloadData;//这里我加了一个刷新方法 如果单击消息进入 app 的时候是在当前页面 要刷新一下,默认是不会刷新的,即使在 viewWillAppear 里面写了也不刷新
@end
.m文件:
#import "ChatListViewController.h"
#import "HPChatListDataModel.h"
#import "NSDate+Category.h"//环信时间分类
#import "ChatViewController.h"
#import "ChatListDataModel.h"//这是自定义的一个 model 类 存放好友的头像昵称和 id
#import "EaseUsersListViewController.h"
@interface ChatListViewController ()<EaseConversationListViewControllerDataSource,EaseConversationListViewControllerDelegate>
@property (nonatomic, strong)NSMutableArray *imageAndNameArray;
@end

  @implementation ChatListViewController
  - (void)viewDidLoad {
  [super viewDidLoad];
  [self sendFriendsList];
  self.dataSource = self;
  self.delegate = self;
  [self.navigationItem setTitle:@"聊天列表"];
  //打开下来刷新
  self.showRefreshHeader = YES;
  [self tableViewDidTriggerHeaderRefresh];
  }
  #pragma mark - 好友列表
  - (void)sendFriendsList {
[SVProgressHUD showWithStatus:@"加载中..."];
MYFMRequestBean* bean = [MyHttpRequest friendsListWithUserId:[UserManager userId]];
self.imageAndNameArray = [NSMutableArray array];
__weak typeof(self) weakSelf = self;
[bean connect:nil success:^(id responseObject) {
    [SVProgressHUD dismiss];
    NSDictionary* dic = responseObject;
    if ([dic optIntKey:@"status"] == 1) {
        NSArray* arr = dic[@"data"];
        for (NSDictionary* dict in arr) {
            HPChatListDataModel *model = [[HPChatListDataModel alloc]initWithDictionary:dict];
            [weakSelf.imageAndNameArray addObject:model];
        }
        [self tableViewDidTriggerHeaderRefresh];
    } else {
        [SVProgressHUD showErrorWithStatus:[dic optStringKey:@"msg"]];
    }
} failure:^(NSError *error) {
    [SVProgressHUD showErrorWithStatus:@"网络错误"];
}];    
}

- (id<IConversationModel>)conversationListViewController:(EaseConversationListViewController *)conversationListViewController
                                modelForConversation:(EMConversation *)conversation{
//用环信提供的model就可以了
EaseConversationModel *model = [[EaseConversationModel alloc] initWithConversation:conversation];
//然后根据用户名  往上面赋值
//self.imageAndNameArray为自定义的数组,其中存储的是从自己服务器上请求下来的数据
//数据包括,昵称,头像
for (HPChatListDataModel *dataModel in self.imageAndNameArray) {
    if ([dataModel.mobile isEqualToString:model.conversation.conversationId]) {//根据用户名对应起来
        model.avatarURLPath = dataModel.pic;//头像的网络图片
        model.title = dataModel.name;//昵称
    }
}
return model;
}
//下拉刷新
  - (void)tableViewDidTriggerHeaderRefresh{
//super必须要有  要不会有问题
[super tableViewDidTriggerHeaderRefresh];
}
  #pragma mark delegate
- (void)conversationListViewController:(EaseConversationListViewController *)conversationListViewController
        didSelectConversationModel:(id<IConversationModel>)conversationModel{
EaseConversationModel *model = (EaseConversationModel *)conversationModel;
//自定义点击cell推出的viewcontroller
ChatViewController *viewController = [[ChatViewController alloc]initWithConversationChatter:model.conversation.conversationId conversationType:(EMConversationTypeChat)];
viewController.talkImg = model.avatarURLPath;
viewController.talkName = model.title;
[self.navigationController pushViewController:viewController animated:YES];
}
  - (void)viewWillAppear:(BOOL)animated {
[self tableViewDidTriggerHeaderRefresh];
}
  - (void)reloadData {
[self tableViewDidTriggerHeaderRefresh];
}

5. 获取未读消息数量 用来然后显示小红点

NSArray *conversations = [[EMClient sharedClient].chatManager getAllConversations];
NSInteger unreadCount = 0;
for (EMConversation *converstaion in conversations) {
    unreadCount  += converstaion.unreadMessagesCount;
}

用 forin 的方式来获取数量

6.单击聊天的头像然后显示个人信息的功能

让ChatViewController 遵循EaseMessageCellDelegate
然后别忘了 self.delegate = self;
然后实现代理方法

- (void)messageViewController:(EaseMessageViewController *)viewController
  didSelectAvatarMessageModel:(id<IMessageModel>)messageModel {
   //判断 model 的 nickname 是不是本人的 name 这里因为上面修改昵称的时候把这个 nickname 从 id 改成 name 了 所以这里判断的时候要用 name 来判断 不能用 id 了
if ([messageModel.nickname isEqualToString:@"本人名字"]) {
    //跳转到个人信息
} else {
    //跳转到对方信息     
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,815评论 25 707
  • 点击查看原文 Web SDK 开发手册 SDK 概述 网易云信 SDK 为 Web 应用提供一个完善的 IM 系统...
    layjoy阅读 13,708评论 0 15
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,633评论 18 139
  • 1)项目里面不需要环信SDK的太多功能,只是想要聊天和好友功能,其他都不用,那SDK一定要总是跟着更新么? a.环...
    DefaultYuan阅读 26,550评论 17 59
  • 这是我第一次读也是第一次推荐我自己专业外的教科书。 它的全名是叫做《超级IP互联网新物种方法论》。 这类书几乎是我...
    SHEROtomorrow阅读 117评论 0 2