消息服务准备

  1. 注册微吼开发者账号

  2. 创建应用 获取AppID

  3. 设置应用包名、签名

  4. 获取 频道ID channelID

    可以通过 【测试工具】 或 【API】 获得

  5. 获取包含消息模块权限的access_token

    可以通过 【测试工具】 或 【API】 获得

工程配置

  1. 在开始使用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));
                    }
                });
            }
        });
    }
}

参考手册

  1. 快速开始
  2. 消息模块参考手册