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,會話列表中訊息的滾動位置及未讀訊息提示等