android中如何显示开发者服务器上的昵称和头像

本文方法已经废弃!请看作者另外一篇文章:


在android中5分钟实现昵称头像的显示  http://www.imgeek.org/article/825308757


无论是IOS还是安卓,集成环信SDK遇到的第一个问题,就是如何显示自有用户体系中的昵称和头像。运行环信的demo app,注册用户是直接使用环信ID(username)作为用户名,但是在我们实际应用中,需要将自有用户体系的UserId生成GUID作为环信ID(username)【参考:http://docs.easemob.com/im/100 ... users】,这时候如果不经过处理,则会显示如下界面:
444.png


那么如何处理,才能显示正确的用户昵称和头像呢?
其实官方已经提供有解决方案了,只不过没有给出示例代码而已。
http://docs.easemob.com/im/490 ... kname
 
引用一下关键文字:
方法二:从消息扩展中获取昵称和头像

昵称和头像的获取:把用户基本的昵称和头像的URL放到消息的扩展中,通过消息传递给接收方,当收到一条消息时,则能通过消息的扩展得到发送者的昵称和头像URL,然后保存到本地数据库和缓存。当显示昵称和头像时,请从本地或者缓存中读取,不要直接从消息中把赋值拿给界面(否则当用户昵称改变后,同一个人会显示不同的昵称)。
昵称和头像的更新:当扩展消息中的昵称和头像 URI 与当前本地数据库和缓存中的相应数据不同的时候,需要把新的昵称保存到本地数据库和缓存,并下载新的头像并保存到本地数据库和缓存。
 
没错,官方提供了两种思路,鉴于项目的实际情况,我选择了【方法二】。
于是,无论安卓,还是IOS,我们都是这样处理的:
【1】.APP间传递用户属性信息:发送(文本、图片...)消息时,要在消息扩展(message.ext)中附带当前用户的属性信息;
【2】.本地缓存用户信息:在接收消息的回调函数里,读取消息扩展(message.ext)里用户属性(键值对)信息;如果本地缓存(sqlite)不存在该用户,则新增缓存记录,如果存在,则更新记录;(用户登录或注册成功后,也要更新用户缓存信息)
【3】.获取用户属性信息:在需要显示昵称的地方,根据环信ID,读取sqlite缓存数据,获取用户昵称和头像;
 
用户属性信息:ChatUserId(环信ID),ChatUserNick(用户昵称), ChatUserPic(用户头像,完整的url地址);
 
关键代码:
/***************** 环信用户缓存信息 *******************************/
public static final String ChatUserId = "ChatUserId";// 用户的环信ID
public static final String ChatUserPic = "ChatUserPic";
public static final String ChatUserNick = "ChatUserNick";
/***************** 环信用户缓存信息***********end ********************/



UserInfoCacheSvc.java是环信用户信息缓存管理类
/**
* 缓存用户信息(主要用于聊天显示昵称和头像)
*/
public class UserInfoCacheSvc {
public static List<UserApiModel> getAllList(){
Dao<UserApiModel, Integer> daoScene = SqliteHelper.getInstance().getUserDao();
try {
List<UserApiModel> list = daoScene.queryBuilder().query();
return list;
} catch (SQLException e) {
e.printStackTrace();
}

return null;
}

public static UserApiModel getByChatUserName(String chatUserName){
Dao<UserApiModel, Integer> dao = SqliteHelper.getInstance().getUserDao();
try {
UserApiModel model = dao.queryBuilder().where().eq("EaseMobUserName", chatUserName).queryForFirst();
return model;
} catch (SQLException e) {
e.printStackTrace();
}

return null;
}

public static UserApiModel getById(long id){
Dao<UserApiModel, Integer> dao = SqliteHelper.getInstance().getUserDao();
try {
UserApiModel model = dao.queryBuilder().where().eq("Id", id).queryForFirst();
return model;
} catch (SQLException e) {
e.printStackTrace();
}

return null;
}

public static boolean createOrUpdate(String chatUserName, String userNickName, String avatarUrl){
try {
Dao<UserApiModel, Integer> dao = SqliteHelper.getInstance().getUserDao();

UserApiModel user = getByChatUserName(chatUserName);

int changedLines = 0;
if (user == null){
user = new UserApiModel();
user.setUsername(userNickName);
user.setHeadImg(avatarUrl);
user.setEaseMobUserName(chatUserName);

changedLines = dao.create(user);
}else {
user.setUsername(userNickName);
user.setHeadImg(avatarUrl);
user.setEaseMobUserName(chatUserName);

changedLines = dao.update(user);
}

if(changedLines > 0){
Log.i("UserInfoCacheSvc", "操作成功~");
return true;
}
} catch (SQLException e) {
e.printStackTrace();
Log.e("UserInfoCacheSvc", "操作异常~");
}

return false;
}

public static boolean createOrUpdate(UserApiModel model){

if(model == null) return false;

try {
Dao<UserApiModel, Integer> dao = SqliteHelper.getInstance().getUserDao();

UserApiModel user = getById(model.Id);

if (!StringUtils.isNullOrEmpty(model.getHeadImg())){
String fullPath = "http://image.baidu.com" + model.getHeadImg();
//特别注意:这里用是图片的完整链接地址,如果要取缩略图,需要服务端配合;

model.setHeadImg(fullPath);
}
int changedLines = 0;
if (user == null){
changedLines = dao.create(model);
}else {
model.setRecordId(user.getRecordId());
changedLines = dao.update(model);
}

if(changedLines > 0){
Log.i("UserInfoCacheSvc", "操作成功~");
return true;
}
} catch (SQLException e) {
e.printStackTrace();
Log.e("UserInfoCacheSvc", "操作异常~");
}

return false;
}

}
首先要在用户登录或注册成功后,返回用户登录信息Model时,缓存一下用户信息,@DatabaseField注解是ormlite库的特性,文章后面的附件包含了此类库:
public class UserApiModel implements Serializable {

@DatabaseField(generatedId=true)
private int RecordId;

@DatabaseField

public long Id;

@DatabaseField
public String Username;

@DatabaseField
public String Email;

@DatabaseField
public String HeadImg;

@DatabaseField
public String EaseMobUserName;

@DatabaseField
public String EaseMobPassword;
}
 
private static void SaveUserInfo(UserApiModel userInfo){

if(userInfo == null) return;

// 缓存用户信息
PrefUtils.setUserId(userInfo.Id);
PrefUtils.setUserEmail(userInfo.Email);
PrefUtils.setUserName(userInfo.Username);
PrefUtils.setUserPic(userInfo.HeadImg);
PrefUtils.setUserChatId(userInfo.EaseMobUserName);
PrefUtils.setUserChatPwd(userInfo.EaseMobPassword);

UserInfoCacheSvc.createOrUpdate(userInfo);
}
然后在接收环信消息的回调函数里保存用户信息,ActyMain.java是我们项目的主框架,我们在这里写了回调函数,无论群聊还是单聊消息,都会调用这里:
private EMMessageListener mMessageListener = new EMMessageListener() {

@Override
public void onMessageReceived(List<EMMessage> messages) {
// 提示新消息
for (EMMessage message : messages) {

// 先将头像和昵称保存在本地缓存
try {
String chatUserId = message.getStringAttribute(SharePrefConstant.ChatUserId);
String avatarUrl = message.getStringAttribute(SharePrefConstant.ChatUserPic);
String nickName = message.getStringAttribute(SharePrefConstant.ChatUserNick);

UserInfoCacheSvc.createOrUpdate(chatUserId, nickName, avatarUrl);

} catch (HyphenateException e) {
e.printStackTrace();
}

ChatHelper.getInstance().getNotifier().onNewMsg(message);
}
refreshUIWithMessage();
}

// 此处省略N行代码....
};
在安卓项目里,环信页面显示昵称和头像时,都会统一从DemoHelper的getUserInfo函数里获取信息,所以我们要在这里从缓存取用户头像和昵称:
private EaseUser getUserInfo(String username){
//获取user信息,demo是从内存的好友列表里获取,
//实际开发中,可能还需要从服务器获取用户信息,
//从服务器获取的数据,最好缓存起来,避免频繁的网络请求
EaseUser user = null;
// 从缓存里取昵称和头像
UserApiModel userInfo = UserInfoCacheSvc.getByChatUserName(username);
if (userInfo != null){
user = new EaseUser(username);
user.setAvatar(userInfo.getHeadImg());
user.setNick(userInfo.getUsername());
}

return user;
}
最后,为了让另外一个客户端也能正确显示头像和昵称,app发送消息时,要在消息扩展里附带用户信息,代码写在
ChatFragment.java里:
    @Override
public void onSetMessageAttributes(EMMessage message) {
setUserInfoAttribute(message);
}

/**
* 设置用户的属性,
* 通过消息的扩展,传递客服系统用户的属性信息
* @param message
*/
private void setUserInfoAttribute(EMMessage message) {
try {
message.setAttribute(SharePrefConstant.ChatUserId, PrefUtils.getUserChatId());
message.setAttribute(SharePrefConstant.ChatUserNick, PrefUtils.getUserName());
message.setAttribute(SharePrefConstant.ChatUserPic, "http://image.baidu.com" + PrefUtils.getUserPic()) ;//这里用是图片的完整链接地址,如果要取缩略图,需要服务端配合;

} catch (Exception e) {
e.printStackTrace();
}
}
有不当之处,欢迎指正~~~谢谢
部分源码因为是公司项目代码,所以没有在文章里提供(而且代码量太多,也不便于阅读)。需要源码的童鞋,可以联系我。等我有空,我整理一下公司项目,然后再share开源给大家。
相关类文件下载:

 
本文方法已经废弃!请看作者另外一篇文章:
在android中5分钟实现昵称头像的显示  http://www.imgeek.org/article/825308757

如有任何问题,请咨询【环信IM互帮互助群】,群号:340452063,
或者加本人QQ:364223587,加Q请认准以下正宗小马头像:


33 个评论

很棒的一篇的教程。赞赏16元!
之前一直卡在这里 卡了很久很久 直到我看到了这篇文章 ,然后第一时间联系了这位大神,很负责的跟我一起调试,一起查问题,到最后的成功,能够显示头像和昵称,非常感谢,通过扩展属性去设置用户名和昵称 ,真的很快,就是遇到问题就慢一点,反正 ,我这里好了,大家如果有疑问欢迎来提问,真的非常感谢这位大神,谢谢
赞一个,热心的大神!
视频和语音通话不能发扩展消息,头像昵称怎么设置。
视频和语音通话不能发扩展消息,头像昵称怎么设置。
陈同学 能帮下忙吗 视频和语音通话不能发扩展消息,头像昵称怎么设置。
这个我确实忘记考虑了。。。我们的项目又正好木有使用视频和语音通话
不错的一片文章,通过这个文章也解决了困扰我的昵称和头像问题,热心的大神一直在帮我处理问题。直到解决了问题。希望对大家也有所帮助。
写的很好,赞一个
我还没有弄到视频和语音上面
能给个联系方式吗 神 我的联系方式就是我的昵称 求加好友
QQ:364223587
你好我遇到一个问题,就是在聊天页面发送方没有显示自己的头像和昵称但是可以显示接收方的头像和昵称这是什么情况
用户登录或注册成功后,也要更新用户缓存信息哦。
谢谢,功能以实现
思路清晰,真的很好已经成功了
谢谢反馈
真的好吗
打了16元?
看了这篇文章上手,期初还是没有特别清晰的思路,后来加了群,进去反馈了自己的问题,理了一下思路,很成功的解决了问题,楼主人也特好,一直帮着解决问题,有问必答。非常感谢~~顶起来
很不错的一篇文章,解决了困扰我很久的昵称和头像问题,非常感谢这位大神!在集成的过程中,遇到一些问题,大神很耐心的帮我一起解决,非常感谢!
我按照上面的方式弄了但是没实现啊
public static UserApiModel getById(long id){
Dao<UserApiModel, Integer> dao = SqliteHelper.getInstance().getUserDao();
Log.i("-->>", "getById: " + dao.toString());
try {
QueryBuilder<UserApiModel, Integer> builder = dao.queryBuilder();
Where<UserApiModel, Integer> where = builder.where();
Where<UserApiModel, Integer> eq = where.eq("Id", id);
UserApiModel userApiModel = eq.queryForFirst();
LogUtils.i("-->>builder:" + builder + ",where:" + where + ",eq:" + eq);
UserApiModel model = dao.queryBuilder().where().eq("Id", id).queryForFirst();
return model;
} catch (SQLException e) {
e.printStackTrace();
}

return null;
}
大神,queryForFirst()这一行报错,不知道哪里出了问题。
java.lang.NullPointerException: Attempt to invoke virtual method 'android.database.sqlite.SQLiteDatabase android.content.Context.openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase$CursorFactory, android.database.DatabaseErrorHandler)' on a null object reference
搜索:makeCallWithUsername
空值引用,你单步调试一下看看哪个变量为空值了。
我上传头像之后,聊天界面的头像没有同步更新,使用了 setUserProvider 这个方法无效,重启应用后走 application的 setUserProvider 才会更新,请问该怎么解决呢
EaseUI头像和昵称相关类文件_0701 中的PrefUtils这个文件里面
public static final MainApplication mAppContext = (MainApplication)BaseApplication.instance();
这个我只有一个Application 这个那个玩!!
这个用自己的Application实例化就行了啊
SaveUserInfo 这个方法是用来缓存用户信息,这个方法一般写在那,有什么用了,求大神指点。
我文章中已经说得很详细“首先要在用户登录或注册成功后,返回用户登录信息Model时,缓存一下用户信息,@DatabaseField注解是ormlite库的特性,文章后面的附件包含了此类库:”
ChatHelper这是什么类
辅助类
请问楼主这个方法一定要有自己的服务器吗

要回复文章请先登录注册

知识价值的认可,源自您的赞赏

扫描二维码,你的支付将由imGeek代收后转给对方

×