集成SDK
集成SDK没什么特别困难的,看看官方文档就可以集成,在这里主要提醒以下两个内容:
① 如界面与demo界面变动较大,需要自己写界面的情况下,就不要导入EaseUI 库,只导入需要的so文件和jar包即可
② 如需集成EaseUI 库,就不要再导入jar包和so文件了,EaseUI 库中已包含了那些内容
在这里插播一句:android gradle tools 3.X 中依赖,implementation 和compile区别
本文介绍的主要是集成EaseUI 库的
初始化及头像,昵称的设置
初始化要求在 application
的oncreate
方法中做初始化。因为还需要设置头像,昵称,以及其它一些监听,建议可以像demo一样,写一个HxEaseuiHelper
,在这个类里做这些操作。
建议copy demo里的以下类,以及DemoModel
,然后该删的删,该改的改
HxEaseuiHelper
代码如下,也是参照demo改的(我是同时集成了环信的即时通讯及客服云的,你们可以按照需要来初始化相对应的SDK)
public class HxEaseuiHelper {
private static HxEaseuiHelper instance = null;
protected EMMessageListener messageListener = null;
private Context appContext;
private String username;
private EaseUI easeUI;
private Map<String, EaseUser> contactList;
private Map<String, RobotUser> robotList;
private DemoModel demoModel = null;
private EaseUser currentUser;
private String TAG = "HxEaseuiHelper";
public synchronized static HxEaseuiHelper getInstance() {
if (instance == null) {
instance = new HxEaseuiHelper();
}
return instance;
}
public void init(Context context) {
demoModel = new DemoModel(context);
ChatClient.Options options = new ChatClient.Options();
options.setAppkey("**********");
options.setTenantId("*****");
//环信客服 SDK 初始化, 初始化成功后再调用环信下面的内容
if (!ChatClient.getInstance().init(context, options)) {
return;
}
appContext = context;
// 环信客服 SDK 初始化, 初始化成功后再调用环信下面的内容
// Kefu EaseUI的初始化
UIProvider.getInstance().init(context);
//获取easeui实例
easeUI = EaseUI.getInstance();
//初始化easeui
easeUI.init(appContext, null);
setEaseUIProviders(context);
//设置全局监听
setGlobalListeners();
}
protected void setEaseUIProviders(final Context appContext) {
// set profile provider if you want easeUI to handle avatar and nickname
easeUI.setUserProfileProvider(new EaseUI.EaseUserProfileProvider() {
@Override
public EaseUser getUser(String username) {
return getUserInfo(username);
}
});
}
private EaseUser getUserInfo(String username) {
//获取 EaseUser实例, 这里从内存中读取
//如果你是从服务器中读读取到的,最好在本地进行缓存
EaseUser user = null;
//如果用户是本人,就设置自己的头像
if (username.equals(EMClient.getInstance().getCurrentUser())) {
String avatar = (!StringUtils.isEmpty(PrefUtils.getString(appContext, "avatar", ""))) ? PrefUtils.getString(appContext, "avatar", "") : "";
if (currentUser != null) {
if (!currentUser.getAvatar().equals(avatar))
currentUser.setAvatar(avatar);
} else {
currentUser = new EaseUser(EMClient.getInstance().getCurrentUser());
currentUser.setAvatar(avatar);
}
return currentUser;
}
//收到别人的消息,设置别人的头像
if (contactList != null && contactList.containsKey(username)) {
user = contactList.get(username);
} else { //如果内存中没有,则将本地数据库中的取出到内存中
contactList = getContactList();
user = contactList.get(username);
}
//如果用户不是你的联系人,则进行初始化
if (user == null) {
user = new EaseUser(username);
EaseCommonUtils.setUserInitialLetter(user);
} else {
if (TextUtils.isEmpty(user.getNick())) {//如果名字为空,则显示环信号码
user.setNick(user.getUsername());
}
}
return user;
}
public Map<String, RobotUser> getRobotList() {
if (isLoggedIn() && robotList == null) {
robotList = demoModel.getRobotList();
}
return robotList;
}
/**
* get current user's id
*/
public String getCurrentUsernName() {
if (username == null) {
username = (String) PrefUtils.getString(appContext, "nickname", "");
}
return username;
}
/**
* 获取所有的联系人信息
*
* @return
*/
public Map<String, EaseUser> getContactList() {
if (isLoggedIn()) {
contactList = demoModel.getContactList();
}
// return a empty non-null object to avoid app crash
if (contactList == null) {
return new Hashtable<String, EaseUser>();
}
return contactList;
}
/**
* if ever logged in
*
* @return
*/
public boolean isLoggedIn() {
return EMClient.getInstance().isLoggedInBefore();
}
/**
* set global listener
*/
protected void setGlobalListeners() {
registerMessageListener();
}
/**
* Global listener
* If this event already handled by an activity, you don't need handle it again
* activityList.size() <= 0 means all activities already in background or not in Activity Stack
*/
protected void registerMessageListener() {
messageListener = new EMMessageListener() {
@Override
public void onMessageReceived(List<EMMessage> messages) {
EventBus.getDefault().post(new MainActivity.UpdateStockEvent());
for (EMMessage message : messages) {
EMLog.d(TAG, "onMessageReceived id : " + message.getMsgId());
//接收并处理扩展消息
String userName = message.getStringAttribute(Constant.USER_NAME, "");
String userId = message.getStringAttribute(Constant.USER_ID, "");
String userPic = message.getStringAttribute(Constant.HEAD_IMAGE_URL, "");
String userNickName = message.getStringAttribute(Constant.USER_NICK_NAME, "");
String hxIdFrom = message.getFrom();
System.out.println("helper接收到的用户名:" + userName + "helper接收到的id:" + userId + "helper头像:" + userPic);
EaseUser easeUser = new EaseUser(hxIdFrom);
easeUser.setAvatar(userPic);
easeUser.setNick(StringUtils.isEmpty(userNickName) ? hxIdFrom : userNickName);
//存入内存
getContactList();
contactList.put(hxIdFrom, easeUser);
//存入db
UserDao dao = new UserDao(appContext);
List<EaseUser> users = new ArrayList<EaseUser>();
users.addAll(contactList.values());
dao.saveContactList(users);
// in background, do not refresh UI, notify it in notification bar
//设置本地消息推送通知
if (!easeUI.hasForegroundActivies()) {
getNotifier().onNewMsg(message);
}
}
}
@Override
public void onCmdMessageReceived(List<EMMessage> messages) {
for (EMMessage message : messages) {
EMLog.d(TAG, "receive command message");
}
}
@Override
public void onMessageRead(List<EMMessage> messages) {
}
@Override
public void onMessageDelivered(List<EMMessage> message) {
}
@Override
public void onMessageRecalled(List<EMMessage> messages) { //撤销
//TODO 属于增值功能
}
@Override
public void onMessageChanged(EMMessage message, Object change) {
}
};
EMClient.getInstance().chatManager().addMessageListener(messageListener);
}
public EaseNotifier getNotifier() {
return easeUI.getNotifier();
}
}
在这个里面也是将如何设置头像和昵称写出来了,在registerMessageListener
,的onMessageReceived
方法里
这是接收,但是接收的内容是在哪里发送的呢,在重写的chatFragment
的onSetMessageAttributes
里,可以参照demo
/**
* 设置消息扩展属性
*/
@Override
public void onSetMessageAttributes(EMMessage message) {
// 通过扩展属性,将userPic和userName发送出去。
String userPic = PrefUtils.getString(getContext(), "avatar", "");
String nickName = PrefUtils.getString(getContext(), "nickname", "");
if (!TextUtils.isEmpty(userPic)) {
message.setAttribute(Constant.HEAD_IMAGE_URL, userPic);
}
if (!TextUtils.isEmpty(nickName)) {
message.setAttribute(Constant.USER_NICK_NAME, nickName);
}
}
从上面应该可以看出以下几点:
① 头像,昵称都是保存在本地数据库的
② 发送消息时的拓展内容为发送方的头像,昵称,那么也就意味着除非对方给你回信息,不然你不会知道对方的头像及昵称,也无法更新对方的头像及昵称
以下提供一个思路:
后台提供一个接口,可以查询用户信息,用于更新用户的头像及昵称,代码如下:
public void updateInfo(String nickName, String avatar) {
Map<String, EaseUser> contactList = HxEaseuiHelper.getInstance().getContactList();
toChatUsernickName = nickName;
toChatUseravatar = avatar;
if (contactList.containsKey(toChatUsername)) { //更新用户信息
EaseUser easeUser = contactList.get(toChatUsername);
if (!StringUtils.isEmpty(avatar) && !easeUser.getAvatar().equals(avatar))
easeUser.setAvatar(avatar);
if (!StringUtils.isEmpty(nickName) && !easeUser.getNickname().equals(nickName)) {
easeUser.setNickname(nickName);
titleBar.setTitle(nickName);
}
//存入内存
contactList.put(toChatUsername, easeUser);
//存入db
UserDao dao = new UserDao(getContext());
List<EaseUser> users = new ArrayList<EaseUser>();
users.addAll(contactList.values());
dao.saveContactList(users);
} else {
if (!StringUtils.isEmpty(nickName))
titleBar.setTitle(nickName);
}
}
那么如何设置呢,可以在发送消息的时候判断列表有没有用户,如果没有的话,就更新数据库,更新方式可参照上述。
使用过程中的坑
参考:[快速搞定] 教你如何快速集成环信(android端EaseUI),跳过我踩过的坑
以下为补充内容:
① 在拍照,发送图片,录像等时 设置运行时权限,部分还需要使用 FileProvider
② 查看大图时,双击放大,缩小,单击 finish
, 但单击时不生效
// EaseShowBigImageActivity
// image.setOnClickListener(new OnClickListener() { //事件被拦截
// @Override
// public void onClick(View v) {
// finish();
// }
// });
image.setOnPhotoTapListener(new PhotoViewAttacher.OnPhotoTapListener() { //单击
@Override
public void onPhotoTap(View view, float x, float y) {
finish();
}
});
③ 底部切换输入法时,有部分界面上的bug
else if (id == R.id.btn_more) {
//解决方法,添加这句话
setModeKeyboard();
showNormalFaceImage();
if (listener != null)
listener.onToggleExtendClicked();
}
④ 修改默认图片:EaseUserUtils
参考文章:
环信官方文档:Android SDK 介绍及导入
重点参考官方文档的以下两个内容:Android SDK API Doc,EaseUI 使用指南