1. 程式人生 > >Android基於環信SDK開發IM即時聊天(一)

Android基於環信SDK開發IM即時聊天(一)

目前市面上我瞭解的做第三方即時聊天SDK的有兩家:環信融雲,這裡我使用環信SDK來完成即時聊天的初步開發工作。

下面先奉上1張效果圖:
聊天內容列表

1、開發準備

首先要到環信官網註冊開發者賬號,目前只有企業賬號註冊,不過反正也不會去稽核企業資訊的正確與否,所以隨便填寫個自己喜歡的ID就好了。註冊成功後,登陸到環信管理後臺,新建一個應用,環信的appkey就是根據你的應用名和企業ID來確定的,比如我的企業ID叫SIP,應用名叫Luffy,那麼我的appkey就是SIP#Luffy,簡單好記。
然後需要在IDE(這裡我還是使用的Eclipse)中新建一個Android Project,取名叫IMSample,該專案工程程式碼目前託管在CSDN平臺下,

傳送門
最後在環信SDK官網下載最新的SDK,這樣準備工作就完成了。

2、登陸註冊

1、初始化SDK

把下載的SDK中的jar包和so檔案放在對應目錄下,在AndroidManifest.xml中新增appkey宣告,然後是在程式碼中初始化SDK,建議繼承Application類,在自己的application中初始化SDK

        int pid = android.os.Process.myPid();
        String processAppName = getAppName(pid);
        if (processAppName == null
                || !processAppName.equalsIgnoreCase
("com.example.imsample")) { Log.e(TAG, "enter the service process!"); return; } EMChat.getInstance().init(getApplicationContext());

2、註冊

註冊模式,我選擇開放註冊,然後在註冊介面新增圖片驗證碼功能,降低惡意註冊垃圾使用者的可能性。

        EMChatManager.getInstance().createAccountOnServer(userName, password);

註冊流程
註冊成功後,我們可以在環信管理後臺中看到剛剛註冊的使用者,當然我們也可以在後臺手動介面化添加註冊使用者
後臺註冊使用者

3、登陸

登陸
然後回到登陸介面,使用剛剛註冊的賬號登陸

        EMChatManager.getInstance().login(userName, password, new EMCallBack() {// 回撥
                    @Override
                    public void onSuccess() {
                        runOnUiThread(new Runnable() {
                            public void run() {
                                EMGroupManager.getInstance().loadAllGroups();
                                EMChatManager.getInstance()
                                        .loadAllConversations();
                                Toast.makeText(getApplicationContext(), "登陸成功",
                                        Toast.LENGTH_SHORT).show();
                                startActivity(new Intent(
                                        ChatLoginActivity.this,
                                        ManiActivity.class));
                            }
                        });
                    }

                    @Override
                    public void onProgress(int progress, String status) {

                    }

                    @Override
                    public void onError(int code, String message) {
                        if (code == -1005) {
                            message = "使用者名稱或密碼錯誤";
                        }
                        final String msg = message;
                        runOnUiThread(new Runnable() {
                            public void run() {
                                Toast.makeText(getApplicationContext(), msg,
                                        Toast.LENGTH_SHORT).show();
                            }
                        });
                    }
                });

如果下次再進入應用,預設是自動登陸的,當然也可以在application中設定不自動登陸

        EMChat.getInstance().setAutoLogin(false)

不過我們需要在自動登入的地方加入以下程式碼,不然會獲取不到好友列表和會話資訊等

        if (EMChat.getInstance().isLoggedIn()) {
            Log.d("TAG", "已經登陸過");
            EMGroupManager.getInstance().loadAllGroups();
            EMChatManager.getInstance().loadAllConversations();
            startActivity(new Intent(ChatLoginActivity.this,
                    ManiActivity.class));
        }

4、登出

登出當前登陸使用者前,記得清空儲存的使用者資料

EMChatManager.getInstance().logout(new EMCallBack() {

            @Override
            public void onSuccess() {
                // 跳轉到登陸頁面
            }

            @Override
            public void onError(int code, String message) {
                // 登出失敗

            }

            @Override
            public void onProgress(int progress, String status) {
                // 正在退出

            }

        });

3、好友管理

1、好友的新增

根據環信SDK官方開發文件介紹,需要對新增好友作非同步處理
這裡寫圖片描述

        try {
            EMContactManager.getInstance().addContact(idStr, reasonStr);
            Log.i("TAG", "請求傳送成功,等待對方驗證");
        } catch (EaseMobException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            Log.i("TAG", "addContact-Errcode==>" + e.getErrorCode());
        }

2、好友申請的同意與拒絕

設定一個好友監聽器來監聽應用程式中好友的狀態,同時告訴EMChat已經初始化完畢,可以開始監聽了
這裡寫圖片描述

        EMContactManager.getInstance().setContactListener(
                new MyContactListener());
        EMChat.getInstance().setAppInited();

繼承EMContactListener實現的自定義好友監聽器監聽了五種不同的好友狀態變化

    private class MyContactListener implements EMContactListener {

        @Override
        public void onContactAgreed(String username) {
            // 好友請求被同意
            Log.i("TAG", "onContactAgreed==>" + username);
            // 提示有新訊息
            EMNotifier.getInstance(getApplicationContext()).notifyOnNewMsg();
            Toast.makeText(getApplicationContext(), username + "同意了你的好友請求",
                    Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onContactRefused(String username) {
            // 好友請求被拒絕
            Log.i("TAG", "onContactRefused==>" + username);
        }

        @Override
        public void onContactInvited(String username, String reason) {
            // 收到好友新增請求
            Log.i("TAG", username + "onContactInvited==>" + reason);
            showAgreedDialog(username, reason);
            EMNotifier.getInstance(getApplicationContext()).notifyOnNewMsg();
        }

        @Override
        public void onContactDeleted(List<String> usernameList) {
            // 好友被刪除時回撥此方法
            Log.i("TAG", "usernameListDeleted==>" + usernameList.size());
        }

        @Override
        public void onContactAdded(List<String> usernameList) {
            // 添加了新的好友時回撥此方法
            for (String str : usernameList) {
                Log.i("TAG", "usernameListAdded==>" + str);
            }
        }
    }

對於好友申請的同意或者拒絕只需要一行程式碼,和上面第二步的好友新增一樣,需要新增非同步處理,之後記得重新整理當前好友列表

EMChatManager.getInstance().acceptInvitation(user); // 同意
EMChatManager.getInstance().refuseInvitation(user); // 拒絕 

3、好友列表的獲取

獲取好友列表只能獲取到好友的名字(id),如果想獲取到每個好友的詳細資訊,還得再重新調取其他介面,在我的demo裡,也不用獲取到好友詳細資訊
這裡寫圖片描述

List<String> userList = EMContactManager.getInstance().getContactUserNames();

4、好友的刪除

長按好友列表某一項可以刪除好友,刪除好友和前面幾步的新增、同意、拒絕一樣,需要非同步處理和重新整理列表

EMChatManager.getInstance().deleteContact(user); // 刪除

4、即時聊天

點選好友列表即可發起聊天請求,效果圖見文章開頭,四步走
第一:新建一個繼承自BroadcastReceiver的用來接收新訊息的廣播

    private class NewMessageBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            // 登出廣播
            abortBroadcast();

            // 訊息id(每條訊息都會生成唯一的一個id,目前是SDK生成)
            String msgId = intent.getStringExtra("msgid");
            // 傳送方
            String username = intent.getStringExtra("from");
            // 收到這個廣播的時候,message已經在db和記憶體裡了,可以通過id獲取mesage物件
            EMMessage message = EMChatManager.getInstance().getMessage(msgId);
            EMConversation conversation = EMChatManager.getInstance()
                    .getConversation(username);

            MessageBody tmBody = message.getBody();

            ChatListData data = new ChatListData();
            data.setReceiveContent(((TextMessageBody) tmBody).getMessage());
            data.setType(2);
            mListData.add(data);
            mHandler.sendEmptyMessage(0x00001);

            Log.i("TAG", "收到訊息:" + ((TextMessageBody) tmBody).getMessage());
            // 如果是群聊訊息,獲取到group id
            if (message.getChatType() == ChatType.GroupChat) {
                username = message.getTo();
            }

            if (!username.equals(username)) {
                // 訊息不是發給當前會話,return
                return;
            }
        }
    }

第二:在該類入口處註冊這個廣播以及環信的intentFilter

        msgReceiver = new NewMessageBroadcastReceiver();
        IntentFilter intentFilter = new IntentFilter(EMChatManager
                .getInstance().getNewMessageBroadcastAction());
        intentFilter.setPriority(3);
        registerReceiver(msgReceiver, intentFilter);

第三:在傳送訊息按鈕的監聽方法裡傳送聊天訊息

    void sendMessageHX(String username, final String content) {
        // 獲取到與聊天人的會話物件。引數username為聊天人的userid或者groupid,後文中的username皆是如此
        EMConversation conversation = EMChatManager.getInstance()
                .getConversation(username);
        // 建立一條文字訊息
        EMMessage message = EMMessage.createSendMessage(EMMessage.Type.TXT);
        // // 如果是群聊,設定chattype,預設是單聊
        // message.setChatType(ChatType.GroupChat);
        // 設定訊息body
        TextMessageBody txtBody = new TextMessageBody(content);
        message.addBody(txtBody);
        // 設定接收人
        message.setReceipt(username);
        // 把訊息加入到此會話物件中
        conversation.addMessage(message);
        // 傳送訊息
        EMChatManager.getInstance().sendMessage(message, new EMCallBack() {

            @Override
            public void onError(int arg0, String arg1) {
                // TODO Auto-generated method stub
                Log.i("TAG", "訊息傳送失敗");
            }

            @Override
            public void onProgress(int arg0, String arg1) {
                // TODO Auto-generated method stub
                Log.i("TAG", "正在傳送訊息");
            }

            @Override
            public void onSuccess() {
                // TODO Auto-generated method stub
                Log.i("TAG", "訊息傳送成功");
                ChatListData data = new ChatListData();
                data.setSendContent(content);
                data.setType(1);
                mListData.add(data);
                mHandler.sendEmptyMessage(0x00001);
            }
        });
    }

第四:在該類的onDestory()方法裡登出這個廣播

@Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        unregisterReceiver(msgReceiver);

    }

5、總結

感覺環信SDK還是不太穩定,或者也有可能說是我沒用好,這裡這是簡單的介紹下它的功能,在我的demo裡僅僅簡單實現了這樣幾個功能:
1,開放註冊,登陸
2,好友新增、同意與拒絕(重新登陸才能看到)、刪除,列表獲取
3,只有雙方都在聊天會話介面才能即時聊天
還有幾個大問題沒解決或者說需要重度優化:
1,斷線重連
2,離線訊息的儲存與讀取
3,好友新增請求與響應請求的即時顯示
4,好友列表訊息數目的獲取顯示
5,會話列表中訊息的滾動位置及未讀訊息提示等