注册

环信(Android)设置头像和昵称的方法(最简单暴力的基于环信demo的集成)。

        最近,经常有朋友问到,如何集成环信头像,怎么才能快速显示头像,因时间紧急,很多朋友都没有时间慢慢的研究代码,这里大家稍微花10分钟看一下文章,看完后再花5分钟改一下代码,即可达到你们所要的效果。
        当然这个是在你直接复制了demo中的工具类和必要的UI的前提下实现的。简短说明简单暴力的方法:除UI外的其他所有类先复制到自己工程中,UI部分MainActivity中的代码需要一个一个复制过去,如与自己项目冲突的需要调整,然后ChatActivity/ChatFragment也复制过去,这就可以进行聊天了。不过头像就是大家所遇到的头像显示不了,昵称显示为环信号码。
        环信官方是有给出头像的设置的,不过大部分朋友看了之后都是晕呼呼的。官方给出的提示如下:方法一 从APP服务器获取昵称和头像


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

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

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

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

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


---------------------------------------------------------------------------------------------
        个人推荐使用方法2,优势比较明显,不仅可以设置头像、昵称,甚至以后出现的是否管理员,或者自己APP中的身份标志,如:店小二、医生、客服等等都可以再定义注明,暴力而简单,不需要考虑对方更新头像或昵称,而软件没重启的情况下怎么去更新头像和昵称等等复杂的问题。本指导以最简单的集成为指导,工具类可使用自己软件中的,或通过别的方式实现。
        方法2的集成步骤:
1、在登录的时候,把自己登录成功时后台返回的信息保存到sharedpreferences中,需要包含需要的头像和昵称。
new Thread(new Runnable() {
@Override
public void run() {
EMClient.getInstance().login(username, password, new EMCallBack() {
@Override
public void onSuccess() {
// 登陆成功,保存用户昵称与头像URL
AppSPUtils.setValueToPrefrences("name", loginBean.getName());
AppSPUtils.setValueToPrefrences("logoUrl", loginBean.getLogoUrl());

// 将自己服务器返回的环信账号、昵称和头像URL设置到帮助类中。
DemoHelper.getInstance().getUserProfileManager().updateCurrentUserNickName(loginBean.getName());
DemoHelper.getInstance().getUserProfileManager().setCurrentUserAvatar(loginBean.getLogoUrl());
DemoHelper.getInstance().setCurrentUserName(loginUser.getHxId()); // 环信Id

// ------以下参考demo中的,加载群组和加载消息。然后跳转到首页-------
2、AppSPUtils是个人写的一个工具类,大家可以自己写一个,给出参考代码。
public class AppSPUtils {

private final static int MODE_SPEC = android.os.Build.VERSION.SDK_INT <= 10 ? 0 : Context.MODE_MULTI_PROCESS;

public static SharedPreferences getSharedPreferences(String name) {
return MainApplication.getContext().getSharedPreferences(name,
Context.MODE_PRIVATE | MODE_SPEC);
}

public static SharedPreferences getAppSharedPreferences() {
return getSharedPreferences(Constants.SP_APP);
}

public static String getValueFromPrefrences(String key, String defaultValue) {
return getValueFromPrefrences(getAppSharedPreferences(), key, defaultValue);
}

public static void setValueToPrefrences(String key, String value) {
try {
SharedPreferences preferences = getAppSharedPreferences();
if (null != preferences) {
preferences.edit().putString(key, value).commit();
}
} catch (Exception e) {
e.printStackTrace();
}
}

// 退出登录时要调用
public static void clean() {
try {
SharedPreferences preferences = getAppSharedPreferences();
if (null != getAppSharedPreferences()) {
getAppSharedPreferences().edit().clear().commit();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
3、保存好自己的信息后,已经成功了四分之一,现在是如何将自己的头像昵称等信息发送出去,最简单的就是使用扩展消息了,在ChatActivity中可以看到,基本上只做了一件事,保证只有一个ChatActivity,那我们的代码在哪里?就在ChatFragment里面。找到代码,可以看到其实它是继承自EaseChatFragment,很多内容在easeui中已经做好了。
这时你会发现ChatFragment类中有一个扩展属性的说明,没错,就是这个方法,把你要发送的内容尽情的发送吧,现附上发送头像和昵称的代码:
@Override
public void onSetMessageAttributes(EMMessage message) {
if (isRobot) {
// 设置消息扩展属性
message.setAttribute("em_robot_message", isRobot);
}

// 通过扩展属性,将userPic和userName发送出去。
String userPic = AppSPUtils.getValueFromPrefrences("logoUrl", "");
if (!TextUtils.isEmpty(userPic)) {
message.setAttribute("userPic", userPic);
}
String userName = AppSPUtils.getValueFromPrefrences("name", "");
if (!TextUtils.isEmpty(userName)) {
message.setAttribute("userName", userName);
}
}
4、发送完成,你已经完成了四分之二的任务了。发送完成后,肯定需要一个接收,其实demo中的广播已经接收好了,那么我们跟随着广播的脚步,来到DemoHelper这个类,初次看这个类,都是云一样的感觉,经过一番查找,发现有个onMessageReceived的方法,并且还有注释“全局监听”,赶紧开工,试试接收吧,可以自己打一下log出来看是不是拿到了我们要的。并且照着demoHelper中的保存方法,将接收到的内容保存起来。
@Override
public void onMessageReceived(List<EMMessage> messages) {
for (EMMessage message : messages) {
message.setMsgTime(System.currentTimeMillis());
//************接收并处理扩展消息***********************
String userName = message.getStringAttribute("userName", "");
String userPic = message.getStringAttribute("userPic", "");
String hxIdFrom = message.getFrom();
EaseUser easeUser = new EaseUser(hxIdFrom);
easeUser.setAvatar(userPic);
easeUser.setNick(userName);

// 存入内存
getContactList();
contactList.put(hxIdFrom, easeUser);
// 存入db
UserDao dao = new UserDao(MainApplication.getContext());
List<EaseUser> users = new ArrayList<EaseUser>();
users.add(easeUser);
dao.saveContactList(users);

getModel().setContactSynced(true);

// 通知listeners联系人同步完毕
notifyContactsSyncListener(true);
if (isGroupsSyncedWithServer()) {
notifyForRecevingEvents();
}

// ******************扩展信息处理完成**********************
EMLog.d(TAG, "onMessageReceived id : " + message.getMsgId());
// 应用在后台,不需要刷新UI,通知栏提示新消息
if (!easeUI.hasForegroundActivies()) {
getNotifier().onNewMsg(message);
}
}
}
5、信息都收到了,就差最后一步就可以显示了,不知道你们是不是激动,反正我是激动了。那在哪里进行显示呢?还是在DemoHelper中,找到getUserInfo方法,代码如下:
private EaseUser getUserInfo(String hxId) {
// 获取user信息,demo是从内存的好友列表里获取,
// 实际开发中,可能还需要从服务器获取用户信息,
// 从服务器获取的数据,最好缓存起来,避免频繁的网络请求

if (hxId.equals(EMClient.getInstance().getCurrentUser())) {
EaseUser currentUserInfo = getUserProfileManager().getCurrentUserInfo();
return currentUserInfo;
}
EaseUser easeUser;
if (contactList != null && contactList.containsKey(hxId)) {

} else { // 如果内存中没有,则将本地数据库中的取出到内存中。
getContactList();
}
// // TODO 获取不在好友列表里的群成员具体信息,即陌生人信息,demo未实现
// if (user == null && getRobotList() != null) {
// user = getRobotList().get(hxId);
// }
easeUser = contactList.get(hxId);
if(easeUser == null){
easeUser = new EaseUser(hxId);
} else {
if(TextUtils.isEmpty(easeUser.getNick())){ // 如果名字为空,则显示环信号码
easeUser.setNick(easeUser.getUsername());
}
}
return easeUser;
}
OK,大功告成,到这里你的头像已经可以显示了。。恭喜你!
有朋友还有疑问,为什么头像是方形的,要变成圆形怎么办?指个路,在easeui中的utils包下,找到EaseUserUtils,这里就是显示用户头像和用户昵称的地方,通过Glide可以轻松显示圆形头像,百度有很多方法,这里就不多讲了,同样,你也可以通过其他图形加载框架来完成。
很多朋友不明白扩展消息的是什么东西,也不明白为什么照着代码敲就能够完成头像的显示,那下面就给大家粗浅的讲讲所涉及到的逻辑关系。
扩展消息:就是你每一次发送消息,都会附带在你发送内容上面的额外消息,他会随着你的内容发送出去,每次会多一点点流量,但微乎其微,个人认为并无多大影响。
显示头像逻辑:区分为本地化缓存和运行内存缓存,在demoHelper中可以发现,有一个成员变量private Map<String, EaseUser> contactList; 这个就是用来保存在运行内存缓存的,只有通过运行缓存,显示头像是最顺畅的,如果每次都从数据库中读取的话,聊天界面会比较卡,有朋友保存在SP里面,以ID做为KEY,头像和昵称等拼接做为value进行缓存,取出后再拆分开分别取值,据说是不卡,大家可以试一下。
         本地化存储是为了在每次打开软件的时候,从本地存储中拿到运行内存中使用做准备,大家可以认真看看demoHelper和MainActivity中的代码。

----------------------------------------------------------------------------------
讲了方法2设置头像,那么方法1,个人不推荐,但这里给出处理的过程,如有个别有需求的,可以按方法1来处理:
1、登录成功后,在手机子线程,访问你们的后台服务器,拿到所有好友的环信ID,头像,昵称。然后按上面的保存方法,保存到本地中,完成后发送广播或EventBus之类到,刷新消息界面和ChatFragment。
2、在getUserInfo中,写和上面扩展消息一样的内容,将如果运行缓存和本地都拿不到,则发起网络请求到后台获取头像,等请求到内容后,再发出广播或EventBus通知刷新消息界面和ChatFragment。

-------------------------------------------------------------------------------------
以上仅为本人在开发过程中的一点小小心得,demo中的保存运存和本地储存的方法,大家也可以单独写,并不会影响程序的运行,当然也有兄弟写过发表,大概根据实际情况择优选取即可。小弟学识浅薄,如果有错漏的,欢迎大家纠正。
如有需要,可以到494167135群中与大家交流学习。本人:乐奇奇,QQ:730326762。大家优先加群,谢谢。
 

18 个评论

怒赞
亲测有效!赞一个!
可用可用,只是为什么环信的那个默认图片成了背景,查查看
谢谢。亲测真的可以。但是我为什么只显示好友的头像,我自己的头像该怎么设置呢?
作者在吗?notifyForRecevingEvents();这个方法没有啊。另外,有个问题,这样使用后,接收到的消息是原消息的两倍。而不是原来的消息。
notifyForRecevingEvents()你找到在哪里了吗?我也不知道在哪里?知道回下被
notifyForRecevingEvents这个方法是3.1.3的demo中的,现在已经移除了,用最新的SDK的demo的话,可以直接注释掉这个方法。
notifyForRecevingEvents这个方法是3.1.3的demo中的,现在已经移除了,用最新的SDK的demo的话,可以直接注释掉这个方法。
问下……在环信服务器上修改昵称的代码是哪一句?
环信服务器上不保存个人的昵称的,需要自己服务器实现。
环信服务器保存个人id,密码,昵称,头像……你在后台可以看到 之前修改成功过,但是代码找不到了,好捉急! 用新文档里面给的EMClient.getInstance().updateCurrentUserNick()也不管用
Constants.SP_APP 是什么
Constants.SP_APP 是什么啊?
Constants.SP_APP 是什么啊?!!
作者您好,我按照您的方法设置完之后,好友都不显示出来了,这是怎么回事呀
你好,我按照作者所说的改了,但只有自己的头像显示了,好友的没有显示,你知道是怎么回事吗?
按照文章一步一步来,总算搞定,复制文件就花了一个小时,其中是各种出问题,各种挠头,不过总算还是解决了,总结下,还是要细心保证每一步的代码都没问题。
您好,你的能正常显示了吗,我遇到了一个问题 能否交流一下

要回复文章请先登录注册