『技術分享』-- 使用極光 IM 構建聊天功能

前言

距離上次極光徵文不知不覺已通過了將近一年的時間,先感謝上次的徵文比賽,經過 《我和 Android 推送的時間簡史》 這篇文章獲獎,此次又厚着臉皮再次參與,由於項目一直很忙,只得利用週末時間準備 demo 素材和寫文章,很差之處,多多見諒。java

上一篇文章主要講述了 我跟 極光推送 的關係,以及簡單的描述了其集成和使用,做爲三個項目都在使用極光推送的我,對其瞭解也是至關多的,固然坑也踩了很多,不得再也不次感謝大俠(極光技術人員)對個人幫助,雖然這一年沒有繼續接觸推送的業務,可是當我遇到困惑依然有問必答,服務態度無可置疑!android

在準備參加徵文時就在想應該從哪一個角度來寫呢,正好以前跟前同事一塊兒寫了一個開源項目 WeaponApp, 如今已經有 800+ 的 star 了。git

image.png

裏面涉及的技術我就不一一闡述了,感興趣的話能夠自行看一下,裏面有一個模塊由我單獨負責- IM模塊,由於已經集成了極光推送,考慮到成本和使用,最終選擇了極光IM,畢竟是以極光推送的大規模、高併發、穩定的推送爲技術基礎,並繼承這些特性。那這篇文章就以我集成的經歷和使用作個介紹,快速的實現具備 IM 功能的 APP。github

展現

這裏只對 IM 模塊功能作簡單的演示,感興趣能夠點擊 連接 進行下載,以下 gif 圖:數據庫

register.gif

ceshi.gif

基本的聊天功能已經實現,其中包括:服務器

  1. 登陸、註冊、強踢和退登
  2. 我的信息查看和修改
  3. 查找好友並進行聊天
  4. 羣聊
  5. 我的中心展現
  6. 刪除會話和清空聊天記錄

後續會根據須要添加新的功能。微信

集成

由於前項已經集成了極光推送服務,不少東西已經不須要重複操做,只須要將 JMessage 相關的組件集成到項目中便可,詳情的步驟可直接參考官網併發

1. 導入jmessage jar 包 2. 在 AndroidManifest 中添加相應的事件app

沒了。。由此能夠看出,由推送到 IM 過渡是多麼流暢!ide

使用

其實在使用的過程,無非是根據本身的業務需求,到 官網 查找 API 來實現本身想要的功能,那我就根據目前項目中有的功能進行介紹。

註冊、登陸和退登

這實際上是用戶的信息管理,極光 IM 統一用 UserInfo 進行管理,內部包含了用戶的大部分信息:

protected long userID;
    protected String userName;
    protected String nickname = "";
    protected String avatarMediaID;
    protected String birthday = "";
    protected String signature = "";
    protected String gender = "";
    protected String region = "";
    protected String address = "";
    protected String appkey = null;
    protected String notename = null;
    protected String noteText = null;
    protected int mTime;
    protected Map<String, String> extras = new ConcurrentHashMap();
複製代碼

1. 註冊

一開始打算本身寫用戶服務器,事實上倒是由另外一位開發者完成了,可是考慮到 IM 的集成,用戶數據的遷移和轉存過程繁瑣,就乾脆直接用極光的用戶接口,其實內部的數據也確實很詳細,還支持自定義字段,徹底知足平常需求。

JMessageClient.register(userName, password, new JMessageCallBack() {
    @Override
    public void onSuccess() {
        registerSuccess(userName);
    }

    @Override
    public void onFailed(int status, String desc) {
        registerFailed(desc);
    }
});
複製代碼

註冊須要用戶名和密碼,註冊成功後經過 setResult 的方法,將帳戶和密碼傳回登陸頁面。

2. 登陸

JMessageClient.login(userName, password, new JMessageCallBack() {
    @Override
    public void onSuccess() {
        loginSuccess(userName);
    }

    @Override
    public void onFailed(int status, String desc) {
        loginFailed(desc);
    }
});
複製代碼

同註冊同樣,登陸也須要用戶名和密碼進行登陸,若是格式有誤會直接觸發 onFailed 回調,彈出相應的提示。成功後本地便會保存一個 UserInfo 對象儲存用戶的信息。

3. 退登

極光支持主動退出帳號的功能,即:

JMessageClient.logout();
複製代碼

直接清除本地保存的用戶信息,一樣他支持多端同時在線:

image.png

若是不打開開關,另外一臺設備登陸,會用 EventBus 發送 LoginStateChangeEvent,告知開發者改帳號已在另外一臺設備登陸,而且會攜帶三種狀態:

case user_password_change:
	forcedExit("帳號密碼被修改");
	break;
case user_logout:
	forcedExit("帳號在另外一臺設備登陸");
	break;
case user_deleted:
	forcedExit("帳號被刪除");
	break;
複製代碼

根據本身的須要進行處理。

信息查看和修改

1. 我的

本身的用戶信息實際上是保存在本地的數據庫中,經過調用:

mUserInfo = JMessageClient.getMyInfo();
複製代碼

獲取用戶信息,以前提過 UserInfo 裏面包含了用戶的全部數據。與之對應的:

JMessageClient.updateMyInfo(UserInfo.Field.gender, mUserInfo, new JMessageCallBack() {
    @Override
    public void onSuccess() {
       
    }

    @Override
    public void onFailed(int status, String desc) {
        
    }
});
複製代碼

這個就是修改本身信息的方法,經過傳入 UserInfo.Field 來區分修改屬性值。

2. 他人

若是須要查看好友的信息,可經過 userName 進行請求查詢:

JMessageClient.getUserInfo(userName, new GetUserInfoCallback() {
    @Override
    public void gotResult(int status, String desc, UserInfo userInfo) {
        if (status == 0) {
            getViewModel().setUserInfo(userInfo);
        } else {
            getViewModel().setError(desc);
        }
    }
});
複製代碼

具體的結果以下:

ceshi.gif

若是是我的信息,直接能夠修改和退登,若是是他人只能查看並與其進行聊天。

聊天

終於到了核心的聊天功能,其實實現起來並不複雜,極光 IM 已經給了豐富的 API 和使用說明,足夠完成基本的需求。

1. 發消息

發消息,前提是須要構建 Message 對象,以基礎文本爲例:

final Message message = mConversation.createSendTextMessage(sendContent);
message.setOnSendCompleteCallback(new BasicCallback() {
    @Override
    public void gotResult(int status, String desc) {
        if (status == 0) {
            // 消息發送成功
            MobclickAgent.onEvent(getContext().getApplicationContext(), "send_message", sendContent);
            addSendMessage(message);
            ++curCount;
            setSendContent("");
            getView().scrollToPosition(items.size() - 1);
        } else {
            // 消息發送失敗
            Toast.makeText(getContext(), desc, Toast.LENGTH_SHORT).show();
        }
    }
});
JMessageClient.sendMessage(message);
複製代碼

最終經過 JmessageClient.sendMessage(message) 將消息發送出去。

2. 接收消息

他這裏比較簡單粗暴,直接使用 EventBus 進行消息接收的回調。

他 jar 裏集成了 EventBus,項目中也有了 EventBus,這一點仍是蠻坑的。換想一下,這裏也是爲了方便接收,否則會有不少相互應用,各類耦合,不過使用過 EventBus 的小夥伴,應該知道,若是維護很差 EventBus 會致使邏輯很是的混亂,維護和拓展異常困難。

* 接收消息事件
 * 目前只支持文字消息,後面再進行優化
 *
 * @param event 消息事件
 */
public void onEventMainThread(MessageEvent event) {
    Message message = event.getMessage();
    switch (message.getContentType()) {
        case text:
            // 處理文字消息
            String userName = ((UserInfo) message.getTargetInfo()).getUserName();
            if (TextUtils.equals(userName, mUserName)) {
                // 當收到的消息是官方消息才進行更新UI
                getViewModel().receiveMessage(message);
            }
        default:
            LogUtils.i("office", message.getFromType());
            break;
    }
}
複製代碼

根據 contentType 區分消息實體的類型,並作相應的處理。 在須要接收消息的地方進行事件的註冊和取消註冊。

JMessageClient.registerEventReceiver(this, 200);
JMessageClient.unRegisterEventReceiver(this);
複製代碼

3. 單聊

這裏引入一個 Conversation 概念,當你與他人聊天必然會創建會話,那會話的消息和聊天的對象都會存在這個會話中,那單聊則經過傳入 userName 進行聯繫,因而可知 userName 的惟一性和重要性。

由於剛進去須要獲取歷史信息,因此經過 conversion 獲取全部的消息,並展現在界面上。

mConversation = Conversation.createSingleConversation(userName);
JMessageClient.getUserInfo(userName, this);
if (mConversation == null) {
    getView().finish();
}
// 獲取本地全部的消息
msgCount = mConversation.getAllMessage().size();
List<Message> messagesFromNewest = mConversation.getMessagesFromNewest(curCount, LIM_COUNT);
curCount = messagesFromNewest.size();
// 第一條消息是正序的,須要反轉一下
Collections.reverse(messagesFromNewest);
for (Message message : messagesFromNewest) {
    MessageDirect direct = message.getDirect();
    if (direct == MessageDirect.send) {
        addSendMessage(message);
    } else {
        addReceiverMessage(message);
    }
}
複製代碼

4. 羣聊

羣聊與單聊有點相似,不過創建會話的前提參數不是 userName, 而是 groupId 羣的惟一標識 ID。

mConversation = Conversation.createGroupConversation(groupId);
if (mConversation == null) {
    getView().finish();
    return;
}
List<Message> messagesFromNewest = mConversation.getMessagesFromNewest(curCount, LIM_COUNT);
curCount = messagesFromNewest.size();
Collections.reverse(messagesFromNewest);
for (Message message : messagesFromNewest) {
    MessageDirect direct = message.getDirect();
    if (direct == MessageDirect.send) {
        addSendMessage(message);
    } else {
        addReceiverMessage(message);
    }
}
複製代碼

具體的代碼很類似,只是建立的過程不同,再也不贅述。

總結

前段時間王欣、字節跳動等都推出社交軟件,不過在微信平臺被封殺,這點仍是蠻狠的,不過另外一方面反映出社交 聊天在各個行業應用的普遍,不管是金融、教育、銷售等軟件都須要一個 IM 做爲用戶與用戶、用戶和平臺之間的溝通橋樑,所以做爲開發者,仍是要多多學習一下 IM 相關的知識。固然本身能獨立完成最好,若是沒有經歷或者暫時能力不夠,又或者公司急切須要集成 IM 功能,建議你能夠考慮極光 IM 服務,其推送服務作得仍是蠻不錯的,並且還在不斷的維護迭代中,有時間不妨嘗試一波吧!

WeaponApp APK下載

本文爲極光徵文參賽文章

相關文章
相關標籤/搜索