編輯:關於Android編程
一、Android SDK簡介
環信SDK為用戶開發IM相關的應用提供的一套完善的開發框架。 包括以下幾個部分:
SDK_Core為核心的消息同步協議實現,完成與服務器之間的信息交換。 SDK是基於核心協議實現的完整的IM功能,實現了不同類型消息的收發、會話管理、群組、好友、聊天室等功能。 EaseUI是一組IM相關的UI控件,旨在幫助開發者快速集成環信SDK。SDK采用模塊化設計,每一模塊的功能相對獨立和完善,用戶可以根據自己的需求選擇使用下面的模塊:
EMClient: SDK的入口,主要完成登錄、退出、連接管理等功能。也是獲取其他模塊的入口。 EMChatManager: 管理消息的收發,完成會話管理等功能。 EMContactManager: 負責好友的添加刪除,黑名單的管理。 EMGroupManager: 負責群組的管理,創建、刪除群組,管理群組成員等功能。 EMChatroomManager: 負責聊天室的管理。二、Android SDK集成
集成前准備:注冊並創建應用
注冊環信開發者賬號:下載SDK :到環信官網下載環信SDK。
SDK目錄講解:從官網下載的SDK目錄包含了4個文件夾,如下:
doc文件夾:SDK相關API文檔 examples文件夾:ChatDemoUI(老的Demo,不推薦使用)、ChatDemoUI3.0(3.0Demo依賴EaseUI庫)、EaseUI libs文件夾:包含IM和實時音視頻功能所需要的jar和so文件 libs.without.audio文件夾:無實時語音、實時視頻功能的SDK包,如果項目中只用到聊天功能,可以把項目裡的jar和so文件替換成此文件夾裡的第三方類庫介紹:
SDK中用到的第三方庫:注:清單文件的配置示例
四、初始化SDK
要求在application的oncreate方法中做初始化,初始化的時候需要傳入設置好的options。
EMOptions options = new EMOptions();
// 默認添加好友時,是不需要驗證的,改成需要驗證
options.setAcceptInvitationAlways(false);
...
//初始化
EMClient.getInstance().init(applicationContext, options);
//在做打包混淆時,關閉debug模式,避免消耗不必要的資源
EMClient.getInstance().setDebugMode(true);
注:如果你的APP中有第三方的服務啟動,請在初始化SDK(EMClient.getInstance().init(applicationContext, options))方法的前面添加以下相關代碼(相應代碼也可參考Demo的application),使用EaseUI庫的就不用理會這個。
appContext = this;
int pid = android.os.Process.myPid();
String processAppName = getAppName(pid);
// 如果APP啟用了遠程的service,此application:onCreate會被調用2次
// 為了防止環信SDK被初始化2次,加此判斷會保證SDK被初始化1次
// 默認的APP會在以包名為默認的process name下運行,如果查到的process name不是APP的process name就立即返回
if (processAppName == null ||!processAppName.equalsIgnoreCase(appContext.getPackageName())) {
Log.e(TAG, "enter the service process!");
// 則此application::onCreate 是被service 調用的,直接返回
return;
}
如何獲取processAppName請參考以下方法。
private String getAppName(int pID) {
String processName = null;
ActivityManager am = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
List l = am.getRunningAppProcesses();
Iterator i = l.iterator();
PackageManager pm = this.getPackageManager();
while (i.hasNext()) {
ActivityManager.RunningAppProcessInfo info = (ActivityManager.RunningAppProcessInfo) (i.next());
try {
if (info.pid == pID) {
processName = info.processName;
return processName;
}
} catch (Exception e) {
// Log.d("Process", "Error>> :"+ e.toString());
}
}
return processName;
}
五、注冊
注冊模式分兩種,開放注冊和授權注冊。只有開放注冊時,才可以客戶端注冊。
開放注冊是為了測試使用,正式環境中不推薦使用該方式注冊環信賬號; 授權注冊的流程應該是您服務器通過環信提供的REST API注冊,之後保存到您的服務器或返回給客戶端。
注冊用戶名會自動轉為小寫字母,所以建議用戶名均以小寫注冊。(強烈建議開發者通過後台調用REST接口去注冊環信ID,客戶端注冊方法不提倡使用。)
//注冊失敗會拋出HyphenateException
EMClient.getInstance().createAccount(username, pwd);//同步方法
六、登錄
EMClient.getInstance().login(userName,password,new EMCallBack() {//回調
@Override
public void onSuccess() {
runOnUiThread(new Runnable() {
public void run() {
EMClient.getInstance().groupManager().loadAllGroups();
EMClient.getInstance().chatManager().loadAllConversations();
Log.d("main", "登錄聊天服務器成功!");
}
});
}
@Override
public void onProgress(int progress, String status) {
}
@Override
public void onError(int code, String message) {
Log.d("main", "登錄聊天服務器失敗!");
}
});
注意: 登錄成功後需要調用EMClient.getInstance().chatManager().loadAllConversations(); 和EMClient.getInstance().groupManager().loadAllGroups();。
以上兩個方法是為了保證進入主頁面後本地會話和群組都load完畢。
另外如果登錄過,APP長期在後台再進的時候也可能會導致加載到內存的群組和會話為空,可以在主頁面的oncreate裡也加上這兩句代碼,當然,更好的辦法應該是放在程序的開屏頁,可參考demo的SplashActivity。
七、自動登錄
即首次登錄成功後,不需要再次調用登錄方法,在下次APP啟動時,SDK會自動為您登錄。並且如果您自動登錄失敗,也可以讀取到之前的會話信息(以上情況是在未調用登出的情況下實現的)。
SDK中自動登錄屬性默認是true打開的,如果不需要自動登錄,在初始化SDK初始化的時候,調用options.setAutoLogin(false);設置為false關閉。
自動登錄在以下幾種情況下會被取消:
用戶調用了SDK的登出動作; 用戶在別的設備上更改了密碼,導致此設備上自動登錄失敗; 用戶的賬號被從服務器端刪除; 用戶從另一個設備登錄,把當前設備上登錄的用戶踢出。
八、退出登錄
EMClient.getInstance().logout(true);//此方法為同步方法,裡面的參數true表示退出登錄時解綁GCM或者小米推送的token
//此方法為異步方法
EMClient.getInstance().logout(true, new EMCallBack() {
@Override
public void onSuccess() {
// TODO Auto-generated method stub
}
@Override
public void onProgress(int progress, String status) {
// TODO Auto-generated method stub
}
@Override
public void onError(int code, String message) {
// TODO Auto-generated method stub
}
});
九、注冊連接狀態監聽
當掉線時,Android SDK會自動重連,無需進行任何操作,通過注冊連接監聽來知道連接狀態。
在聊天過程中難免會遇到網絡問題,在此SDK為您提供了網絡監聽接口,實時監聽
可以根據disconnect返回的error判斷原因。若服務器返回的參數值為EMError.USER_LOGIN_ANOTHER_DEVICE,則認為是有同一個賬號異地登錄;若服務器返回的參數值為EMError.USER_REMOVED,則是賬號在後台被刪除。
//注冊一個監聽連接狀態的listener
EMClient.getInstance().addConnectionListener(new MyConnectionListener());
//實現ConnectionListener接口
private class MyConnectionListener implements EMConnectionListener {
@Override
public void onConnected() {
}
@Override
public void onDisconnected(final int error) {
runOnUiThread(new Runnable() {
@Override
public void run() {
if(error == EMError.USER_REMOVED){
// 顯示帳號已經被移除
}else if (error == EMError.USER_LOGIN_ANOTHER_DEVICE) {
// 顯示帳號在其他設備登錄
} else {
if (NetUtils.hasNetwork(MainActivity.this))
//連接不到聊天服務器
else
//當前網絡不可用,請檢查網絡設置
}
}
});
}
}
十、消息
1. 發送消息:
* 發送文本消息:
“`
//創建一條文本消息,content為消息文字內容,toChatUsername為對方用戶或者群聊的id,後文皆是如此
EMMessage message = EMMessage.createTxtSendMessage(content, toChatUsername);
//如果是群聊,設置chattype,默認是單聊
if (chatType == CHATTYPE_GROUP)
message.setChatType(ChatType.GroupChat);
//發送消息
EMClient.getInstance().chatManager().sendMessage(message);
```
發送語音消息:
```
//filePath為語音文件路徑,length為錄音時間(秒)
EMMessage message = EMMessage.createVoiceSendMessage(filePath, length, toChatUsername);
//如果是群聊,設置chattype,默認是單聊
if (chatType == CHATTYPE_GROUP)
message.setChatType(ChatType.GroupChat);
EMClient.getInstance().chatManager().sendMessage(message);
```
發送視頻信息:
“`
//videoPath為視頻本地路徑,thumbPath為視頻預覽圖路徑,videoLength為視頻時間長度
EMMessage message = EMMessage.createVideoSendMessage(videoPath, thumbPath, videoLength, toChatUsername);
//如果是群聊,設置chattype,默認是單聊
if (chatType == CHATTYPE_GROUP)
message.setChatType(ChatType.GroupChat);
EMClient.getInstance().chatManager().sendMessage(message);
```
發送圖片信息:
“`
//imagePath為圖片本地路徑,false為不發送原圖(默認超過100k的圖片會壓縮後發給對方),需要發送原圖傳true
EMMessage.createImageSendMessage(imagePath, false, toChatUsername);
//如果是群聊,設置chattype,默認是單聊
if (chatType == CHATTYPE_GROUP)
message.setChatType(ChatType.GroupChat);
EMClient.getInstance().chatManager().sendMessage(message);
```
發送地理位置信息:
“`
//latitude為緯度,longitude為經度,locationAddress為具體位置內容
EMMessage message = EMMessage.createLocationSendMessage(latitude, longitude, locationAddress, toChatUsername);
//如果是群聊,設置chattype,默認是單聊
if (chatType == CHATTYPE_GROUP)
message.setChatType(ChatType.GroupChat);
EMClient.getInstance().chatManager().sendMessage(message);
```
發送文件消息:
“`
EMMessage message = EMMessage.createFileSendMessage(filePath, toChatUsername);
// 如果是群聊,設置chattype,默認是單聊
if (chatType == CHATTYPE_GROUP)
message.setChatType(ChatType.GroupChat);
EMClient.getInstance().chatManager().sendMessage(message);
```
發送透傳消息:
“`
透傳消息能做什麼:頭像、昵稱的更新等。可以把透傳消息理解為一條指令,通過發送這條指令給對方,告訴對方要做的action,收到消息可以自定義處理的一種消息。(透傳消息不會存入本地數據庫中,所以在UI上是不會顯示的)
EMMessage cmdMsg = EMMessage.createSendMessage(EMMessage.Type.CMD);
//支持單聊和群聊,默認單聊,如果是群聊添加下面這行
cmdMsg.setChatType(ChatType.GroupChat)
String action="action1";//action可以自定義
EMCmdMessageBody cmdBody = new EMCmdMessageBody(action);
String toUsername = "test1";//發送給某個人
cmdMsg.setReceipt(toUsername);
cmdMsg.addBody(cmdBody);
EMClient.getInstance().chatManager().sendMessage(message);
```
接收消息:
通過注冊消息監聽來接收消息。
EMClient.getInstance().chatManager().addMessageListener(msgListener);
EMMessageListener msgListener = new EMMessageListener() {
@Override
public void onMessageReceived(List messages) {
//收到消息
}
@Override
public void onCmdMessageReceived(List messages) {
//收到透傳消息
}
@Override
public void onMessageReadAckReceived(List messages) {
//收到已讀回執
}
@Override
public void onMessageDeliveryAckReceived(List message) {
//收到已送達回執
}
@Override
public void onMessageChanged(EMMessage message, Object change) {
//消息狀態變動
}
};
記得在不需要的時候移除listener,如在activity的onDestroy()時EMClient.getInstance().chatManager().removeMessageListener(msgListener);
監聽消息狀態:通過message設置消息的發送及接收狀態。
message.setMessageStatusCallback(new EMCallBack(){});
消息擴展:
當SDK提供的消息類型不滿足需求時,開發者可以通過擴展自SDK提供的文本、語音、圖片、位置等消息類型,從而生成自己需要的消息類型。
這裡是擴展自文本消息,如果這個自定義的消息需要用到語音或者圖片等,可以擴展自語音、圖片消息,亦或是位置消息。
EMMessage message = EMMessage.createTxtSendMessage(content, toChatUsername);
// 增加自己特定的屬性
message.setAttribute("attribute1", "value");
message.setAttribute("attribute2", true);
...
EMClient.getInstance().chatManager().sendMessage(message);
//接收消息的時候獲取到擴展屬性
//獲取自定義的屬性,第2個參數為沒有此定義的屬性時返回的默認值
message.getStringAttribute("attribute1",null);
message.getBooleanAttribute("attribute2", false);
...
獲取聊天記錄:
EMConversation conversation = EMClient.getInstance().chatManager().getConversation(username);
//獲取此會話的所有消息
List messages = conversation.getAllMessages();
//SDK初始化加載的聊天記錄為20條,到頂時需要去DB裡獲取更多
//獲取startMsgId之前的pagesize條消息,此方法獲取的messages SDK會自動存入到此會話中,APP中無需再次把獲取到的messages添加到會話中
List messages = conversation.loadMoreMsgFromDB(startMsgId, pagesize);
建議初始化SDK的時候設置成每個會話默認load一條消息,節省加載會話的時間,方法為: options.setNumberOfMessagesLoaded(1);
獲取未讀消息數量:
EMConversation conversation = EMClient.getInstance().chatManager().getConversation(username);
conversation.getUnreadMsgCount();
未讀消息數清零:
EMConversation conversation = EMClient.getInstance().chatManager().getConversation(username);
//指定會話消息未讀數清零
conversation.markAllMessagesAsRead();
//把一條消息置為已讀
conversation.markMessageAsRead(messageId);
//所有未讀消息數清零
EMClient.getInstance().chatManager().markAllConversationsAsRead();
獲取消息總數:
EMConversation conversation = EMClient.getInstance().chatManager().getConversation(username);
//獲取此會話在本地的所有的消息數量
conversation.getAllMsgCount();
//如果只是獲取當前在內存的消息數量,調用
conversation.getAllMessages().size();
刪除會話及聊天記錄:
//刪除和某個user會話,如果需要保留聊天記錄,傳false
EMClient.getInstance().chatManager().deleteConversation(username, true);
//刪除當前會話的某條聊天記錄
EMConversation conversation = EMClient.getInstance().chatManager().getConversation(username);
conversation.removeMessage(deleteMsg.msgId);
導入消息到數據庫:
EMClient.getInstance().chatManager().importMessages(msgs);
十一、好友管理
獲取好友列表獲取好友的username list,開發者需要根據username去自己服務器獲取好友的詳情。
List usernames = EMClient.getInstance().contactManager().getAllContactsFromServer();
查找好友
SDK不提供好友查找的服務,如需要查找好友,需要調用開發者自己服務器的用戶查詢接口。
為了保證查找到的好友可以添加,需要將開發者自己服務器的用戶數據(用戶的環信ID),通過SDK的後台接口導入到 環信服務器中。
添加好友
//參數為要添加的好友的username和添加理由
EMClient.getInstance().contactManager().addContact(toAddUsername, reason);
刪除好友
EMClient.getInstance().contactManager().deleteContact(username);
同意好友請求
默認好友請求是自動同意的,如果要手動同意需要在初始化SDK時調用 opptions.setAcceptInvitationAlways(false); 。
EMClient.getInstance().contactManager().acceptInvitation(username);
拒絕好友請求
EMClient.getInstance().contactManager().declineInvitation(username);
監聽好友狀態事件
EMClient.getInstance().contactManager().setContactListener(new EMContactListener() {
@Override
public void onContactAgreed(String username) {
//好友請求被同意
}
@Override
public void onContactRefused(String username) {
//好友請求被拒絕
}
@Override
public void onContactInvited(String username, String reason) {
//收到好友邀請
}
@Override
public void onContactDeleted(String username) {
//被刪除時回調此方法
}
@Override
public void onContactAdded(String username) {
//增加了聯系人時回調此方法
}
});
從服務器獲取黑名單列表
EMClient.getInstance().contactManager().getBlackListFromServer();
從本地數據庫獲取名單列表
EMClient.getInstance().contactManager().getBlackListUsernames();
將用戶加入黑名單
//第二個參數如果為true,則把用戶加入到黑名單後雙方發消息時對方都收不到;false,則我能給黑名單的中用戶發 消息,但是對方發給我時我是收不到的
EMClient.getInstance().contactManager().addUserToBlackList(username,true);
把用戶從黑名單移除
EMClient.getInstance().contactManager().removeUserFromBlackList(username);
十二、群組管理
新建群組
/**
* 創建群組
* @param groupName 群組名稱
* @param desc 群組簡介
* @param allMembers 群組初始成員,如果只有自己傳null即可
* @param reason 邀請成員加入的reason
* @param option 群組類型選項,可以設置群組最大用戶數(默認200)及群組類型@see {@link EMGroupStyle}
* @return 創建好的group
* @throws HyphenateException
*/
EMGroupOptions option = new EMGroupOptions();
option.maxUsers = 200;
option.style = EMGroupStyle.EMGroupStylePrivateMemberCanInvite;
EMClient.getInstance().groupManager().createGroup(groupName, desc, allMembers, reason, option);
option裡的GroupStyle分別為:
EMGroupStylePrivateOnlyOwnerInvite——私有群,只有群主可以邀請人;
EMGroupStylePrivateMemberCanInvite——私有群,群成員也能邀請人進群;
EMGroupStylePublicJoinNeedApproval——公開群,加入此群除了群主邀請,只能通過申請加入此群;
EMGroupStylePublicOpenJoin ——公開群,任何人都能加入此群。
群組加人
//群主加人調用此方法
EMClient.getInstance().groupManager().addUsersToGroup(groupId, newmembers);//需異步處理
//私有群裡,如果開放了群成員邀請,群成員邀請調用下面方法
EMClient.getInstance().groupManager().inviteUser(groupId, newmembers, null);//需異步處理
群組踢人
//把username從群組裡刪除
EMClient.getInstance().groupManager().removeUserFromGroup(groupId, username);//需異步處理
加入某個群組
//如果群開群是自由加入的,即group.isMembersOnly()為false,直接join
EMClient.getInstance().groupManager().joinGroup(groupid);//需異步處理
//需要申請和驗證才能加入的,即group.isMembersOnly()為true,調用下面方法
EMClient.getInstance().groupManager().applyJoinToGroup(groupid, "求加入");//需異步處理
退出群組
EMClient.getInstance().groupManager().leaveGroup(groupId);//需異步處理
解散群組
EMClient.getInstance().groupManager().destroyGroup(groupId);//需異步處理
獲取群組列表
//從服務器獲取自己加入的和創建的群組列表,此api獲取的群組sdk會自動保存到內存和db。
List grouplist = EMClient.getInstance().groupManager().getJoinedGroupsFromServer();//需異步處理
//從本地加載群組列表
List grouplist = EMClient.getInstance().groupManager().getAllGroups();
//獲取公開群列表
//pageSize為要取到的群組的數量,cursor用於告訴服務器從哪裡開始取
EMCursorResult result = EMClient.getInstance().groupManager().getPublicGroupsFromServer(pageSize, cursor);//需異步處理
List groupsList = List returnGroups = result.getData();
String cursor = result.getCursor();
修改群組名稱
//groupId 需要改變名稱的群組的id
//changedGroupName 改變後的群組名稱
EMClient.getInstance().groupManager().changeGroupName(groupId,changedGroupName);//需異步處理
獲取單個群組信息
//根據群組ID從本地獲取群組基本信息
EMGroup group = EMClient.getInstance().groupManager().getGroup(groupId);
//根據群組ID從服務器獲取群組基本信息
EMGroup group = EMClient.getInstance().groupManager().getGroupFromServer(groupId);
group.getMembers();//獲取群成員
group.getOwner();//獲取群主
...
屏蔽群消息
/**
* 屏蔽群消息後,就不能接收到此群的消息(還是群裡面的成員,但不再接收消息)
* @param groupId, 群ID
* @throws EasemobException
*/
EMClient.getInstance().groupManager().blockGroupMessage(groupId);//需異步處理
解除屏蔽群
/**
* 取消屏蔽群消息,就可以正常收到群的所有消息
* @param groupId
* @throws EaseMobException
*/
EMClient.getInstance().groupManager().unblockGroupMessage(groupId);//需異步處理
將群成員拉入群組黑名單
/**
* 將用戶加到群組的黑名單,被加入黑名單的用戶無法加入群,無法收發此群的消息
* (只有群主才能設置群的黑名單)
* @param groupId, 群組的ID
* @param username, 待屏蔽的用戶名
* @exception EaseMobException 出錯會拋出
*/
EMClient.getInstance().groupManager().blockUser(groupId, username);//需異步處理
將用戶移出群黑名單
/**
* 將用戶從群組的黑名單移除(只有群主才能調用此函數)
* @param groupId, 群組的ID
* @param username, 待解除屏蔽的用戶名
*/
EMClient.getInstance().groupManager().unblockUser(groupId, username);//需異步處理
獲取群組黑名單用戶列表
/**
* 獲取群組的黑名單用戶列表
* (只有群主才能調用此函數)
* @return List
* @throws EaseMobException 獲取失敗
*/
EMClient.getInstance().groupManager().getBlockedUsers(groupId);//需異步處理
群組監聽事件
EMClient.getInstance().groupManager().addGroupChangeListener(new EMGroupChangeListener() {
@Override
public void onUserRemoved(String groupId, String groupName) {
//當前用戶被管理員移除出群組
}
@Override
public void onInvitationReceived(String groupId, String groupName, String inviter, String reason) {
//收到加入群組的邀請
}
@Override
public void onInvitationDeclined(String groupId, String invitee, String reason) {
//群組邀請被拒絕
}
@Override
public void onInvitationAccpted(String groupId, String inviter, String reason) {
//群組邀請被接受
}
@Override
public void onGroupDestroy(String groupId, String groupName) {
//群組被創建者解散
}
@Override
public void onApplicationReceived(String groupId, String groupName, String applyer, String reason) {
//收到加群申請
}
@Override
public void onApplicationAccept(String groupId, String groupName, String accepter) {
//加群申請被同意
}
@Override
public void onApplicationDeclined(String groupId, String groupName, String decliner, String reason) {
// 加群申請被拒絕
}
});
View的平滑滾動效果什麼是實現View的平滑滾動效果呢,舉個簡單的例子,一個View從在我們指定的時間內從一個位置滾動到另外一個位置,我們利用Scroller類可以實現
BroadcastReceiver(廣播接收器)是Android中的四大組件之一。下面就具體介紹一下Broadcast Receiver組件的用法。下面是Android
PS: 入門階段,加上是Android菜鳥,所以先閱讀他們的文檔作為學習,幸好他們的文檔寫得夠詳細,非常適合我這種小白菜鳥用戶。我主要是看他們的developer_gui
數據存儲在開發中是使用最頻繁的,在這裡主要介紹Android平台中實現數據存儲的5種方式,更加系統詳細的介紹了5種存儲的方法和異同。 第一種: 使用SharedPre