环信SDK 头像、昵称、表情自定义和群聊设置的实现 一(附源码)

时间:2023-01-12 22:34:30

前言:

环信的SDK在公司的项目中有用到,现在用到的是群聊的部分,这里我们分析总结一下自己对环信给的DEMO大概的拆解一下,说说我们怎么样充分的利用这个demo来写我们所需要的业务。这个也由于篇幅的原因,实在没办法写成一篇博客,我们今天先说说它的一个文件解析昵称头像的实现。写这篇博客环信也是更新到3.0版本了,我们就按照3.0的版本分析一下,先看看这整个Demo的大概的文件;

环信SDK 头像、昵称、表情自定义和群聊设置的实现 一(附源码)

刚开始,使用这个Demo的时候,有些人不知道自己需要的到底是什么文件,一个劲的恨不得连整个Demo全都拉进来,建议大家千万不要这样子做,你花点时间好好研究一些,看一下整个Demo有哪些你是用的着的,有哪些你是用不着的,找有用的拉进自己的项目中!给大家看看我觉得你用的着的一下文件,先看这整个大文件夹EaseUI,环信的文件我用到的全都在这里了。

环信SDK 头像、昵称、表情自定义和群聊设置的实现 一(附源码)

我自己拉到项目中的就这么多,当然这个也因需求有个具体的不同,说两个地方:

一: 关于3rdparty这个文件,这里面是第三方的文件,有些事环信二次封装的,你一定要看清楚,已经在你项目中的,建议不要再拉进来!!环信封装的一些,比如图片浏览三方这些,你要自己项目中已经存在这样功能的第三方就不要再重复拉进来。保持整个项目代码的整洁,避免混乱和一些不懂也没用的代码出现,给以后造成困难!

二:Resources这个文件,这里面的图片我几乎是已经删除干净了,我们自己项目中的UI肯定是要自己重新写的,不能直接连图片就不改动的用环信的Demo,建议这里这样做,等你们的设计师做好相应的UI切图之后,你拿到图片再找环信对应的是那张,全局搜索这张图片的名字,找到位置,看清楚了再把自己的UI切图名称换上去!

三:说说环信SDK,因为自己的项目中还是有网易云直播SDK和支付宝微信的SDK,比较的多,这时候你一定要注意静态文件!避免这里面出现冲突!其实只要仔细点,集成环信这一步我相信大部分人都没啥问题,集成这个也不是我们今天说的重点,我们把重点放在功能解析Demo上面!

重点是这两个文件:Class 和 EaseUI

恩,是的,重点就是这个文件,重点都在这个文件夹当中,我们先看看Class这个文件夹当中的内容:

环信SDK 头像、昵称、表情自定义和群聊设置的实现 一(附源码)

说这么几点,先看到这里的话,我的给大家说一下,

一:这里的三个文件CoreData文件就是本地化的一些存储,ChatGroup是关于群聊的一些文件,剩下的几乎都在Chat这个文件夹当中了。

二:APPDelegate的几个类别,写的还是不错的,这说的不是说代码多精简,看着这里我也真的是学习到了,以后这样的话我们的支付,聊天,推送等等都可以一个功能一个功能的区分开了,简单,明了!!看看下面我们项目中的真实按照这思路写的,希望大家看了都可以学到思路,具体怎么写的,你可以看看Demo里面的代码,有问题也可以来找我!我尽我所能!

环信SDK 头像、昵称、表情自定义和群聊设置的实现 一(附源码)

在说说这个 EaseUI,这么说吧,只要和界面相关的东西都在这个文件夹里面!!EaseUI这里面最重要的是ViewController这个文件夹了:环信SDK 头像、昵称、表情自定义和群聊设置的实现 一(附源码)

箭头标注出来的地方,大家注意这个继承关系!

仔细说说下面的功能:

一:头像和昵称

给大家看看下面的效果图,这是自己我们项目中的界面截图:

环信SDK 头像、昵称、表情自定义和群聊设置的实现 一(附源码)

好,我们说说这个昵称和头像,官方有给出这两个方法来处理头像;

方法一 从APP服务器获取昵称和头像

  • 昵称和头像的获取:当收到一条消息(群消息)时,得到发送者的用户ID,然后查找手机本地数据库是否有此用户ID的昵称和头像,如没有则调用APP服务器接口通过用户ID查询出昵称和头像,然后保存到本地数据库和缓存,下次此用户发来信息即可直接查询缓存或者本地数据库,不需要再次向APP服务器发起请求

  • 昵称和头像的更新:当点击发送者头像时加载用户详情时从APP服务器查询此用户的具体信息然后更新本地数据库和缓存。当用户自己更新昵称或头像时,也可以发送一条透传消息到其他用户和用户所在的群,来更新该用户的昵称和头像。

方法二 从消息扩展中获取昵称和头像

  • 昵称和头像的获取:把用户基本的昵称和头像的URL放到消息的扩展中,通过消息传递给接收方,当收到一条消息时,则能通过消息的扩展得到发送者的昵称和头像URL,然后保存到本地数据库和缓存。当显示昵称和头像时,请从本地或者缓存中读取,不要直接从消息中把赋值拿给界面(否则当用户昵称改变后,同一个人会显示不同的昵称)。

  • 昵称和头像的更新:当扩展消息中的昵称和头像URI与当前本地数据库和缓存中的相应数据不同的时候,需要把新的昵称保存到本地数据库和缓存,并下载新的头像并保存到本地数据库和缓存。

这里项目采用的是方法二,通过扩展消息来添加头像和昵称:我们一句一句的实现上面的话,先实现这一条:当收到一条消息时,则能通过消息的扩展得到发送者的昵称和头像URL,然后保存到本地数据库和缓存。

下面的两个文件是通过FMDB缓存的,通过CoreData肯定也是没有问题的,下面是缓存文件的源码文件ChatUserDataManagerHelper.h

#import <Foundation/Foundation.h>
#import "UserInfoModel.h"
#import "FMDB.h" @interface ChatUserDataManagerHelper : NSObject /**
保存用户数据,登录创建Model保存 @param userinfoDic 用户数据字典
*/
+(void)saveUserInfoModel:(UserInfoModel*)userInfo; /**
保存用户数据,收到消息的扩展是字典类型,用这个方法直接保存。 @param userinfoDic 用户数据字典
*/
+(void)saveUserInfoDictionary:(NSDictionary *)userinfoDic; /**
根据一个userID 查询一个用户数据 @param userid 用户id
@return UserInfoModel 返回一个用户Model
*/
+(UserInfoModel *)queryByuserEaseMobId:(NSString *)userid; @end

还有就是ChatUserDataManagerHelper.m文件了:

#import "ChatUserDataManagerHelper.h"

#define DBNAME @"cache_data.db"

@implementation ChatUserDataManagerHelper

/**
类方法创建一张表单 @param FMDBTable FMDBTable表
*/ +(void)createTable:(FMDatabase *)Database
{
// 打开
if ([Database open]) { // 要是不存在UserInfo表单
if (![Database tableExists :@"userinfo"]) { // 创建这张表单,参数(用户ID,用户名称,用户头像)
if ([Database executeUpdate:@"create table userinfo (userid text, username text, userimage text)"]) { // NSLog(@"create table success"); }else{ // NSLog(@"fail to create table");
} }else { // NSLog(@"table is already exist");
} // 打开失败
}else{ // NSLog(@"fail to open");
}
} /**
从userinfo清除所有信息 @param FMDBTable FMDBTable表
*/
+ (void)clearTableData:(FMDatabase *)Database
{
if ([Database executeUpdate:@"DELETE FROM userinfo"]) { //NSLog(@"clear successed"); }else{ // NSLog(@"fail to clear");
}
} /**
获取FMDatabase @return FMDatabase
*/
+(FMDatabase*)getFMDB{ NSString * docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSString * FMDBPath = [docsPath stringByAppendingPathComponent:DBNAME];
FMDatabase * Database = [FMDatabase databaseWithPath:FMDBPath];
[self createTable:Database];
return Database;
} /**
保存用户Model @param userInfo userInfo description
*/
+(void)saveUserInfoModel:(UserInfoModel*)userInfo{ [ChatUserDataManagerHelper SaveUserInfoWithUserEaseMobId:userInfo.userEaseMobId andUserHeaderImageUrl:userInfo.userHeaderImageUrl andUserNickName:userInfo.usernickName];
} /**
根据创建的用户数据Model,保存用户信息 @param easeMobId 用户ID
@param imageUrl 用户头像
@param nickName 用户昵称
*/ +(void)SaveUserInfoWithUserEaseMobId:(NSString *)easeMobId andUserHeaderImageUrl:(NSString*)imageUrl andUserNickName:(NSString*)nickName{ NSMutableDictionary * userDic = [NSMutableDictionary dictionary]; [userDic setValue:easeMobId forKey:CHATUSERID];
[userDic setValue:imageUrl forKey:CHATUSRTHEADIMAGE];
[userDic setValue:nickName forKey:CHATUSERNICK]; [ChatUserDataManagerHelper saveUserInfoDictionary:userDic];
} /**
保存用户数据 @param userinfoDic 用户数据字典
*/
+(void)saveUserInfoDictionary:(NSDictionary *)userinfoDic{ FMDatabase * dataBase = [self getFMDB]; NSString * userid = [userinfoDic objectForKey:CHATUSERID]; if ([dataBase executeUpdate:@"DELETE FROM userinfo where userid = ?", userid]) { debugLog(@"删除成功"); }else{ debugLog(@"删除失败");
} NSString *username = [userinfoDic objectForKey:CHATUSERNICK];
NSString *userimage = [userinfoDic objectForKey:CHATUSRTHEADIMAGE];
if ([dataBase executeUpdate:@"INSERT INTO userinfo (userid, username, userimage) VALUES (?, ?, ?)", userid,username,userimage]) { debugLog(@"插入成功"); }else{ debugLog(@"插入失败");
} // NSLog(@"%d: %@", [db lastErrorCode], [db lastErrorMessage]);
FMResultSet *rs = [dataBase executeQuery:@"SELECT userid, username, userimage FROM userinfo where userid = ?",userid]; if ([rs next]) { NSString * userid = [rs stringForColumn:@"userid"];
NSString * username = [rs stringForColumn:@"username"];
NSString * userimage = [rs stringForColumn:@"userimage"];
debugLog(@"查询一个 %@ %@ %@",userid,username,userimage);
} rs = [dataBase executeQuery:@"SELECT userid, username, userimage FROM userinfo"];
while ([rs next]) {
NSString * userid = [rs stringForColumn:@"userid"];
NSString * username = [rs stringForColumn:@"username"];
NSString * userimage = [rs stringForColumn:@"userimage"]; debugLog(@"查询所有 %@ %@ %@",userid,username,userimage);
} [rs close]; // NSLog(@"%d: %@", [db lastErrorCode], [db lastErrorMessage]);
[dataBase close];
} /**
根据一个userID 查询一个用户数据 @param userid 用户id
@return UserInfoModel 返回一个用户Model
*/ +(UserInfoModel *)queryByuserEaseMobId:(NSString *)userid { FMDatabase * dataBase = [self getFMDB]; if ([dataBase open]) { FMResultSet *rs = [dataBase executeQuery:@"SELECT userid, username, userimage FROM userinfo where userid = ?",userid]; if ([rs next]) { UserInfoModel * userInfo = [[UserInfoModel alloc] init]; userInfo.userEaseMobId = [rs stringForColumn:@"userid"];
userInfo.usernickName = [rs stringForColumn:@"username"];
userInfo.userHeaderImageUrl = [rs stringForColumn:@"userimage"]; debugLog(@"查询一个 %@",userInfo);
return userInfo; }else{ return nil;
}
}else{ return nil;
}
} @end

注意: 通过上面的代码,你就实现了存储的功能。不过你的记着,在登录成功之后你得先把自己的信息存储起来,在更改了个人资料之后,你要更新这里的存储信息。

我们再说这个发送消息的时候,把自己的个人信息附加在扩展消息当中发送出去,这里我们就用发送文本消息为例子,其他的都一样:

你找到EaseSDKHelper.m这个文件,这里面有这个方法

+(EMMessage *)sendTextMessage:(NSString *)text  to:(NSString *)toUser  messageType:(EMChatType)messageType  messageExt:(NSDictionary *)messageExt

说说这里,这个你看看Demo的话你就可以看到,所有的信息发送都是EaseSDKHelper这个类发送的,由于这个EaseMessageViewController控制器已经代码行数够多了,就不要再在这里添加了,写在EaseSDKHelper,在EaseMessageViewController中有下面这个方法,这个方法就是发送消息的

- (void)_sendMessage:(EMMessage *)message

看看EaseSDKHelper.m中我们怎样添加扩展消息发送的,

#pragma mark - send message
+(EMMessage *)sendTextMessage:(NSString *)text
to:(NSString *)toUser
messageType:(EMChatType)messageType
messageExt:(NSDictionary *)messageExt{ NSMutableDictionary * extDictionary = nil;
// 这里要加判断,因为群聊消息的扩展和直播聊天室的扩展会冲突
if (messageType == EMChatTypeGroupChat) { //这是为了区分一下表情的扩展消息
if (!messageExt) { extDictionary = [self reGetMessageExt]; }else{ //扩展消息字典
extDictionary = [[NSMutableDictionary alloc]initWithDictionary:messageExt];
[extDictionary addEntriesFromDictionary:[self reGetMessageExt]]; }
} NSString *willSendText = [EaseConvertToCommonEmoticonsHelper convertToCommonEmoticons:text];
EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithText:willSendText];
NSString *from = [[EMClient sharedClient] currentUsername];
EMMessage *message = [[EMMessage alloc] initWithConversationID:toUser from:from to:toUser body:body ext:extDictionary];
message.chatType = messageType;
return message;
} // 获取消息扩展,这里不要纠结,我这里只是去了一下自己本地存储的个人信息,你把自己的取出来拼成一个字 // 典返回就可以了
+(NSMutableDictionary*)reGetMessageExt{ NSMutableDictionary *extDic = [NSMutableDictionary dictionary];
NSString * userId = [NSString stringWithFormat:@"%@",READUSERDEFAULTS(UserId)];
[extDic setValue:userId forKey:CHATUSERID];
[extDic setValue:READUSERDEFAULTS(UserName) forKey:CHATUSERNICK];
[extDic setValue:READUSERDEFAULTS(UserHeadImage) forKey:CHATUSRTHEADIMAGE];
return extDic;
}

最后就是接收到之后的赋值了,在这里进行ChatViewController.m中来写,这里面又有一个方法

- (id<IMessageModel>)messageViewController:(EaseMessageViewController *)viewController  modelForMessage:(EMMessage *)message

看下面这个方法的完整代理:

#pragma mark - EaseMessageViewControllerDataSource
// 数据源方法
- (id<IMessageModel>)messageViewController:(EaseMessageViewController *)viewController
modelForMessage:(EMMessage *)message{ id<IMessageModel> model = nil;
// 根据聊天消息生成一个数据源Model
//NSLog(@"-======%@",message.from);
//debugObj(message.ext); model = [[EaseMessageModel alloc] initWithMessage:message];
NSDictionary * messageDic = message.ext; UserInfoModel * userinfoModel = [ChatUserDataManagerHelper queryByuserEaseMobId:messageDic[CHATUSERID]]; if (userinfoModel != nil) { model.nickname = userinfoModel.usernickName;
model.avatarURLPath = userinfoModel.userHeaderImageUrl;
}
// 默认头像
//model.avatarImage = [UIImage imageNamed:@"EaseUIResource.bundle/user"];
//Placeholder image for network error
//项目图片取出错误的时候就用这张代替
model.failImageName = @"icon_Default-Avatar";
return model;
}

其实到这里头像和昵称差不多可以了,在具体的Cell中,你不需要给它再去赋值,因为这些Demo当中已经写好了,你要一直写到这里了,你可以试试效果了!剩下的部分内容明天发出来,不然篇幅有点过长了!

环信SDK 头像、昵称、表情自定义和群聊设置的实现 一(附源码)的更多相关文章

  1. Android 环信聊天头像昵称显示解决方案

    从消息扩展中获取昵称和头像 昵称和头像的获取:把用户基本的昵称和头像的URL放到消息的扩展中,通过消息传递给接收方,当收到一条消息时,则能通过消息的扩展得到发送者的昵称和头像URL,然后保存到本地数据 ...

  2. jquery自定义插件结合baiduTemplate&period;js实现异步刷新(附源码)

    上一篇记录了BaiduTemplate模板引擎使用示例附源码,在此基础上对使用方法进行了封装 自定义插件jajaxrefresh.js 代码如下: //闭包限定命名空间 (function ($) { ...

  3. cesium 之自定义气泡窗口 infoWindow 后续优化篇(附源码下载)

    前言 cesium 官网的api文档介绍地址cesium官网api,里面详细的介绍 cesium 各个类的介绍,还有就是在线例子:cesium 官网在线例子,这个也是学习 cesium 的好素材. 该 ...

  4. 环信SDK与Apple Watch的结合(2)

    这一篇主要是介绍怎么拖apple watch上的相关页面,附源码EMWatchOCDemo. 需要在工程中的“EMWatchOCDemo WatchKit App”中进行操作,该文件夹的结构如图 Wa ...

  5. android-使用环信SDK开发即时通信功能及源代码下载

    近期项目中集成即时聊天功能.挑来拣去,终于选择环信SDK来进行开发,选择环信的主要原因是接口方便.简洁.说明文档清楚易懂.文档有android.ios.和后台server端.还是非常全的. 环信官网: ...

  6. 基于环信SDK的IM即时通讯填坑之路&lpar;vue&rpar;

    公司最近使用第三方环信SDK的进行通信聊天,基本已完成.记录下填坑之路 1.可以通过以下方式引用 WebSDK 1.安装 npm install easemob-websdk --save 2. 先 ...

  7. 环信SDK与Apple Watch的结合(1)

    该系列是记录在apple watch上开发IM,用到了最近挺流行的环信IM SDK. 一.先来一段网上随处可查到的信息: 1.两种分辨率 1.65寸 312*390 1.5寸 272*340 2.开发 ...

  8. 李洪强iOS开发之-环信02&period;2&lowbar;环信官网下载环信 SDK

    李洪强iOS开发之-环信02.2_环信官网下载环信 SDK 移动客服即时通讯云 iOS SDK 当前版本:V3.1.4 2016-07-08 [ 版本历史 ] | 开发指南 | 知识库 | Demo源 ...

  9. 环信SDK集成

    利用环信SDK可以实现即时通讯,但在集成的过程中碰到了不少的坑. 注意 选择项目路径,这里以最新版环信demo为例 注意:环信的ChatDemoUI这个demo里边因为研发的同事为了照顾老版本的And ...

随机推荐

  1. osgearth各个例子功能概述

    osgearth各个例子功能概述 转自:http://blog.csdn.net/wl198302/article/details/21177309 最近在学习osgearth,对其还不是很理解,有些 ...

  2. 《c程序设计语言》读书笔记-字符型0-9转为数字0-9

    #include <stdio.h> #define Num 10 int atoi(char s[]); int main() { int c,i = 0; char s[Num]; i ...

  3. c&plus;&plus;11之智能指针

    在c++98中,智能指针通过一个模板“auto_ptr”来实现,auto_ptr以对象的方式来管理堆分配的内存,在适当的时间(比如析构),释放所获得的内存.这种内存管理的方式只需要程序员将new操作返 ...

  4. ADODB&period;Connection 错误 &&num;39&semi;800a0e7a&&num;39&semi; 未找到提供程序 该程序可能未正确安装

    今天调程序的时候发现的,错误提示如下: ADODB.Connection 错误 '800a0e7a' 未找到提供程序.该程序可能未正确安装. /conn.asp,行 6 因为系统是64位的win7或w ...

  5. Android测试分析二

    什么是android测试,分为黑盒测试和白盒测试. 黑盒就是测试人员看不到代码的,针对需求而进行的一系列测试动作,看代码所展现出来的效果是否和需求一样,或者有什么意外的情况没有处理等,一般开发交给测试 ...

  6. sed与正则用法收集

    1.将文本每行最后七个字符换成!号 sed   -n  's#.\{7\}$#!#p' ooo 在文本的每一行前添加#符号 sed  's/^.\?/#&/' passwd &  替代 ...

  7. Java序列化和反序列化,你该知道得更多

    序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程.在序列化期间,对象将其当前状态写入到临时或持久性存储区.以后,可以通过从存储区中读取或反序列化对象的状态,重新 ...

  8. 前端 CSS 目录

    前端 CSS 介绍 前端 CSS语法 前端 CSS 注释

  9. unity3D 中的C&num;脚本一个类调用另一类中简单方法

    案例展示 SubMenuManage类中的实例化代码如下: static SubMenuManage sub_this; public static SubMenuManage Instance() ...

  10. Web服务器缓存

    前面提到的一些缓存技术都是有我们的动态才程序控制的,现在的web服务器功能越来越强大,常用的web服务器软件也都内置了缓存功能,下面我们就简单的说下服务器端缓存的应用. 首先,我们先来介绍一下URL映 ...