android-使用环信SDK开发即时通信功能及源代码下载

时间:2023-01-12 22:39:09

近期项目中集成即时聊天功能。挑来拣去,终于选择环信SDK来进行开发,选择环信的主要原因是接口方便、简洁。说明文档清楚易懂。文档有android、ios、和后台server端。还是非常全的。

环信官网:http://www.easemob.com/

本篇文章目的主要在于说明环信Demo怎样实现即时通信的。我在集成环信SDK到我们自己开发的app之前,研究了一下环信demo的代码。看了两三天的样子,基本搞清楚来龙去脉,可是仅仅是清楚来龙去脉。要说到里面的细节可能得深一步研究,可是这就够了,已经能够把demo里面的功能集成到我们自己的app中了。

所以本篇文章就说明一下怎样集成环信到自己的app中。

集成起来还是比較快的。最多一周时间集成就搞定了。我们是有自己的用户体系的。所以我们採用的是将环信与现有的APP用户体系集成。

android-使用环信SDK开发即时通信功能及源代码下载

集成之前。必定要到上面这个页面进行了解,怎样集成。在这里说明了怎样集成的方案。这个方法的选择就须要你自己依据已有的需求进行选择了。这个就不多说了。应该都明确。

登 录 原 理

我们的方案是将环信与现有的APP用户体系集成!

也就是说我们的server须要把现有的用户在后台注冊到环信server中,然后app登录的时候自己主动登录环信server,然后使用环信的即时通信功能。

这就意味着用户登录app的时候,须要登录两次,一次是我们的应用server。一次是环信server,仅仅只是给用户的感觉是登录了一次,而环信server的登录是代码中控制的。用户看不到也感觉不到。

好友体系原理

登录之后,就是获取好友和群组了。环信添加了聊天室的功能,有点相似于松群组的功能。仅仅只是聊天室更加任意些。群组大家都明确,不多说,聊天室呢不同,开放的公共的聊天室。成员能够随时进入聊天随时离开。离开之后自己主动不再收到聊天信息。

好友体系中环信是能够进行管理的,当然也能够不使用环信的好友管理体系,而使用应用server来进行好友的管理工作。我们项目中使用的是环信的好友管理体系。主要是方便,只是也不见得省了多少事儿,由于应用server用户体系的变更,都要由server把该用户体系的关系的变更通知环信server,然环信server也进行更改,从而保持应用server和环信server用户体系的一致性。所以大家集成过程中须要自己考虑代价。我们项目中使用环信管理好友体系主要在于app端方便,app端也不进行用户体系的变更,复杂的操作都在server端实现。所以app端方便实现、开发简单。

用户昵称、头像

环信server採用了低浸入的方式开发即时通信,也就是说它不保存用户的信息。也不訪问用户的信息。这就意味着用户的昵称、头像等等信息环信是没有保存的。开发人员无法通过环信获取用户信息。所以环信专门对与用户的昵称、头像信息给出了解决方式。

android-使用环信SDK开发即时通信功能及源代码下载

方法一 从APPserver获取昵称和头像

方法二 从消息扩展中获取昵称和头像

昵称或头像处理的方法一和方法二差别:

方法一:在发送消息时不含有不论什么扩展,收消息时假设本地不存在发送人的用户信息则须要从APPserver查询发送人的昵称和头像的URL。

方法二:在发送消息时带有包括昵称和头像URL的消息扩展,收到消息时就可以从消息扩展中取出,不须要再去APPserver获取。 方法二和方法一相比

长处:收到消息马上显示昵称不用等待APPserver返回数据后显示。

缺点:每条消息都要带有扩展,添加消息体积,每次发消息都有一些不必要的数据。

上面是环信给出的用户昵称和头像的两种解决方式。

这两种解决方式大家一看就应用明确了,不多说。主要说说我们项目中的解决方式,採用第一种方案。从应用server获取。保存本地数据库。之后,查询操作就是本地操作。那就会有问题了。用户关系更新或者信息更新呢?这个问题主要解决方法是用户好友体系的每次更新都会同一时候更新用户昵称和头像,然后更新本地数据库来解决问题。

到此,这三个问题明确之后,基本就能够開始进行开发了,你可能会说。还没有说明即时通信呢?最基本的就是即时通信怎么没有说明呢?这个问题大家勿急,后面会有!

^_^

开 发

开发过程。首先就是要研究一下环信demo的代码,里面已经进行了封装。所以把环信demo的代码看懂,利用的好的代码全然能够应用到现有的app中。

android-使用环信SDK开发即时通信功能及源代码下载

这个环信demo的代码,导入手机直接执行。注冊,用着非常好,代码执行正常,功能也正常。所以研究这个代码之后,再集成到自己的app中那就so easy!!

demo里面用到了几个jar包,主要是环信的sdk、百度地图、友盟数据分析、百度地图定位、图片载入等这几个jar包,百度地图这个应该没什么说的,之前我们app里面集成过,只是有点旧,这次顺带着把百度地图也更新成最新的了。眼下百度地图最新的挺好用的。也算是教训,就是实时更新所应用的第三方的jar!别的jar就没什么说的了。

以下就是demo里面的分包了。demo里面的分包比較多,只是从分包的名字能够看出每一个包以下的代码是什么作用了。我主要看的是activity包以下的每一个类,由于activity类就是一个个的界面,其它的都是为这个activity类服务的代码工具类。所以主要看这个就能够了。

android-使用环信SDK开发即时通信功能及源代码下载

activity包以下的类比較多,只是我们关心的类仅仅有几个而已。ChatActivity.java类就是即时聊天的界面。这个一定是要集成到自己的app其中的。

其它的三个ContactlistFragment.java、ChatAllHistoryFragment.java、GroupsActivity.java这三个类各自是联系人界面、回话历史界面、群组界面。这三个须要依据自己app的需求进行集成。

所以主要研究的工作就是放在这几个类上。

MainActivity.java就是主界面。主界面集成了上面三个界面,由主界面进行管理界面的显示。

剩下的工作没什么特别的了。搞不明确代码的能够给我留言,相互交流一下。

特别提一下以下的几个类

android-使用环信SDK开发即时通信功能及源代码下载

这个几个类有点绕。刚開始着实弄混了。

如今看来demo里面代码也是用心良苦呀!!

1、先看controller包以下的HXSDKHelper.java类,再看chatuidemo包以下的DemoHXSDKHelper.java类。明显是继承关系。后者才是demo中使用的对象类。

而且该父类在controller包下。明显是控制信息管理类,打开该类查看代码

android-使用环信SDK开发即时通信功能及源代码下载

从说明能够看出该类的作用了。

2、再看HXSDKModel.java类。这类名字就是模版类。还有DefaultHXSDKModel.java类和DemoSDKModel.java类。也非常明显存在继承关系。

完毕的功能主要是app其中即时通信的一些数据的保存和控制信息显示信息等。

这几个类搞清楚之后基本就没有什么打的问题了。

主要代码解说

1、主类MainActivity.java

public class MainActivity extends BaseActivity implements EMEventListener 

该类实现了EMEventListener 接口,就一个方法例如以下:

/**
* 监听事件
*/
@Override
public void onEvent(EMNotifierEvent event) {
switch (event.getEvent()) {
case EventNewMessage: // 普通消息
{
EMMessage message = (EMMessage) event.getData();
// 提示新消息
HXSDKHelper.getInstance().getNotifier().onNewMsg(message);
refreshUI();
break;
}
case EventOfflineMessage: {
refreshUI();
break;
}
case EventConversationListChanged: {
refreshUI();
break;
} default:
break;
}
}

主要就是监听新消息、离线消息、回话消息变化等。然后更新界面refreshUI(),更新界面就是刷新未读消息数、刷新联系人列表。回话列表等。

在主界面初始化中注冊了三个监听器,例如以下代码:

private void init() {
// setContactListener监听联系人的变化等
EMContactManager.getInstance().setContactListener(new MyContactListener());
// 注冊一个监听连接状态的listener
connectionListener = new MyConnectionListener();
EMChatManager.getInstance().addConnectionListener(connectionListener); groupChangeListener = new MyGroupChangeListener();
// 注冊群聊相关的listener
}

这三个监听器就是监听联系人变化、群组变化、与环信server链接变化的监听器,这三者的变化都会回调这三个监听器里面的对应的方法,方便开发人员通过对应的方法採取对应的措施。

这三个监听器demo中代码比較具体,在此就不多说了。

2 联系人列表ContactlistFragment.java类

/**
* 联系人列表页
*/
public class ContactlistFragment extends Fragment {
public static final String TAG = "ContactlistFragment";
private ContactAdapter adapter;
private List<User> contactList;
private ListView listView;
private boolean hidden;
private Sidebar sidebar;
private InputMethodManager inputMethodManager;
private List<String> blackList;
ImageButton clearSearch;
EditText query;
HXContactSyncListener contactSyncListener;
HXBlackListSyncListener blackListSyncListener;
View progressBar;
Handler handler = new Handler();
private User toBeProcessUser;
private String toBeProcessUsername; /**
* 这里注冊了两个监听器,目的在于同步联系人信息
* 当联系人发生变化、黑名单发生变化。通知这里注冊的监听器
* 进而刷新界面
*
*/
class HXContactSyncListener implements HXSDKHelper.HXSyncListener {
@Override
public void onSyncSucess(final boolean success) {
EMLog.d(TAG, "on contact list sync success:" + success);
ContactlistFragment.this.getActivity().runOnUiThread(new Runnable() {
public void run() {
getActivity().runOnUiThread(new Runnable(){
@Override
public void run() {
if(success){
progressBar.setVisibility(View.GONE);
refresh();
}else{
String s1 = getResources().getString(R.string.get_failed_please_check);
Toast.makeText(getActivity(), s1, 1).show();
progressBar.setVisibility(View.GONE);
}
} });
}
});
}
} class HXBlackListSyncListener implements HXSyncListener{
@Override
public void onSyncSucess(boolean success) {
getActivity().runOnUiThread(new Runnable(){
@Override
public void run() {
blackList = EMContactManager.getInstance().getBlackListUsernames();
refresh();
}
});
} }; @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_contact_list, container, false);
} @Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//防止被T后,没点确定button然后按了home键,长期在后台又进app导致的crash
if(savedInstanceState != null && savedInstanceState.getBoolean("isConflict", false))
return;
inputMethodManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
listView = (ListView) getView().findViewById(R.id.list);
sidebar = (Sidebar) getView().findViewById(R.id.sidebar);
sidebar.setListView(listView); //黑名单列表
blackList = EMContactManager.getInstance().getBlackListUsernames();
contactList = new ArrayList<User>();
// 获取设置contactlist
getContactList();
//搜索框
query = (EditText) getView().findViewById(R.id.query);
query.setHint(R.string.search);
clearSearch = (ImageButton) getView().findViewById(R.id.search_clear);
query.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before, int count) {
adapter.getFilter().filter(s);
if (s.length() > 0) {
clearSearch.setVisibility(View.VISIBLE);
} else {
clearSearch.setVisibility(View.INVISIBLE);
}
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void afterTextChanged(Editable s) {
}
});
clearSearch.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
query.getText().clear();
hideSoftKeyboard();
}
}); // 设置adapter
adapter = new ContactAdapter(getActivity(), R.layout.row_contact, contactList);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new OnItemClickListener() { @Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String username = adapter.getItem(position).getUsername();
if (Constant.NEW_FRIENDS_USERNAME.equals(username)) {
// 进入申请与通知页面
User user = DemoApplication.getInstance().getContactList().get(Constant.NEW_FRIENDS_USERNAME);
user.setUnreadMsgCount(0);
startActivity(new Intent(getActivity(), NewFriendsMsgActivity.class));
} else if (Constant.GROUP_USERNAME.equals(username)) {
// 进入群聊列表页面
startActivity(new Intent(getActivity(), GroupsActivity.class));
} else if(Constant.CHAT_ROOM.equals(username)){
//进入聊天室列表页面
startActivity(new Intent(getActivity(), PublicChatRoomsActivity.class));
}else {
// demo中直接进入聊天页面,实际通常是进入用户详情页
startActivity(new Intent(getActivity(), ChatActivity.class).putExtra("userId", adapter.getItem(position).getUsername()));
}
}
});
listView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// 隐藏软键盘
if (getActivity().getWindow().getAttributes().softInputMode
!= WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN) {
if (getActivity().getCurrentFocus() != null)
inputMethodManager.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(),
InputMethodManager.HIDE_NOT_ALWAYS);
}
return false;
}
}); ImageView addContactView = (ImageView) getView().findViewById(R.id.iv_new_contact);
// 进入加入好友页
addContactView.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
startActivity(new Intent(getActivity(), AddContactActivity.class));
}
});
registerForContextMenu(listView); progressBar = (View) getView().findViewById(R.id.progress_bar); contactSyncListener = new HXContactSyncListener();
HXSDKHelper.getInstance().addSyncContactListener(contactSyncListener); blackListSyncListener = new HXBlackListSyncListener();
HXSDKHelper.getInstance().addSyncBlackListListener(blackListSyncListener); if (!HXSDKHelper.getInstance().isContactsSyncedWithServer()) {
progressBar.setVisibility(View.VISIBLE);
} else {
progressBar.setVisibility(View.GONE);
}
} @Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
if (((AdapterContextMenuInfo) menuInfo).position > 2) {
toBeProcessUser = adapter.getItem(((AdapterContextMenuInfo) menuInfo).position);
toBeProcessUsername = toBeProcessUser.getUsername();
getActivity().getMenuInflater().inflate(R.menu.context_contact_list, menu);
}
} @Override
public boolean onContextItemSelected(MenuItem item) {
if (item.getItemId() == R.id.delete_contact) {
try {
// 删除此联系人
deleteContact(toBeProcessUser);
// 删除相关的邀请消息
InviteMessgeDao dao = new InviteMessgeDao(getActivity());
dao.deleteMessage(toBeProcessUser.getUsername());
} catch (Exception e) {
e.printStackTrace();
}
return true;
}else if(item.getItemId() == R.id.add_to_blacklist){
moveToBlacklist(toBeProcessUsername);
return true;
}
return super.onContextItemSelected(item);
} /**
* 当该Fragment对象改变了隐藏状态(由isHidden()方法返回)时,系统会调用这种方法。
* Fragment初始是不隐藏的,仅仅要Fragment对象改变了它的显示状态。就会调用该方法。
* 參数hidden 假设该Fragment对象如今是隐藏的,则该參数是true。否则是false。 */
@Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
this.hidden = hidden;
if (!hidden) {
refresh();
}
} @Override
public void onResume() {
super.onResume();
if (!hidden) {
refresh();
}
} /**
* 删除联系人
*
* @param toDeleteUser
*/
public void deleteContact(final User tobeDeleteUser) {
String st1 = getResources().getString(R.string.deleting);
final String st2 = getResources().getString(R.string.Delete_failed);
final ProgressDialog pd = new ProgressDialog(getActivity());
pd.setMessage(st1);
pd.setCanceledOnTouchOutside(false);
pd.show();
new Thread(new Runnable() {
public void run() {
try {
EMContactManager.getInstance().deleteContact(tobeDeleteUser.getUsername());
// 删除db和内存中此用户的数据
UserDao dao = new UserDao(getActivity());
dao.deleteContact(tobeDeleteUser.getUsername());
DemoApplication.getInstance().getContactList().remove(tobeDeleteUser.getUsername());
getActivity().runOnUiThread(new Runnable() {
public void run() {
pd.dismiss();
adapter.remove(tobeDeleteUser);
adapter.notifyDataSetChanged(); }
});
} catch (final Exception e) {
getActivity().runOnUiThread(new Runnable() {
public void run() {
pd.dismiss();
Toast.makeText(getActivity(), st2 + e.getMessage(), 1).show();
}
}); } }
}).start(); } /**
* 把user移入到黑名单
*/
private void moveToBlacklist(final String username){
final ProgressDialog pd = new ProgressDialog(getActivity());
String st1 = getResources().getString(R.string.Is_moved_into_blacklist);
final String st2 = getResources().getString(R.string.Move_into_blacklist_success);
final String st3 = getResources().getString(R.string.Move_into_blacklist_failure);
pd.setMessage(st1);
pd.setCanceledOnTouchOutside(false);
pd.show();
new Thread(new Runnable() {
public void run() {
try {
//加入到黑名单
EMContactManager.getInstance().addUserToBlackList(username,false);
getActivity().runOnUiThread(new Runnable() {
public void run() {
pd.dismiss();
Toast.makeText(getActivity(), st2, 0).show();
refresh();
}
});
} catch (EaseMobException e) {
e.printStackTrace();
getActivity().runOnUiThread(new Runnable() {
public void run() {
pd.dismiss();
Toast.makeText(getActivity(), st3, 0).show();
}
});
}
}
}).start(); } // 刷新ui
public void refresh() {
try {
// 可能会在子线程中调到这方法
getActivity().runOnUiThread(new Runnable() {
public void run() {
getContactList();
adapter.notifyDataSetChanged();
}
});
} catch (Exception e) {
e.printStackTrace();
}
} @Override
public void onDestroy() {
if (contactSyncListener != null) {
HXSDKHelper.getInstance().removeSyncContactListener(contactSyncListener);
contactSyncListener = null;
}
if(blackListSyncListener != null){
HXSDKHelper.getInstance().removeSyncBlackListListener(blackListSyncListener);
}
super.onDestroy();
} public void showProgressBar(boolean show) {
if (progressBar != null) {
if (show) {
progressBar.setVisibility(View.VISIBLE);
} else {
progressBar.setVisibility(View.GONE);
}
}
} /**
* 获取联系人列表。并过滤掉黑名单和排序
*/
private void getContactList() {
contactList.clear();
//获取本地好友列表
Map<String, User> users = DemoApplication.getInstance().getContactList();
Iterator<Entry<String, User>> iterator = users.entrySet().iterator();
while (iterator.hasNext()) {
Entry<String, User> entry = iterator.next();
if (!entry.getKey().equals(Constant.NEW_FRIENDS_USERNAME)
&& !entry.getKey().equals(Constant.GROUP_USERNAME)
&& !entry.getKey().equals(Constant.CHAT_ROOM)
&& !blackList.contains(entry.getKey())){
EMLog.i(TAG, "获取联系人="+entry.getValue());
contactList.add(entry.getValue());
}
}
// 排序
Collections.sort(contactList, new Comparator<User>() { @Override
public int compare(User lhs, User rhs) {
return lhs.getUsername().compareTo(rhs.getUsername());
}
}); // 加入"群聊"和"聊天室"
if(users.get(Constant.CHAT_ROOM) != null)
contactList.add(0, users.get(Constant.CHAT_ROOM));
if(users.get(Constant.GROUP_USERNAME) != null)
contactList.add(0, users.get(Constant.GROUP_USERNAME)); // 把"申请与通知"加入到首位
if(users.get(Constant.NEW_FRIENDS_USERNAME) != null)
contactList.add(0, users.get(Constant.NEW_FRIENDS_USERNAME));
} void hideSoftKeyboard() {
if (getActivity().getWindow().getAttributes().softInputMode !=
WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN) {
if (getActivity().getCurrentFocus() != null)
inputMethodManager.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(),
InputMethodManager.HIDE_NOT_ALWAYS);
}
} @Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if(((MainActivity)getActivity()).isConflict){
outState.putBoolean("isConflict", true);
}else if(((MainActivity)getActivity()).getCurrentAccountRemoved()){
outState.putBoolean(Constant.ACCOUNT_REMOVED, true);
} }
}

上面联系人类中的注冊的监听器使用的就是观察者模式,先看HXSDKHelper.java中的部分代码

public void addSyncGroupListener(HXSyncListener listener) {
if (listener == null) {
return;
}
if (!syncGroupsListeners.contains(listener)) {
syncGroupsListeners.add(listener);
}
} public void removeSyncGroupListener(HXSyncListener listener) {
if (listener == null) {
return;
}
if (syncGroupsListeners.contains(listener)) {
syncGroupsListeners.remove(listener);
}
} public void addSyncContactListener(HXSyncListener listener) {
if (listener == null) {
return;
}
if (!syncContactsListeners.contains(listener)) {
syncContactsListeners.add(listener);
}
} public void removeSyncContactListener(HXSyncListener listener) {
if (listener == null) {
return;
}
if (syncContactsListeners.contains(listener)) {
syncContactsListeners.remove(listener);
}
} public void addSyncBlackListListener(HXSyncListener listener) {
if (listener == null) {
return;
}
if (!syncBlackListListeners.contains(listener)) {
syncBlackListListeners.add(listener);
}
} public void removeSyncBlackListListener(HXSyncListener listener) {
if (listener == null) {
return;
}
if (syncBlackListListeners.contains(listener)) {
syncBlackListListeners.remove(listener);
}
}
public void noitifyGroupSyncListeners(boolean success){
for (HXSyncListener listener : syncGroupsListeners) {
listener.onSyncSucess(success);
}
}
public void notifyContactsSyncListener(boolean success){
for (HXSyncListener listener : syncContactsListeners) {
listener.onSyncSucess(success);
}
}
public void notifyBlackListSyncListener(boolean success){
for (HXSyncListener listener : syncBlackListListeners) {
listener.onSyncSucess(success);
}
}

这部分代码控制着观察者,加入、删除、通知每一个观察者,当群组、好友、黑名单 通过环信server同步到client之后,notify每一个观察者,然后观察者接收到之后,刷新UI。这里就是观察者模式的经典应用!

联系人列表看懂之后,其它的群组界面和回话历史界面就不多说了。

3 聊天界面ChatActivity.java

这个类比較庞大,由于demo里面把单聊和群聊、聊天室都集成到这一个界面中完毕,代码非常庞大。可是不影响终于的集成,直接集成该类就能够实现功能。

不多说。

附上界面:

android-使用环信SDK开发即时通信功能及源代码下载

图一 回话历史界面

android-使用环信SDK开发即时通信功能及源代码下载

图二 通讯录界面好友

android-使用环信SDK开发即时通信功能及源代码下载

图三 设置界面

android-使用环信SDK开发即时通信功能及源代码下载

图四 聊天界面

最后附上源代码下载

其它的就没有什么特别须要指出的地方了,大家假设有什么问题或者疑问。都能够留言交流!

【握手】!


2016年5月17日更新

环信官方站点已经公布IM3.0版本号。

眼下开发的一个app採用的就是IM3.0版本号。

总体界面没发生大的变化,功能也都一样。可是在官方给的demo代码上优化非常多。方便非常多。只是得大概看懂里面的代码。假设是高手的话,半天就应该能集成好环信的即时通信功能。

本文给出的下载链接,是IM2.0版本号。所以假设想要使用IM3.0的版本号的。须要到官网下载。

对于新手来说,环信官网给出的demo是能够直接使用的。人家给出的是完整的app代码。新手就疑惑,不知道该怎样入手集成即时通信功能?

事实上非常easy!

首先,把环信官网给出的依赖包和动态库加入到自己的project中。

眼下官网给出的依赖包和动态库分为包括语音视频通话功能的和不包括语音视频通话功能的。

大家依据自己的APP的功能加入。

然后,把demo里面的聊天界面直接拷贝到自己的功能里面。此时复制进去以后。会出现大量的错误!由于聊天界面关联了非常多demo中的其它类,所以,要把其它类拷贝到自己的project中。

记得不要忘记布局文件、资源图片文件、字符串等等资源文件。 建议在自己的project中。新建一个包专门放环信的类。

由于你要复制的类非常多。大概有二三十个!



最后,向即时通信代码填充数据。主要有几部分:

    1)application类中环信helper类完毕初始化操作。
2)登录app界面做好登录环信server操作。须要登录环信的登录名和password。 这里的环信登录与登录app
不同。APP登录是应用server的用户。用户名和password在应用server。 而登录环信是环信的登录名和password。
须要先注冊到环信server才行。注冊操作能够在应用server提前做好。APP登录应用server的时候顺带着
登录环信server就可以。
3)获取好友信息。这里要分为好友信息的维护是应用server维护还是环信帮助你维护。 这个我就不多说
了。 环信官网有说明。
4)本地维护好友列表和聊天信息里列表。聊天信息列表在环信中已经不让开发人员编辑和改变了。 该功能
已经集成在了依赖的环信的包中了。 好友列表在demo中给出了简单的数据表。 开发人员能够自己依据APP
须要开发和扩展。
5)退出APP。退出APP时务必调用helper类的logout方法。 这样以后,先前登录的用户就从APP上退
出了环信的server。开发人员要注意。我这里说的退出时指APP用户手动退出。不是用户按手机返回button或
者返回主界面button导致APP退出。而是APP中的退出button,当前登录用户退出APP。假设是用户按返回按
钮或回主界面button,返回到手机桌面的,不是必需调用helper类的logout方法。

先说这么多。大家还有什么问题,大家留言交流~~

android-使用环信SDK开发即时通信功能及源代码下载的更多相关文章

  1. 基于环信SDK的IM即时通讯填坑之路&lpar;vue&rpar;

    公司最近使用第三方环信SDK的进行通信聊天,基本已完成.记录下填坑之路 1.可以通过以下方式引用 WebSDK 1.安装 npm install easemob-websdk --save 2. 先 ...

  2. 李洪强iOS开发之-环信02&period;2&lowbar;环信官网下载环信 SDK

    李洪强iOS开发之-环信02.2_环信官网下载环信 SDK 移动客服即时通讯云 iOS SDK 当前版本:V3.1.4 2016-07-08 [ 版本历史 ] | 开发指南 | 知识库 | Demo源 ...

  3. 李洪强iOS开发本人集成环信的经验总结&lowbar;01环信SDK的导入

    李洪强iOS开发本人集成环信的经验总结_01环信SDK的导入 01 - 直接在项目中导入SDK和一些静态库 这个时候,没有错误的编译没有错误的话,就说明SDK已经配置成功 还有一种方法是用cocoap ...

  4. 李洪强iOS开发之-环信02&period;1&lowbar;环信 SDK 2&period;x到3&period;0升级文档

    李洪强iOS开发之-环信02.1_环信 SDK 2.x到3.0升级文档 SDK 2.x 至 3.0 升级指南 环信 SDK 3.0 升级文档 3.0 中的核心类为 EMClient 类,通过 EMCl ...

  5. 环信SDK集成

    利用环信SDK可以实现即时通讯,但在集成的过程中碰到了不少的坑. 注意 选择项目路径,这里以最新版环信demo为例 注意:环信的ChatDemoUI这个demo里边因为研发的同事为了照顾老版本的And ...

  6. 集成IOS 环信SDK

    集成IOS SDK 在您阅读此文档时,我们假定您已经具备了基础的 iOS 应用开发经验,并能够理解相关基础概念. 下载SDK 通过Cocoapods下载地址 不包含实时语音版本SDK(EaseMobC ...

  7. 环信SDK与Apple Watch的结合(1)

    该系列是记录在apple watch上开发IM,用到了最近挺流行的环信IM SDK. 一.先来一段网上随处可查到的信息: 1.两种分辨率 1.65寸 312*390 1.5寸 272*340 2.开发 ...

  8. 环信SDK与Apple Watch的结合(2)

    这一篇主要是介绍怎么拖apple watch上的相关页面,附源码EMWatchOCDemo. 需要在工程中的“EMWatchOCDemo WatchKit App”中进行操作,该文件夹的结构如图 Wa ...

  9. 环信SDK 头像、昵称、表情自定义和群聊设置的实现 一(附源码)

    前言: 环信的SDK在公司的项目中有用到,现在用到的是群聊的部分,这里我们分析总结一下自己对环信给的DEMO大概的拆解一下,说说我们怎么样充分的利用这个demo来写我们所需要的业务.这个也由于篇幅的原 ...

随机推荐

  1. Spring&lowbar;跨项目读取properties文件

    应用背景:工程中有40~50个项目,分为4个模块,分别是核心模块.服务接口模块.服务实现模块.Web模块.其它模块(包括消息队列.quartz任务等).工程中很多配置项都是多个项目共有调用的,所以单独 ...

  2. Javassist之常用API的应用 02

    测试模型代码: package org.study2.JavaSenior.annotation.javassistDemo; /** * @Auther:GongXingRui * @Date:20 ...

  3. django之跨表查询及添加记录

    一:创建表 书籍模型: 书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many);     一本书只应该由一个出版商出 ...

  4. k8s中的api server的ca证书,可以和front proxy ca证书一样么?

    答案是: 绝对不可以! 因为请求先验证的是 --requestheader-client-ca-file CA 然后才是--client-ca-file. . 那获取的用户名就会通不过了. 所以会影响 ...

  5. &lbrack;转载&rsqb;ORA-01502错误成因和解决方法

    检查一下索引状态,我们会注意到索引已经是“UNUSABLE”了.SQL> select index_name,index_type,tablespace_name,table_type,stat ...

  6. 强制ubuntu登陆用户退出

    #skill -KILL -u user1 杀死并注销user1. #skill -CONT -u user1 恢复user1. 在Windows 2003默认情况下,三个以上就远程不了,必须强制登录 ...

  7. Django JSON 时间

    在views.py中导入: from django.core.serializers.json import DjangoJSONEncoder 在返回JSON数据时调用: return HttpRe ...

  8. 用 Angularjs 重构了整个 Raysnote 笔记本前端, v2&period;0 上线

    Raysnote是一个简洁优雅的在线笔记工具,致力于提升笔记书写和阅读的体验. 简洁高效的笔记本管理后台(Angularjs重构) 支持HTML/Markdown两种格式,重点关注和支持Markdow ...

  9. Android GridView异步加载图片和加载大量图片时出现Out Of Memory问题

    我们在使用GridView或者ListView时,通常会遇到两个棘手的问题: 1.每个Item获取的数据所用的时间太长会导致程序长时间黑屏,更甚会导致程序ANR,也就是Application No R ...

  10. Oracle Study之-AIX6&period;1构建Oracle 10gR2 RAC&lpar;4&rpar;

    Oracle Study之-AIX6.1构建Oracle 10gR2 RAC(4) 一.安装CRS补丁 在安装CRS之前,须要安装补丁p6718715_10203_AIX64-5L,否则在安装时会出现 ...