最近,經常有朋友問到,如何集成環信頭像,怎么才能快速顯示頭像,因時間緊急,很多朋友都沒有時間慢慢的研究代碼,這里大家稍微花10分鍾看一下文章,看完后再花5分鍾改一下代碼,即可達到你們所要的效果。
當然這個是在你直接復制了demo中的工具類和必要的UI的前提下實現的。簡短說明簡單暴力的方法:除UI外的其他所有類先復制到自己工程中,UI部分MainActivity中的代碼需要一個一個復制過去,如與自己項目沖突的需要調整,然后ChatActivity/ChatFragment也復制過去,這就可以進行聊天了。不過頭像就是大家所遇到的頭像顯示不了,昵稱顯示為環信號碼。
環信官方是有給出頭像的設置的,不過大部分朋友看了之后都是暈呼呼的。官方給出的提示如下:
方法一 從APP服務器獲取昵稱和頭像
昵稱和頭像的獲取:當收到一條消息(群消息)時,得到發送者的用戶ID,然后查找手機本地數據庫是否有此用戶ID的昵稱和頭像,如沒有則調用APP服務器接口通過用戶ID查詢出昵稱和頭像,然后保存到本地數據庫和緩存,下次此用戶發來信息即可直接查詢緩存或者本地數據庫,不需要再次向APP服務器發起請求
昵稱和頭像的更新:當點擊發送者頭像時加載用戶詳情時從APP服務器查詢此用戶的具體信息然后更新本地數據庫和緩存。當用戶自己更新昵稱或頭像時,也可以發送一條透傳消息到其他用戶和用戶所在的群,來更新該用戶的昵稱和頭像。
方法二 從消息擴展中獲取昵稱和頭像
昵稱和頭像的獲取:把用戶基本的昵稱和頭像的URL放到消息的擴展中,通過消息傳遞給接收方,當收到一條消息時,則能通過消息的擴展得到發送者的昵稱和頭像URL,然后保存到本地數據庫和緩存。當顯示昵稱和頭像時,請從本地或者緩存中讀取,不要直接從消息中把賦值拿給界面(否則當用戶昵稱改變后,同一個人會顯示不同的昵稱)。
昵稱和頭像的更新:當擴展消息中的昵稱和頭像URI與當前本地數據庫和緩存中的相應數據不同的時候,需要把新的昵稱保存到本地數據庫和緩存,並下載新的頭像並保存到本地數據庫和緩存。
個人推薦使用方法2,優勢比較明顯,不僅可以設置頭像、昵稱,甚至以后出現的是否管理員,或者自己APP中的身份標志,如:店小二、醫生、客服等等都可以再定義注明,暴力而簡單,不需要考慮對方更新頭像或昵稱,而軟件沒重啟的情況下怎么去更新頭像和昵稱等等復雜的問題。本指導以最簡單的集成為指導,工具類可使用自己軟件中的,或通過別的方式實現。
方法2的集成步驟:
1、在登錄的時候,把自己登錄成功時后台返回的信息保存到sharedpreferences中,需要包含需要的頭像和昵稱。
new Thread(new Runnable() { @Override public void run() { EMClient.getInstance().login(username, password, new EMCallBack() { @Override public void onSuccess() { // 登陸成功,保存用戶昵稱與頭像URL AppSPUtils.setValueToPrefrences("name", loginBean.getName()); AppSPUtils.setValueToPrefrences("logoUrl", loginBean.getLogoUrl()); // 將自己服務器返回的環信賬號、昵稱和頭像URL設置到幫助類中。 DemoHelper.getInstance().getUserProfileManager().updateCurrentUserNickName(loginBean.getName()); DemoHelper.getInstance().getUserProfileManager().setCurrentUserAvatar(loginBean.getLogoUrl()); DemoHelper.getInstance().setCurrentUserName(loginUser.getHxId()); // 環信Id // ------以下參考demo中的,加載群組和加載消息。然后跳轉到首頁-------
2、AppSPUtils是個人寫的一個工具類,大家可以自己寫一個,給出參考代碼。
public class AppSPUtils { private final static int MODE_SPEC = android.os.Build.VERSION.SDK_INT <= 10 ? 0 : Context.MODE_MULTI_PROCESS; public static SharedPreferences getSharedPreferences(String name) { return MainApplication.getContext().getSharedPreferences(name, Context.MODE_PRIVATE | MODE_SPEC); } public static SharedPreferences getAppSharedPreferences() { return getSharedPreferences(Constants.SP_APP); } public static String getValueFromPrefrences(String key, String defaultValue) { return getValueFromPrefrences(getAppSharedPreferences(), key, defaultValue); } public static void setValueToPrefrences(String key, String value) { try { SharedPreferences preferences = getAppSharedPreferences(); if (null != preferences) { preferences.edit().putString(key, value).commit(); } } catch (Exception e) { e.printStackTrace(); } } // 退出登錄時要調用 public static void clean() { try { SharedPreferences preferences = getAppSharedPreferences(); if (null != getAppSharedPreferences()) { getAppSharedPreferences().edit().clear().commit(); } } catch (Exception e) { e.printStackTrace(); } } }
3、保存好自己的信息后,已經成功了四分之一,現在是如何將自己的頭像昵稱等信息發送出去,最簡單的就是使用擴展消息了,在ChatActivity中可以看到,基本上只做了一件事,保證只有一個ChatActivity,那我們的代碼在哪里?就在ChatFragment里面。找到代碼,可以看到其實它是繼承自EaseChatFragment,很多內容在easeui中已經做好了。
這時你會發現ChatFragment類中有一個擴展屬性的說明,沒錯,就是這個方法,把你要發送的內容盡情的發送吧,現附上發送頭像和昵稱的代碼:
@Override public void onSetMessageAttributes(EMMessage message) { if (isRobot) { // 設置消息擴展屬性 message.setAttribute("em_robot_message", isRobot); } // 通過擴展屬性,將userPic和userName發送出去。 String userPic = AppSPUtils.getValueFromPrefrences("logoUrl", ""); if (!TextUtils.isEmpty(userPic)) { message.setAttribute("userPic", userPic); } String userName = AppSPUtils.getValueFromPrefrences("name", ""); if (!TextUtils.isEmpty(userName)) { message.setAttribute("userName", userName); } }
4、發送完成,你已經完成了四分之二的任務了。發送完成后,肯定需要一個接收,其實demo中的廣播已經接收好了,那么我們跟隨着廣播的腳步,來到DemoHelper這個類,初次看這個類,都是雲一樣的感覺,經過一番查找,發現有個onMessageReceived的方法,並且還有注釋“全局監聽”,趕緊開工,試試接收吧,可以自己打一下log出來看是不是拿到了我們要的。並且照着demoHelper中的保存方法,將接收到的內容保存起來。
@Override public void onMessageReceived(List<EMMessage> messages) { for (EMMessage message : messages) { message.setMsgTime(System.currentTimeMillis()); //************接收並處理擴展消息*********************** String userName = message.getStringAttribute("userName", ""); String userPic = message.getStringAttribute("userPic", ""); String hxIdFrom = message.getFrom(); EaseUser easeUser = new EaseUser(hxIdFrom); easeUser.setAvatar(userPic); easeUser.setNick(userName); // 存入內存 getContactList(); contactList.put(hxIdFrom, easeUser); // 存入db UserDao dao = new UserDao(MainApplication.getContext()); List<EaseUser> users = new ArrayList<EaseUser>(); users.add(easeUser); dao.saveContactList(users); getModel().setContactSynced(true); // 通知listeners聯系人同步完畢 notifyContactsSyncListener(true); if (isGroupsSyncedWithServer()) { notifyForRecevingEvents(); } // ******************擴展信息處理完成********************** EMLog.d(TAG, "onMessageReceived id : " + message.getMsgId()); // 應用在后台,不需要刷新UI,通知欄提示新消息 if (!easeUI.hasForegroundActivies()) { getNotifier().onNewMsg(message); } } }
5、信息都收到了,就差最后一步就可以顯示了,不知道你們是不是激動,反正我是激動了。那在哪里進行顯示呢?還是在DemoHelper中,找到getUserInfo方法,代碼如下:
private EaseUser getUserInfo(String hxId) { // 獲取user信息,demo是從內存的好友列表里獲取, // 實際開發中,可能還需要從服務器獲取用戶信息, // 從服務器獲取的數據,最好緩存起來,避免頻繁的網絡請求 if (hxId.equals(EMClient.getInstance().getCurrentUser())) { EaseUser currentUserInfo = getUserProfileManager().getCurrentUserInfo(); return currentUserInfo; } EaseUser easeUser; if (contactList != null && contactList.containsKey(hxId)) { } else { // 如果內存中沒有,則將本地數據庫中的取出到內存中。 getContactList(); } // // TODO 獲取不在好友列表里的群成員具體信息,即陌生人信息,demo未實現 // if (user == null && getRobotList() != null) { // user = getRobotList().get(hxId); // } easeUser = contactList.get(hxId); if(easeUser == null){ easeUser = new EaseUser(hxId); } else { if(TextUtils.isEmpty(easeUser.getNick())){ // 如果名字為空,則顯示環信號碼 easeUser.setNick(easeUser.getUsername()); } } return easeUser; }
OK,大功告成,到這里你的頭像已經可以顯示了。。恭喜你!
有朋友還有疑問,為什么頭像是方形的,要變成圓形怎么辦?指個路,在easeui中的utils包下,找到EaseUserUtils,這里就是顯示用戶頭像和用戶昵稱的地方,通過Glide可以輕松顯示圓形頭像,百度有很多方法,這里就不多講了,同樣,你也可以通過其他圖形加載框架來完成。
很多朋友不明白擴展消息的是什么東西,也不明白為什么照着代碼敲就能夠完成頭像的顯示,那下面就給大家粗淺的講講所涉及到的邏輯關系。
擴展消息:就是你每一次發送消息,都會附帶在你發送內容上面的額外消息,他會隨着你的內容發送出去,每次會多一點點流量,但微乎其微,個人認為並無多大影響。
顯示頭像邏輯:區分為本地化緩存和運行內存緩存,在demoHelper中可以發現,有一個成員變量private Map<String, EaseUser> contactList;
這個就是用來保存在運行內存緩存的,只有通過運行緩存,顯示頭像是最順暢的,如果每次都從數據庫中讀取的話,聊天界面會比較卡,有朋友保存在SP里面,以ID做為KEY,頭像和昵稱等拼接做為value進行緩存,取出后再拆分開分別取值,據說是不卡,大家可以試一下。
本地化存儲是為了在每次打開軟件的時候,從本地存儲中拿到運行內存中使用做准備,大家可以認真看看demoHelper和MainActivity中的代碼。
講了方法2設置頭像,那么方法1,個人不推薦,但這里給出處理的過程,如有個別有需求的,可以按方法1來處理:
1、登錄成功后,在手機子線程,訪問你們的后台服務器,拿到所有好友的環信ID,頭像,昵稱。然后按上面的保存方法,保存到本地中,完成后發送廣播或EventBus之類到,刷新消息界面和ChatFragment。
2、在getUserInfo中,寫和上面擴展消息一樣的內容,將如果運行緩存和本地都拿不到,則發起網絡請求到后台獲取頭像,等請求到內容后,再發出廣播或EventBus通知刷新消息界面和ChatFragment。