Android环信官方集成文档:http://docs.easemob.com/im/200androidclientintegration/10androidsdkimport
我在项目里集成环信时是根据环信官方EaseUI进行集成的,EaseUI环信说明文档:http://docs.easemob.com/im/200androidclientintegration/135easeuiuseguide
这里只介绍怎么通过扩展消息显示头像和昵称,参考文章:在android中5分钟实现环信昵称头像的显示,感谢作者!
一、将以下三个java文件复制到自己的项目里:
import android.content.Context; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.util.Log; import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper; import com.j256.ormlite.dao.Dao; import com.j256.ormlite.support.ConnectionSource; import com.j256.ormlite.table.TableUtils; /** * sqlite数据库辅助类 * Created by lkj */ public class SqliteHelper extends OrmLiteSqliteOpenHelper { private final String LOG_TAG = getClass().getSimpleName(); // 数据库名字 private static final String DATABASE_NAME = "im_user_cache.db"; // 版本号 private static final int DATABASE_VERSION = 1; private static SqliteHelper mInstance; private Dao<UserCacheInfo, Integer> mUserInfoDao = null; public SqliteHelper(Context context){ super(context, DATABASE_NAME, null, DATABASE_VERSION); } public synchronized static SqliteHelper getInstance(){ if (mInstance == null) { ///TODO:: 把这里的 DemoApplication.getInstance() 换成自己的Application类实例对象。例如:new MainApplication() mInstance = new SqliteHelper(MyApplication.getInstance()); } return mInstance; } /** * 创建SQLite数据库 */ @Override public void onCreate(SQLiteDatabase sqliteDatabase, ConnectionSource connectionSource) { try { TableUtils.createTable(connectionSource, UserCacheInfo.class); } catch (SQLException e) { Log.e(LOG_TAG, "Unable to create datbases", e); } catch (java.sql.SQLException e) { e.printStackTrace(); } } /** * 更新SQLite数据库 */ @Override public void onUpgrade( SQLiteDatabase sqliteDatabase, ConnectionSource connectionSource, int oldVer, int newVer) { try { TableUtils.dropTable(connectionSource, UserCacheInfo.class, true); onCreate(sqliteDatabase, connectionSource); } catch (SQLException e) { Log.e(LOG_TAG, "Unable to upgrade database from version " + oldVer + " to new " + newVer, e); } catch (java.sql.SQLException e) { e.printStackTrace(); } } public Dao<UserCacheInfo,Integer> getUserDao() throws SQLException{ if(mUserInfoDao == null){ try { mUserInfoDao = getDao(UserCacheInfo.class); } catch (Exception e) { e.printStackTrace(); } } return mUserInfoDao; } }
import com.google.gson.Gson; import com.j256.ormlite.field.DatabaseField; import com.j256.ormlite.table.DatabaseTable; /** * 用户缓存信息类 * 需要ormlite库支持 * Created by Martin on 2017/4/24. */ @DatabaseTable(tableName="UserCacheInfo") public class UserCacheInfo{ @DatabaseField(generatedId=true) private int id; /*环信ID*/ @DatabaseField(index = true) private String userId; /*昵称*/ @DatabaseField private String nickName; /*头像*/ @DatabaseField private String avatarUrl; /*数据过期时间*/ @DatabaseField(canBeNull = false) private long expiredDate; // 必须顶一个无参数的构造函数,否则会报【virtual method】异常 UserCacheInfo(){} /*将json字符串转换成model*/ public static UserCacheInfo parse(String jsonStr) { return (new Gson()).fromJson(jsonStr, UserCacheInfo.class); } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } public String getNickName() { return nickName; } public void setNickName(String nickName) { this.nickName = nickName; } public String getAvatarUrl() { return avatarUrl; } public void setAvatarUrl(String avatarUrl) { this.avatarUrl = avatarUrl; } public long getExpiredDate() { return expiredDate; } public void setExpiredDate(long expiredDate) { this.expiredDate = expiredDate; } }
import android.content.Context; import android.text.TextUtils; import android.util.Log; import com.alibaba.fastjson.JSON; import com.google.gson.Gson; import com.hyphenate.chat.EMClient; import com.hyphenate.chat.EMMessage; import com.hyphenate.easeui.domain.EaseUser; import com.j256.ormlite.dao.Dao; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 用户缓存管理类 * Created by Martin on 2017/4/24. */ public class UserCacheManager { private static Context context; private static SPUtils spUtils; public UserCacheManager(Context context){ this.context=context; spUtils=SPUtils.getInstance(UserConstants.USER_INFO); } /** * 消息扩展属性 */ private static final String kChatUserId = "ChatUserId";// 环信ID private static final String kChatUserNick = "ChatUserNick";// 昵称 private static final String kChatUserPic = "ChatUserPic";// 头像Url /** * 获取所有用户信息 * @return */ public static List<UserCacheInfo> getAll(){ Dao<UserCacheInfo, Integer> dao = SqliteHelper.getInstance().getUserDao(); try { List<UserCacheInfo> list = dao.queryForAll(); return list; } catch (Exception e) { e.printStackTrace(); } return null; } /** * 获取用户信息 * @param userId 用户环信ID * @return */ public static UserCacheInfo get(final String userId){ UserCacheInfo info = null; // 如果本地缓存不存在或者过期,则从存储服务器获取 if (notExistedOrExpired(userId)){ MyHttpUtils.get(context, MyApiHelper.URL_USER_INFO + userId, new MyHttpUtils.HttpCallback() { @Override public void success(String success) { if (TextUtils.isEmpty(success)) return; UserInfoBean infoModel = JSON.parseObject(success, UserInfoBean.class); if (infoModel.getResult()==0){ UserInfoBean.DataBean dataBean=infoModel.getData(); if (ObjectUtils.isNotEmpty(dataBean)){ //生成头像的绝对路径,保存在本地 save(userId,dataBean.getNickName(),dataBean.getAppImage()); } } } @Override public void fail(String fail) { } }); } // 从本地缓存中获取用户数据 info = getFromCache(userId); return info; } /** * 获取用户信息 * @param userId 用户环信ID * @return */ public static UserCacheInfo getFromCache(String userId){ try { Dao<UserCacheInfo, Integer> dao = SqliteHelper.getInstance().getUserDao(); UserCacheInfo model = dao.queryBuilder().where().eq("userId", userId).queryForFirst(); return model; } catch (Exception e) { e.printStackTrace(); } return null; } /** * 获取用户信息 * @param userId * @return */ public static EaseUser getEaseUser(String userId){ UserCacheInfo user = get(userId); if (user == null) return null; EaseUser easeUser = new EaseUser(userId); easeUser.setAvatar(user.getAvatarUrl()); easeUser.setNickname(user.getNickName()); return easeUser; } /** * 用户是否存在 * @param userId 用户环信ID * @return */ public static boolean isExisted(String userId){ Dao<UserCacheInfo, Integer> dao = SqliteHelper.getInstance().getUserDao(); try { long count = dao.queryBuilder().where().eq("userId", userId).countOf(); return count > 0; } catch (Exception e) { e.printStackTrace(); } return false; } /** * 用户不存在或已过期 * @param userId 用户环信ID * @return */ public static boolean notExistedOrExpired(String userId){ Dao<UserCacheInfo, Integer> dao = SqliteHelper.getInstance().getUserDao(); try { long count = dao.queryBuilder().where() .eq("userId", userId).and() .gt("expiredDate",new Date().getTime()) .countOf(); return count <= 0; } catch (Exception e) { e.printStackTrace(); } return true; } /** * 缓存用户信息 * @param userId 用户环信ID * @param avatarUrl 头像Url * @param nickName 昵称 * @return */ public static boolean save(String userId, String nickName, String avatarUrl){ try { Dao<UserCacheInfo, Integer> dao = SqliteHelper.getInstance().getUserDao(); UserCacheInfo user = getFromCache(userId); // 新增 if (user == null){ user = new UserCacheInfo(); } user.setUserId(userId); user.setAvatarUrl(avatarUrl); user.setNickName(nickName); user.setExpiredDate(new Date().getTime() + 24*60*60*1000);// 一天过期,单位:毫秒 Dao.CreateOrUpdateStatus status = dao.createOrUpdate(user); if(status.getNumLinesChanged() > 0){ Log.i("UserCacheManager", "操作成功~"); return true; } } catch (Exception e) { e.printStackTrace(); Log.e("UserCacheManager", "操作异常~"); } return false; } /** * 更新当前用户的昵称 * @param nickName 昵称 */ public static void updateMyNick(String nickName){ UserCacheInfo user = getMyInfo(); if (user == null) return; save(user.getUserId(), nickName, user.getAvatarUrl()); } /** * 更新当前用户的头像 * @param avatarUrl 头像Url(完成路径) */ public static void updateMyAvatar(String avatarUrl){ UserCacheInfo user = getMyInfo(); if (user == null) return; save(user.getUserId(), user.getNickName(), avatarUrl); } /** * 缓存用户信息 * @param model 用户信息 * @return */ public static boolean save(UserCacheInfo model){ if(model == null) return false; return save(model.getUserId(),model.getNickName(),model.getAvatarUrl()); } /** * 缓存用户信息 * @param ext 用户信息 * @return */ public static boolean save(String ext){ if(ext == null) return false; UserCacheInfo user = UserCacheInfo.parse(ext); return save(user); } /** * 缓存用户信息 * @param ext 消息的扩展属性 * @return */ public static void save(Map<String,Object> ext){ if(ext == null) return; try { String userId = ext.get(kChatUserId).toString(); String avatarUrl = ext.get(kChatUserPic).toString(); String nickName = ext.get(kChatUserNick).toString(); save(userId,nickName,avatarUrl); } catch (Exception e) { e.printStackTrace(); } } /** * 获取当前环信用户信息 * @return */ public static UserCacheInfo getMyInfo(){ return get(EMClient.getInstance().getCurrentUser()); } /** * 获取用户昵称 * @return */ public static String getMyNickName(){ UserCacheInfo user = getMyInfo(); if(user == null) return EMClient.getInstance().getCurrentUser(); return user.getNickName(); } /** * 设置消息的扩展属性 * @param msg 发送的消息 */ public static void setMsgExt(EMMessage msg){ if(msg == null) return; UserCacheInfo user = getMyInfo(); msg.setAttribute(kChatUserId, user.getUserId()); msg.setAttribute(kChatUserNick, user.getNickName()); msg.setAttribute(kChatUserPic, user.getAvatarUrl()); } /** * 获取登录用户的昵称头像 * @return */ public static String getMyInfoStr(){ Map<String,Object> map = new HashMap<>(); UserCacheInfo user = getMyInfo(); map.put(kChatUserId, user.getUserId()); map.put(kChatUserNick, user.getNickName()); map.put(kChatUserPic, user.getAvatarUrl()); return new Gson().toJson(map); } }
二、从消息扩展中获取头像昵称:
1.首先,要注释从APP服务器获取昵称头像的方法。
删除类文件:UserWebInfo.java和UserWebManager.java。
UserCacheManager.java中注释第57-68行,不从APP服务器中获取昵称头像:
// 如果本地缓存不存在或者过期,则从存储服务器获取 if (notExistedOrExpired(userId)){ UserWebManager.getUserInfoAync(userId, new UserWebManager.UserCallback() {//从自己服务器获取用户信息 @Override public void onCompleted(UserWebInfo info) { if(info == null) return; // 缓存到本地 save(userId, info.getNickName(),info.getAvatarUrl()); } }); }2.登录(或注册)成功后,需要缓存当前用户的昵称头像。
在登录(或注册)服务端回调(不是环信IM登录回调)里,增加如下代码:
// 登录成功,将用户的环信ID、昵称和头像缓存在本地 UserCacheManager.save(userId, nickName, avatarUrl);3.发送消息时携带昵称头像。
ChatFragment.java里的 onSetMessageAttributes函数。第231行增加代码:
// 设置消息的扩展属性,携带昵称头像 UserCacheManager.setMsgExt(message);
4.接收消息时携带昵称头像。
DemoHelper.java里的 onMessageReceived函数。第856行增加代码:
// 从消息的扩展属性里获取昵称头像 UserCacheManager.save(message.ext());
5.另外。音视频通话里,昵称头像也要进行处理。 (不需要音视频通话功能的开发者可以省略后面所有步骤)
发送音视频通话请求时携带昵称头像。
CallActivity.java里第162行代码更改为:
// 通过扩展属性将昵称头像传给对方 String ext = UserCacheManager.getMyInfoStr(); if (msg.what == MSG_CALL_MAKE_VIDEO) { EMClient.getInstance().callManager().makeVideoCall(username,ext); } else { EMClient.getInstance().callManager().makeVoiceCall(username,ext); }
6.接收音视频通话时保存昵称头像。
CallReceiver.java第33行增加代码:
// 缓存用户昵称头像 String ext = EMClient.getInstance().callManager().getCurrentCallSession().getExt(); UserCacheManager.save(ext);
7.音频通话里显示昵称头像。
VoiceCallActivity.java第114行代码改为:
// 显示昵称头像 UserCacheInfo user = UserCacheManager.get(username); if (user != null){ nickTextView.setText(user.getNickName()); //Glide.with(VoiceCallActivity.this).load(user.getAvatarUrl()).placeholder(R.drawable.em_default_avatar).into(avatarImage); }else { nickTextView.setText(username); }
8.视频通话里显示昵称头像。
VideoCallActivity.java第171行代码改为:
// 显示昵称头像 UserCacheInfo user = UserCacheManager.get(username); if (user != null){ nickTextView.setText(user.getNickName()); }else { nickTextView.setText(username); }
通过以上步骤相信大家应该就能实现使用扩展消息显示昵称头像了。