前提条件
客户端集成前,请确保已完成服务端集成,并提供客户端访问的获取鉴权Token的接口。详细操作,请参见服务端集成。
集成SDK
添加Maven仓库。
repositories {
maven { url 'https://maven.aliyun.com/nexus/content/repositories/releases' }
}
添加SDK依赖。
// 互动库
implementation "com.aliyun.sdk.android:AliVCInteractionMessage:1.4.2"
配置AndroidManifest.xml
权限。
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
在应用工程的proguard-rules.pro
文件中添加如下代码,以防止SDK代码被混淆。
说明 v1.4.0、v1.4.1 版本必须添加如下混淆配置。其他版本非必须,可通过aar包自动引入混淆配置。
###################### 混淆配置 #########################
-keep class com.aliyun.im.common.** { *; }
-keepclassmembers class com.aliyun.im.common.** { *; }
-keep class com.aliyun.im.interaction.** { *; }
-keepclassmembers class com.aliyun.im.interaction.** { *; }
-keep interface com.aliyun.im.AliVCIMInterface { *; }
-keep interface com.aliyun.im.AliVCIMGroupInterface { *; }
-keep interface com.aliyun.im.AliVCIMMessageInterface { *; }
使用SDK
SDK使用需遵循如下操作顺序:
初始化
登录
相关操作
登出
反初始化
其中相关操作包含群组操作和消息操作,详细说明如下:
相关操作
群组操作
消息操作
单发消息
群发消息
查询最近群发消息列表
查询全部群发消息(仅限群主/群管理员操作)
删除/撤回群消息
查询历史消息
注意事项
各ID需遵循以下规则:
appid :最长64位,仅限于A~Z,a~z, 0~9及“-”, 不能包含其他字符
userid:最长64位,仅限于A~Z,a~z, 0~9及“-”, 不能包含其他字符
groupid:最长64位,仅限于A~Z,a~z, 0~9及“-”, 不能包含其他字符
初始化
在App入口(如Application/Activity的onCreate中)进行初始化配置。
ImSdkConfig config = new ImSdkConfig();
config.deviceId = "deviceId"; //[选填]
config.appId = "appId"; //[必填],传空会返回初始化失败-2
config.appSign = "appSign"; //[必填],传空会返回初始化失败-2
config.logLevel = ImLogLevel.DEBUG; //[选填],指定Log日志可输出的最小等级,默认是ImLogLevel.DEBUG;若需要关闭Log日志,则设置为ImLogLevel.NONE;
// 初始化返回非0,表示初始化失败,其中1001:重复初始化、1002:创建底层引擎失败、-1:底层重复初始化、-2:初始化配置信息有误
int ret = AliVCIMEngine.instance().init(context, config);
监听长连接状态
AliVCIMEngine.instance().addSdkListener(new ImSdkListener() {
@Override
public void onConnecting() {
}
@Override
public void onConnectSuccess() {
}
@Override
public void onConnectFailed(com.aliyun.im.common.Error error) {
}
@Override
public void onDisconnect(int code) {
}
// 登录token失效(如token过期)会通过该接口获取新的token,务必实现该接口
@Override
public void onTokenExpired(ImTokenCallback callback) {
// 第一步,实现新token的生成,若需要网络请求等耗时操作,请务必抛到异步线程实现;
// 第二步,若token生成失败,则通过 callback.onError() 回调错误信息;
// 若token生成成功,则通过 callback.onSuccess() 回调token信息;
}
@Override
public void onReconnectSuccess(ArrayList<ImGroupInfo> groupStatus) {
}
/**
* v1.4.1版本开始,新增连接状态的回调:一共有4个状态
* ImLinkState.IDLE:初始化状态;登录前,处于该状态;
* ImLinkState.CONNECTING:连接中;登录中或断连重连中,处于该状态;
* ImLinkState.CONNECTED:已连接;登录成功或断连重连成功,处于该状态;
* ImLinkState.DISCONNECTED:已断连;因断网等异常情况导致断连,处于该状态;
*
* 可以结合各种连接状态的变化,增加相关交互提示;例如 CONNECTED -> DISCONNECTED,提示用户检查网络状态等
*/
@Override
public void onLinkStateEvent(ImLinkStateEvent event) {
// 获取连接变化前的状态
ImLinkState previousState = event.getPreviousState();
// 获取连接变化后的状态
ImLinkState currentStateState = event.getCurrentState();
}
});
登录
ImLoginReq req = new ImLoginReq();
req.user.userId = userId;
//透传业务额外信息
Map<String, Object> data = new HashMap<>();
data.put("level", "high");
req.user.userExtension = App.getGson().toJson(data).toString();
req.userAuth = new ImAuth(nonce, timestamp, role, app_token);
AliVCIMEngine.instance().login(req, new ImSdkCallback());
其中role参数,有两种角色:
登出
AliVCIMEngine.instance().logout();
反初始化
登出后进行反初始化。
AliVCIMEngine.instance().unInit();
消息服务
//消息服务
AliVCIMMessageInterface messageInterface = AliVCIMEngine.instance().getMessageManager();
非管理员操作
监听消息
//监听消息
messageInterface.addMessageListener(new ImMessageListener() {
@Override
public void onRecvC2cMessage(ImMessage msg) {
}
@Override
public void onRecvGroupMessage(ImMessage msg, String groupId) {
}
@Override
public void onDeleteGroupMessage(String msgId, String groupId) {
}
});
发送C2C消息
ImSendMessageToUserReq req = new ImSendMessageToUserReq();
req.type = 88888;
req.data = "This is a test message";
req.receiverId = userInput.getText().toString();
// 需确保对方在线,否则会返回错误码424,此时建议待对方上线后再重发
messageInterface.sendC2cMessage(req, new ImSdkValueCallback<ImSendMessageToUserRsp>() {
@Override
public void onSuccess(ImSendMessageToUserRsp data) {
Log.v(ImTag.TAG, "发送C2C消息成功:" + data.messageId);
}
@Override
public void onFailure(Error error) {
Log.v(ImTag.TAG, "发送C2C消息失败:error" + error.code);
}
});
在群组内发送全员消息
ImSendMessageToGroupReq req = new ImSendMessageToGroupReq();
/**
* 设置消息等级,默认是普通消息ImMessageLevel.NORMAL,可接受消息丢失,如弹幕等;
* 若是高优消息,可设置为ImMessageLevel.HIGH,提高消息可靠性;
*/
req.level = ImMessageLevel.NORMAL;
req.type = 88888;
req.data = "a test";
req.groupId = groupId;
// 需确保已经加入群成功(即在AliVCIMGroupInterface.joinGroup回调成功之后),再发送群组消息,否则会返回错误码425
messageInterface.sendGroupMessage(req, new ImSdkValueCallback<ImSendMessageToGroupRsp>() {
@Override
public void onSuccess(ImSendMessageToGroupRsp data) {
Log.v(ImTag.TAG, "发送群消息成功:" + data.messageId);
}
@Override
public void onFailure(Error error) {
Log.v(ImTag.TAG, "发送群消息失败" + error.code);
}
});
查询最近消息列表
ImListRecentMessageReq req;
req.groupId = groupId;
messageInterface.listRecentMessage(req, new ImSdkValueCallback<ImListRecentMessageRsp>() {
@Override
public void onSuccess(ImListRecentMessageRsp data) {
}
@Override
public void onFailure(com.aliyun.im.common.Error error) {
}
});
查询历史消息
//该接口主要用户直播结束后的历史消息回放,用户无需进入群组可查询,比较耗时,在直播过程中不建议使用,另外该接口后续会收费。
ImListHistoryMessageReq req = new ImListHistoryMessageReq();
req.groupId = "群ID";
req.nextPageToken = 231231; //不传时表示第一页,遍历时服务端会返回下一页Token,客户端获取下一页时应带上
req.type = 99999; // 自定义消息类型,需大于10000
req.sortType = ImSortType.ASC;
req.pageSize = 20;
req.beginTime = 0; // 按时间范围遍历,开始时间,单秒,为0时表示最早时间
req.endTime = 0; // 按时间范围遍历,结束时间,单秒,为0时表示最晚时间
messageInterface.listHistoryMessage(req, new ImSdkValueCallback<ImListHistoryMessageRsp>() {
@Override
public void onSuccess(ImListHistoryMessageRsp rsp) {
}
@Override
public void onFailure(Error error) {
}
});
删除消息
ImDeleteMessageReq req = new ImDeleteMessageReq();
req.groupId = "群ID";
req.messageId = "消息ID";
messageInterface.deleteMessage(req, new ImSdkCallback() {
@Override
public void onSuccess() {
}
@Override
public void onFailure(Error error) {
}
});
管理员操作
查询消息列表
//该接口(仅限群主/群管理员操作)
ImListMessageReq req = new ImListMessageReq();
req.groupId = "群ID";
req.nextPageToken = 231231; //不传时表示第一页,遍历时服务端会返回下一页Token,客户端获取下一页时应带上
req.type = 99999; // 自定义消息类型,需大于10000
req.sortType = ImSortType.ASC;
req.pageSize = 20;
req.beginTime = 0; // 按时间范围遍历,开始时间,单秒,为0时表示最早时间
req.endTime = 0; // 按时间范围遍历,结束时间,单秒,为0时表示最晚时间
messageInterface.listMessage(req, new ImSdkValueCallback<ImListMessageRsp>() {
@Override
public void onSuccess(ImListMessageRsp rsp) {
}
@Override
public void onFailure(Error error) {
}
});
群组服务
//群组服务
AliVCIMGroupInterface groupInterface = AliVCIMEngine.instance().getGroupManager();
非管理员操作
监听群组状态
groupManager.addGroupListener(new ImGroupListener() {
/**
* 群组成员变化通知
* @param groupMemberChangeInfo 群成员变化信息
* @apiNote v1.4.1新增;若重写该接口,则不再回调旧接口,请务必迁移旧的逻辑;
*/
@Override
public void onMemberChange(ImGroupMemberChangeInfo groupMemberChangeInfo) {
// 可以监听这个回调,在群人员变化后,更新当前房间的人数、累积访问量(观看数)
// 若当前是大群(群人数超过一定量级),即groupMemberChangeInfo.isBigGroup()返回true,群成员变化的通知会控制频率,通知可能不及时;若需要实时通知,可通过OpenAPI对接该回调接口;
}
/**
* 退出群组通知
* @param groupId 群组ID
* @param reason 退出原因 , 1: 群被解散, 2:被踢出来了
*/
@Override
public void onExit(String groupId, int reason) {
}
/**
* 群组禁言状态通知
* @param groupId 群组ID
* @param status 群组禁言状态
*/
@Override
public void onMuteChange(String groupId, ImGroupMuteStatus status) {
}
/**
* 群组信息变化通知
* @param groupId 群组ID
* @param info 群组信息
*/
@Override
public void onInfoChange(String groupId, ImGroupInfoStatus info) {
}
});
加入群组
ImJoinGroupReq req = new ImJoinGroupReq();
req.groupId = groupId;
groupInterface.joinGroup(req, new ImSdkValueCallback<ImJoinGroupRsp>() {
@Override
public void onSuccess(ImJoinGroupRsp data) {
}
@Override
public void onFailure(Error error) {
}
});
离开群组
ImLeaveGroupReq req = new ImLeaveGroupReq();
req.groupId = groupId;
groupInterface.leaveGroup(req, new ImSdkCallback() {
@Override
public void onSuccess() {
}
@Override
public void onFailure(Error error) {
}
});
查看最近群组成员
ImListRecentGroupUserReq req = new ImListRecentGroupUserReq();
req.groupId = groupId;
groupManager.listRecentGroupUser(req, new ImSdkValueCallback<ImListRecentGroupUserRsp>() {
@Override
public void onSuccess(ImListRecentGroupUserRsp data) {
}
@Override
public void onFailure(Error error) {
}
});
管理员操作
创建群组
ImCreateGroupReq req = new ImCreateGroupReq();
req.groupName = "羽毛球群";
Map<String, Object> data = new HashMap<>();
data.put("desc", "一三五晚8-10");
req.groupMeta = App.getGson().toJson(data).toString();
groupInterface.createGroup(req, new ImSdkValueCallback<ImCreateGroupRsp>() {
@Override
public void onSuccess(ImCreateGroupRsp data) {
Log.v(ImTag.TAG, "Create Group Success:" + data.groupId);
}
@Override
public void onFailure(com.aliyun.im.common.Error error) {
Log.v(ImTag.TAG, "Create Group Failure:" + error.getCode());
}
});
删除群组
ImCloseGroupReq req = new ImCloseGroupReq();
req.groupId = groupId;
groupInterface.closeGroup(req, new ImSdkCallback() {
@Override
public void onSuccess() {
}
@Override
public void onFailure(Error error) {
}
});
修改群组
ImModifyGroupReq req = new ImModifyGroupReq();
req.groupId = groupId;
req.admins.add(adminUserId);//指定群管理员ID列表,最多设置3个管理员;若需要清空列表,则配置空列表或者不设置,同时必须设置req.forceUpdateAdmins=true;
req.groupMeta = "群信息拓展字段";//添加群拓展信息;若需要清空,则配置空字符串或者不设置,同时必须设置req.forceUpdateGroupMeta=true;
groupInterface.modifyGroup(req, new ImSdkCallback() {
@Override
public void onSuccess() {
}
@Override
public void onFailure(Error error) {
}
});
查询群组成员
ImListGroupUserReq req = new ImListGroupUserReq();
req.groupId = groupId;
req.sortType = ImSortType.ASC;
req.pageSize = 30;
groupManager.listGroupUser(req, new ImSdkValueCallback<ImListGroupUserRsp>() {
@Override
public void onSuccess(ImListGroupUserRsp data) {
}
@Override
public void onFailure(Error error) {
}
});
全体禁言
ImMuteAllReq req = new ImMuteAllReq();
req.groupId = groupId;
groupInterface.muteAll(req, new ImSdkCallback() {
@Override
public void onSuccess() {
}
@Override
public void onFailure(Error error) {
}
});
取消禁言
ImCancelMuteAllReq req = new ImCancelMuteAllReq();
req.groupId = groupId;
groupInterface.cancelMuteAll(req, new ImSdkCallback() {
@Override
public void onSuccess() {
}
@Override
public void onFailure(Error error) {
}
});
禁言指定用户
ImMuteUserReq req = new ImMuteUserReq();
req.groupId = groupId;
req.userList.add(muteUserId);
groupInterface.muteUser(req, new ImSdkCallback() {
@Override
public void onSuccess() {
}
@Override
public void onFailure(Error error) {
}
});
取消禁言
ImCancelMuteUserReq req = new ImCancelMuteUserReq();
req.groupId = groupId;
req.userList.add(muteUserId);
groupInterface.cancelMuteUser(req, new ImSdkCallback() {
@Override
public void onSuccess() {
}
@Override
public void onFailure(Error error) {
}
});
查询禁言用户
ImListMuteUsersReq req = new ImListMuteUsersReq();
req.groupId = groupId;
groupManager.listMuteUsers(req, new ImSdkValueCallback<ImListMuteUsersRsp>() {
@Override
public void onSuccess(ImListMuteUsersRsp data) {
}
@Override
public void onFailure(Error error) {
}
});