网易云集成IM

背景

项目中需要实现IM通信功能,其实原来已经继承了云信的视频SDK,而IM模块其实已经在SDK中了,但是由于我们的IM聊天界面是需要自己定制了,因此就加了添加了一个lib-ui的库,方便去自定义IM界面

集成

集成其实很简单,网易提供了两种方式,jar和gradle,毫无疑问gradle

1
2
3
4
5
6
7
8
// 基础功能 (必需)
netease_basesdk : 'com.netease.nimlib:basesdk:5.1.1',
// 音视频需要
netease_avchat : 'com.netease.nimlib:avchat:5.1.1',
// 音视频需要
netease_nrtc : 'com.netease.nimlib:nrtc:5.1.1',
// 全文检索服务需要
netease_lucene : 'com.netease.nimlib:lucene:5.1.1',

其中第一个是早就集成了的,自带IM功能,第二第三则是音视频需要的,第四个是需要做聊天记录搜索要用到的

  1. APPID申请
  2. 权限
  3. 初始化
  • 前两个看官方文档就可以了,初始化一般就是在主APP的Aplication中进行,代码如下
1
2
3
4
5
6
7
8
9
10
11
// 注册通知消息过滤器
registerIMMessageFilter();

// 初始化消息提醒
NIMClient.toggleNotification(true);

// 注册网络通话来电
enableAVChat();

//初始化IM UI组件
NimUIKit.init(this);

官方文档和demo中也有说明,需要使用到哪种能力就去初始化哪些,比如该版本还用到了IM的自定义消息,那么也必须在这里进行注册

注意:以上的初始化只能在主线程中进行,为此,云信提供了一个API:NIMUtil.isMainProcess(this)

1
2
3
NIMClient.getService(MsgService.class).registerCustomAttachmentParser(new CustomAttachParse());

NimUIKit.registerMsgItemViewHolder(DiagnosisMsg.class, MsgViewHolderDiagnosis.class);
  1. IM消息监听
1
2
3
4
5
6
// 注册IM消息监听
NIMClient.getService(MsgServiceObserve.class)
.observeReceiveMessage(messageObserver, true);
// 反注册
NIMClient.getService(MsgServiceObserve.class)
.observeReceiveMessage(messageObserver, false);

相关概念

  • 注册登陆:集成网易云后,需要将本地用户与网易云id关联,每一个用户在网易云有一个唯一的accid和token,对于登陆相当于用户名及密码,对于业务比如:视频/IM则相当与电话号码,你需要和别人通信的时候必须知道对方的accid。
  • 用户信息托管:由于本地用户在网易云有一个id关联,那么当要用到网易云的一些能力的时候,我们希望用户的一些基础信息(头像,昵称)是要与本地后端保持一致的。
  • 消息锚点:其实就是一个消息对象,它携带了一些时间或者其他信息,方便搜索。

上面两点都是本地后端处理的,前段需要处理的则是,在登陆系统成功后,需要手动调用网易登陆api去帮助用户登陆到网易云,并且监听用户的登陆状态。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public void nimLogin(User user) {
LoginInfo info = new LoginInfo(user.accid, user.token); // config...
RequestCallback<LoginInfo> callback =
new RequestCallback<LoginInfo>() {
@Override
public void onSuccess(LoginInfo param) {
Logger.d("login nim success");
}

@Override
public void onFailed(int code) {
Logger.d("login nim failed :" + code);
}

@Override
public void onException(Throwable exception) {
Logger.e(exception, "login nim failed");
}
};
AbortableFuture<LoginInfo> request = NIMClient.getService(AuthService.class).login(info);
request.setCallback(callback);
}

@Override
public void observeNimOnlineStatus(User user) {
NIMClient.getService(AuthServiceObserver.class).observeOnlineStatus(
(Observer<StatusCode>) status -> {
Log.i("nim", "User status changed to: " + status);
if (status.shouldReLogin()) {
new Handler().postDelayed(() -> nimLogin(user), 5000);
}
}, true);
}

IM相关

界面

由于lib_neteaseui库提供了界面能力,所以自然自定义界面的话需要集成他的界面,这里有两种方式

  1. 集成现有类(比如p2pmessage),只需要修改layout,并且传递需要的参数即可。
  2. 继承SDK中的UI并实现ModuleProxy代理类中方法

开启单聊

很简单直接看代码

1
IMMessageActivity.start(getContext(), entity.accid, customization, null, IMMessageActivity.class);

其中,entity.accid代表了对方的号码。

消息面板设置

  1. 面板类:MessageListPanelEx,这里面封装了发送消息面板的所有功能
  2. 抽屉:基类BaseAction,比如拍照,相片或者自定义类型都是通过这个基类来实现的。
  3. IM面板layout:nim_message_activity_text_layout
  4. 设置用户托管信息:
1
2
// 设置网易云用户资料(IM中的头像,昵称等)
NimUserManager.setUserBasicInfo(user.patientName,user.imgUrl);

消息设置

  1. 消息屏蔽:
1
2
3
4
//屏蔽所有消息
NIMClient.toggleNotification(false);
//屏蔽某个用户消息
NIMClinet.getService(FriendService.class).setMessageNotify(account,checkState)
  1. 消息接收
1
2
3
4
5
6
7
8
9
10
/**
* IM消息监听
*/
com.netease.nimlib.sdk.Observer<List<IMMessage>> messageObserver = new com.netease.nimlib.sdk.Observer<List<IMMessage>>() {
@Override
public void onEvent(List<IMMessage> imMessages) {
Logger.d("im message received");

}
};
  1. 自定义消息

自定义消息比较复杂,参见代码。具体步骤如下:

  • 定义消息
1
2
3
4
5
6
7
/**
* 需要多端统一
*/
public interface CustomAttachmentType {

int diagnosisMsg = 1001;
}
  • 自定义消息的基础类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public abstract class CustomAttachment implements MsgAttachment {
protected int type;
CustomAttachment(int type) {
this.type = type;
}
public void fromJson(JsonObject data) {
if (data != null) {
parseData(data);
}
}
@Override
public String toJson(boolean send) {
return CustomAttachParse.packData(type, packData());
}
public int getType() {
return type;
}
protected abstract void parseData(JsonObject data);
protected abstract JsonObject packData();
}
  • 自定义消息结构类(用于组装自定义数据)
1
public class DiagnosisMsg extends CustomAttachment
  • 自定义消息解析类(用于显示自定义消息)
1
public class CustomAttachParse implements MsgAttachmentParser

参见官方文档

其他

  1. 注册账号accid网易云强制小写
  2. 网易云消息从后端还是本地拉取
1
messageListPanel = new MessageListPanelEx(container, rootView, anchor, false, remote);

其中最后一个参数remote = true表示从云端拉取数据

  1. IM聊天点击头像事件
    layout:MsgAdapter中layout.nim_message_item

点击事件:NimUIKitImpl.setSessionListener