消息服务准备
-
获取 频道ID channelID
-
获取包含消息模块权限的access_token
工程配置
- 在开始使用sdk之前,我们要配置好IDE和创建基础的工程代码。相关内容在【工程配置】中有详细说明。
时序图
注:已知频道ID的情况下虚线框部分无需请求。
对接流程:
请先查看工程配置,配置成功后在进行如下操作 :
复制 vhallims1.0.jar到工程lib目录下。
1、 使用Gradle自动添加Jar包依赖。
2、 通过类库配置集成 SDK
1 创建VHIM实例
/**
* 开始观看,传递开始配置的channelId(频道ID)和AccessToken;
* @param String channelId; // 频道ID
* @param String accessToken; // Token
*/
VHIM im = new VHIM(mChannelId, mAccessToken);
/**
* 设置IM的监听事件,具体事件参考本文的事件处理
*/
im.setOnMessageListener(new MsgListener());
2 进入聊天室
什么是聊天室:
1、 每一个Channel对应一个聊天室,用户可以根据Channel加入对应的聊天室。
2、 每一个聊天室允许加入聊天的成员无上限。
3、 允许不同的端(PC/移动)加入聊天室。
4、 聊天室只允许用户Join加入,不能邀请
5、 当退出聊天室后,IM服务将不会在给此用户推送消息。
第三方用户发起登录的流程,每次调用Join方法,加入聊天室,IM服务会自动发送一条上线消息,这条上线消息可以在OnMessage中接收。
/**
* 加入频道,连接服务,当服务连接成功,开始接受消息,消息在onMessage中回调
*/
public void join();
3 发送消息及回调
当用户加入聊天室后,可以发送消息,message为用户需要发送的内容,当调用此方法,发送的内容会通过IM服务让此聊天室中的所有用户看到。
/*
* 确保聊天室加入成功后,调用此方法发送消息
* @param message 用户需要发送的消息
* @param callback 会返回用户发送后的结果。需要重写IM中的Callback回调。
*/
VHIM.sendMsg(v.getText().toString(), new VHIM.Callback() {
@Override
public void onSuccess() {
//聊天发送成功
}
@Override
public void onFailure(int errorCode, String errorMsg) {
//聊天发送失败
}
});
4 离开聊天室
每次调用leave方法,离开聊天室,IM服务会自动发送一条下线消息,这条下线消息可以在OnMessage中接收。
/**
* 离开频道,连接服务,当服务连接成功,开始接受消息,消息在onMessage中回调
*/
public void leave();
5 错误码和常量
关于IM服务的常量定义在 Framework.jar包中的 VhallConnectService , 用户可以根据自己的实际场景去查看。
常量 | 描述 |
---|---|
VhallConnectService.TYPE_CUSTOM | 收到自定义消息 |
VhallConnectService.TYPE_CHAT | 接收普通的聊天消息 |
VhallConnectService.TYPE_JOIN | 接收上线消息 |
VhallConnectService.TYPE_LEAVE | 接收下线消息 |
事件处理
当VHIM创建完毕,需要添加监听消息,每当有消息推送会回调onMessage(),用户需要根据自己的场景解析数据
公共字段 | 描述 |
---|---|
third_party_user_id | 第三方用户ID |
nick_name | 用户名 |
avatar | 头像 |
date_time | 时间戳 |
user_online_num | 当前在线人数 |
data | 对应各个不同消息的数据 |
im.setOnMessageListener(new VHIM.OnMessageListener() {
@Override
public void onMessage(String msg) {
if (event.equals(VhallConnectService.TYPE_CUSTOM)) {//收到自定义消息
//Do Something....
} else if (event.equals(VhallConnectService.TYPE_CHAT)) { // 聊天消息
//Do Something....
} else if (event.equals(VhallConnectService.TYPE_JOIN)) { // 上线消息
//Do Something....
} else if (event.equals(VhallConnectService.TYPE_LEAVE)) {// 下线消息
//Do Something....
}
}
});
代码演示
public class IMActivity extends Activity {
private String mChannelId = "";
private String mAccessToken = "";
private LinearLayout ll_content;
private EditText et;
VHIM im;
private OkHttpClient mClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mChannelId = getIntent().getStringExtra("channelid");
mAccessToken = getIntent().getStringExtra("token");
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN | WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
setContentView(R.layout.im_layout);
ll_content = (LinearLayout) this.findViewById(R.id.ll_content);
et = (EditText) this.findViewById(R.id.et);
et.setOnEditorActionListener(new EditListener());
/*** 添加VHIM的实例,添加channelId 和 token*/
im = new VHIM(mChannelId, mAccessToken);
/*** 设置IM的监听*/
im.setOnMessageListener(new MsgListener());
/*** 加入聊天室,此时开始监听channelId 的消息*/
im.join();
if (!VhallSDK.getInstance().isEnable())
Toast.makeText(this, "请先初始化SDK", Toast.LENGTH_SHORT).show();
}
@Override
protected void onDestroy() {
/*** 退出聊天室,断开服务*/
im.leave();
super.onDestroy();
}
class EditListener implements TextView.OnEditorActionListener {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_SEND) {
/*** 发送聊天消息*/
im.sendMsg(v.getText().toString(), new VHIM.Callback() {
@Override
public void onSuccess() {
// 发送消息成功
}
@Override
public void onFailure(int errorCode, String errorMsg) {
// 发送消息失败
}
});
}
return true;
}
}
/**
* IM的监听事件
* 所有的事件统一从onMessage中获取
*/
class MsgListener implements VHIM.OnMessageListener {
@Override
public void onMessage(String msg) {
try {
JSONObject obj = new JSONObject(msg);
JSONObject text = new JSONObject(URLDecoder.decode(obj.optString("text")));
String event = text.optString("event");
String third_party_user_id = text.optString("third_party_user_id");
String nick_name = text.optString("nick_name");
String avatar = text.optString("avatar");
String time = text.optString("date_time");
String data = text.optString("data");
int onlineNum = text.getInt("user_online_num");
if (TextUtils.isEmpty(event)) return; //
if (event.equals(VhallConnectService.TYPE_CUSTOM)) {//收到自定义消息
JSONObject dataSource = new JSONObject(data);
addView(event, nick_name, data, time, avatar);
} else if (event.equals(VhallConnectService.TYPE_CHAT)) { // 聊天消息
addView(event, nick_name, data, time, avatar);
} else if (event.equals(VhallConnectService.TYPE_JOIN)) { // 进入消息
addView(event, nick_name, data, time, avatar);
} else if (event.equals(VhallConnectService.TYPE_LEAVE)) {// 离开消息
addView(event, nick_name, data, time, avatar);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
/**
* 添加View
* 根据不同的事件设置不同的View
* @param event 事件类型
* @param nick_name 昵称
* @param data 数据
*/
private void addView(String event, String nick_name, String data, String time, String avatar) {
View view = View.inflate(IMActivity.this, R.layout.im_item_layout, null);
ImageView v = (ImageView) view.findViewById(R.id.avatar);
if (ll_content.getChildCount() >= 10) {
View removeView = ll_content.getChildAt(0);
ll_content.removeView(removeView);
}
if (!TextUtils.isEmpty(avatar) && !avatar.equals("null")) {
requestAvatar(avatar, v);
}
TextView c = (TextView) view.findViewById(R.id.content);
TextView t = (TextView) view.findViewById(R.id.time);
if (event.equals(VhallConnectService.TYPE_CUSTOM)) {
c.setText("接收的自定义消息" + nick_name + ": " + data);
} else if (event.equals(VhallConnectService.TYPE_JOIN)) {
c.setText(nick_name + ": 上线了");
} else if (event.equals(VhallConnectService.TYPE_LEAVE)) {
c.setText(nick_name + ": 下线了");
} else {
c.setText(nick_name + ": " + data);
}
t.setText(time);
ll_content.addView(view);
}
/**
* 根据地址获取头像
* @param url 头像地址
* @param view 设置头像的View
*/
private void requestAvatar(String url, final ImageView view) {
Request request = new Request.Builder().url(url).build();
if (mClient == null)
mClient = new OkHttpClient();
Call call = mClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {}
@Override
public void onResponse(Call call, Response response) throws IOException {
final byte[] picture = response.body().bytes();
runOnUiThread(new Runnable() {
@Override
public void run() {
view.setImageBitmap(BitmapFactory.decodeByteArray(picture, 0, picture.length));
}
});
}
});
}
}