前段时间由于项目需要,了解一下环信即时通讯,然后自己通过查资料写了一个基于环信的单聊demo,一下是源码,希望可以帮助到需要的小伙伴。
首先,我们要去环信官网注册账号,这个我就不多说了,注册完登录,创建应用,新建两个测试IM用户,


这里主要用到的是应用标示(Appkey)


好了,在环信官网下载对应的sdk,这个不多说了,最好下载一个文档,里面讲的很详细的。
好了,一下是源码

AppManager.java

public class AppManager {private static Stack<Activity> mActivityStack;private static AppManager mAppManager;private AppManager() {}/*** 单一实例*/public static AppManager getInstance() {if (mAppManager == null) {mAppManager = new AppManager();}return mAppManager;}/*** 添加Activity*/public void addActivity(Activity activity) {if (mActivityStack == null) {mActivityStack = new Stack<Activity>();}mActivityStack.add(activity);}/*** 获取栈顶Activity*/public Activity getTopActivity() {Activity activity = mActivityStack.lastElement();return activity;}/*** 结束栈顶Activity*/public void killTopActivity() {Activity activity = mActivityStack.lastElement();killActivity(activity);}/*** 结束指定的Activity*/public void killActivity(Activity activity) {if (activity != null) {mActivityStack.remove(activity);activity.finish();activity = null;}}/*** 结束指定类名的Activity*/public void killActivity(Class<?> cls) {for (Activity activity : mActivityStack) {if (activity.getClass().equals(cls)) {killActivity(activity);}}}/*** 结束所有Activity*/public void killAllActivity() {for (int i = 0, size = mActivityStack.size(); i < size; i++) {if (null != mActivityStack.get(i)) {mActivityStack.get(i).finish();}}mActivityStack.clear();}/*** 退出应用程序*/public void AppExit(Context context) {try {killAllActivity();ActivityManager activityMgr = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);activityMgr.restartPackage(context.getPackageName());System.exit(0);} catch (Exception e) {}}
}

BaseActivity.java

public abstract class BaseActivity extends Activity {protected Context context = null;protected BaseApplication mApplication;protected Handler mHandler;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);mApplication = (BaseApplication) getApplication();AppManager.getInstance().addActivity(this);
//      check netwotkcontext = this;}@Overridepublic void onBackPressed() {// TODO Auto-generated method stubsuper.onBackPressed();}@Overrideprotected void onDestroy() {// TODO Auto-generated method stubsuper.onDestroy();}@Overrideprotected void onPause() {// TODO Auto-generated method stubsuper.onPause();}@Overrideprotected void onResume() {// TODO Auto-generated method stubsuper.onResume();}}

BaseApplication.java

public class BaseApplication extends Application {private static final String TAG = BaseApplication.class.getSimpleName();private static BaseApplication mInstance = null;@Overridepublic void onConfigurationChanged(Configuration newConfig) {super.onConfigurationChanged(newConfig);}/** (non-Javadoc)* * @see android.app.Application#onCreate()*/@Overridepublic void onCreate() {// TODO Auto-generated method stubsuper.onCreate();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("com.xmliu.imsample")) {Log.e(TAG, "enter the service process!");// "com.easemob.chatuidemo"为demo的包名,换到自己项目中要改成自己包名// 则此application::onCreate 是被service 调用的,直接返回return;}//      EMChat.getInstance().setAutoLogin(false);EMChat.getInstance().init(getApplicationContext());// 在做代码混淆的时候需要设置成falseEMChat.getInstance().setDebugMode(true);initHXOptions();mInstance = this;}protected void initHXOptions() {Log.d(TAG, "init HuanXin Options");// 获取到EMChatOptions对象EMChatOptions options = EMChatManager.getInstance().getChatOptions();// 默认添加好友时,是不需要验证的true,改成需要验证falseoptions.setAcceptInvitationAlways(false);// 默认环信是不维护好友关系列表的,如果app依赖环信的好友关系,把这个属性设置为trueoptions.setUseRoster(true);options.setNumberOfMessagesLoaded(1);}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) {CharSequence c = pm.getApplicationLabel(pm.getApplicationInfo(info.processName,PackageManager.GET_META_DATA));// Log.d("Process", "Id: "+ info.pid +" ProcessName: "+// info.processName +"  Label: "+c.toString());// processName = c.toString();processName = info.processName;return processName;}} catch (Exception e) {// Log.d("Process", "Error>> :"+ e.toString());}}return processName;}@Overridepublic void onLowMemory() {// TODO Auto-generated method stubsuper.onLowMemory();Log.i(TAG, "onLowMemory");}@Overridepublic void onTerminate() {// TODO Auto-generated method stubLog.i(TAG, "onTerminate");super.onTerminate();}public static BaseApplication getInstance() {return mInstance;}}

ChatListAdapter.java

public class ChatListAdapter extends BaseAdapter {Context mContext;List<ChatListData> mListData;public ChatListAdapter(Context mContext, List<ChatListData> mListData) {super();this.mContext = mContext;this.mListData = mListData;}@Overridepublic int getCount() {// TODO Auto-generated method stubreturn mListData.size();}@Overridepublic Object getItem(int arg0) {// TODO Auto-generated method stubreturn null;}@Overridepublic long getItemId(int arg0) {// TODO Auto-generated method stubreturn 0;}@Overridepublic View getView(int index, View cView, ViewGroup arg2) {// TODO Auto-generated method stubHolder holder;if (cView == null) {holder = new Holder();cView = LayoutInflater.from(mContext).inflate(R.layout.chat_listview_item, null);holder.rAvatar = (Button) cView.findViewById(R.id.listview_item_receive_avatar);holder.rContent = (TextView) cView.findViewById(R.id.listview_item_receive_content);holder.chatTime = (TextView) cView.findViewById(R.id.listview_item_time);holder.sContent = (TextView) cView.findViewById(R.id.listview_item_send_content);holder.sAvatar = (Button) cView.findViewById(R.id.listview_item_send_avatar);holder.sName = (TextView) cView.findViewById(R.id.name1);holder.sName1 = (TextView) cView.findViewById(R.id.name2);cView.setTag(holder);} else {holder = (Holder) cView.getTag();}holder.chatTime.setVisibility(View.GONE);if (mListData.get(index).getType() == 2) {holder.rAvatar.setVisibility(View.VISIBLE);holder.rContent.setVisibility(View.VISIBLE);holder.sName.setVisibility(View.VISIBLE);holder.sName.setText("您的朋友说:");holder.sContent.setVisibility(View.GONE);holder.sAvatar.setVisibility(View.GONE);holder.sName1.setVisibility(View.GONE);} else if (mListData.get(index).getType() == 1) {holder.rAvatar.setVisibility(View.GONE);holder.sName.setVisibility(View.GONE);holder.rContent.setVisibility(View.GONE);holder.sContent.setVisibility(View.VISIBLE);holder.sAvatar.setVisibility(View.VISIBLE);holder.sName1.setVisibility(View.VISIBLE);holder.sName1.setText("我");}holder.chatTime.setText(mListData.get(index).getChatTime());holder.rContent.setText(mListData.get(index).getReceiveContent());holder.sContent.setText(mListData.get(index).getSendContent());return cView;}class Holder {Button rAvatar;TextView rContent;TextView chatTime;TextView sContent;TextView sName;TextView sName1;Button sAvatar;}
}

FriendListAdapter.java

public class FriendListAdapter extends BaseAdapter {Context mContext;List<String> mListData;public FriendListAdapter(Context mContext, List<String> mListData) {super();this.mContext = mContext;this.mListData = mListData;}@Overridepublic int getCount() {// TODO Auto-generated method stubreturn mListData.size();}@Overridepublic Object getItem(int arg0) {// TODO Auto-generated method stubreturn null;}@Overridepublic long getItemId(int arg0) {// TODO Auto-generated method stubreturn 0;}@Overridepublic View getView(int index, View cView, ViewGroup arg2) {// TODO Auto-generated method stubFHolder holder;if (cView == null) {holder = new FHolder();cView = LayoutInflater.from(mContext).inflate(R.layout.friend_listview_item, null);holder.name = (TextView) cView.findViewById(R.id.friend_listview_name);cView.setTag(holder);} else {holder = (FHolder) cView.getTag();}holder.name.setText(mListData.get(index));return cView;}class FHolder {TextView name;}
}

ChatListData.java

public class ChatListData {String receiveAvatar;String receiveContent;String chatTime;String sendAvatar;String sendContent;/*** 1 发送; 2接收*/int type;/*** 1 发送; 2接收*/public int getType() {return type;}/*** 1 发送; 2接收*/public void setType(int type) {this.type = type;}public String getReceiveAvatar() {return receiveAvatar;}public void setReceiveAvatar(String receiveAvatar) {this.receiveAvatar = receiveAvatar;}public String getReceiveContent() {return receiveContent;}public void setReceiveContent(String receiveContent) {this.receiveContent = receiveContent;}public String getChatTime() {return chatTime;}public void setChatTime(String chatTime) {this.chatTime = chatTime;}public String getSendAvatar() {return sendAvatar;}public void setSendAvatar(String sendAvatar) {this.sendAvatar = sendAvatar;}public String getSendContent() {return sendContent;}public void setSendContent(String sendContent) {this.sendContent = sendContent;}}

ChatListActivity.java

public class ChatListActivity extends BaseActivity {private EditText contentET;private TextView topNameTV;private Button sendBtn;private NewMessageBroadcastReceiver msgReceiver;private ListView mListView;private List<ChatListData> mListData = new ArrayList<ChatListData>();private ChatListAdapter mAdapter;private InputMethodManager imm;private String receiveName = null;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.activity_chat_main);mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {// TODO Auto-generated method stubsuper.handleMessage(msg);switch (msg.what) {case 0x00001:imm.hideSoftInputFromWindow(contentET.getApplicationWindowToken(), 0); // 隐藏键盘mAdapter.notifyDataSetChanged(); // 刷新聊天列表mListView.setSelection(mListData.size()); // 跳转到listview最底部contentET.setText(""); // 清空发送内容break;default:break;}}};receiveName = this.getIntent().getStringExtra("userid");initView();topNameTV.setText(receiveName);// 只有注册了广播才能接收到新消息,目前离线消息,在线消息都是走接收消息的广播(离线消息目前无法监听,在登录以后,接收消息广播会执行一次拿到所有的离线消息)msgReceiver = new NewMessageBroadcastReceiver();IntentFilter intentFilter = new IntentFilter(EMChatManager.getInstance().getNewMessageBroadcastAction());intentFilter.setPriority(3);registerReceiver(msgReceiver, intentFilter);imm = (InputMethodManager) contentET.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);mAdapter = new ChatListAdapter(ChatListActivity.this, mListData);mListView.setAdapter(mAdapter);initEvent();}private void initView() {contentET = (EditText) findViewById(R.id.chat_content);topNameTV = (TextView) findViewById(R.id.chat_list_name);sendBtn = (Button) findViewById(R.id.chat_send_btn);mListView = (ListView) findViewById(R.id.chat_listview);}private void initEvent() {// TODO Auto-generated method stubsendBtn.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {// TODO Auto-generated method stubsendMsg();}});contentET.setOnKeyListener(new OnKeyListener() {@Overridepublic boolean onKey(View arg0, int keycode, KeyEvent arg2) {// TODO Auto-generated method stubif (keycode == KeyEvent.KEYCODE_ENTER&& arg2.getAction() == KeyEvent.ACTION_DOWN) {sendMsg();return true;}return false;}});}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);// 设置消息bodyTextMessageBody txtBody = new TextMessageBody(content);message.addBody(txtBody);// 设置接收人message.setReceipt(username);// 把消息加入到此会话对象中conversation.addMessage(message);// 发送消息EMChatManager.getInstance().sendMessage(message, new EMCallBack() {@Overridepublic void onError(int arg0, String arg1) {// TODO Auto-generated method stubLog.i("TAG", "消息发送失败");}@Overridepublic void onProgress(int arg0, String arg1) {// TODO Auto-generated method stubLog.i("TAG", "正在发送消息");}@Overridepublic void onSuccess() {// TODO Auto-generated method stubLog.i("TAG", "消息发送成功");ChatListData data = new ChatListData();data.setSendContent(content);data.setType(1);mListData.add(data);mHandler.sendEmptyMessage(0x00001);}});}private class NewMessageBroadcastReceiver extends BroadcastReceiver {@Overridepublic 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 idif (message.getChatType() == ChatType.GroupChat) {username = message.getTo();}if (!username.equals(username)) {// 消息不是发给当前会话,returnreturn;}}}@Overrideprotected void onDestroy() {// TODO Auto-generated method stubsuper.onDestroy();unregisterReceiver(msgReceiver);}private void sendMsg() {String content = contentET.getText().toString().trim();if (TextUtils.isEmpty(content)) {Toast.makeText(getApplicationContext(), "请输入发送的内容",Toast.LENGTH_SHORT).show();} else {sendMessageHX(receiveName, content);}}}

ChatLoginActivity.java

public class ChatLoginActivity extends BaseActivity {private EditText mUsernameET;private EditText mPasswordET;private TextView mPasswordForgetTV;private Button mSigninBtn;private TextView mSignupTV;private CheckBox mPasswordCB;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.activity_chat_login);mUsernameET = (EditText) findViewById(R.id.chat_login_username);mPasswordET = (EditText) findViewById(R.id.chat_login_password);mPasswordForgetTV = (TextView) findViewById(R.id.chat_login_forget_password);mSigninBtn = (Button) findViewById(R.id.chat_login_signin_btn);mSignupTV = (TextView) findViewById(R.id.chat_login_signup);mPasswordCB = (CheckBox) findViewById(R.id.chat_login_password_checkbox);if (EMChat.getInstance().isLoggedIn()) {Log.d("TAG", "已经登陆过");EMGroupManager.getInstance().loadAllGroups();EMChatManager.getInstance().loadAllConversations();startActivity(new Intent(ChatLoginActivity.this,MainActivity.class));}mPasswordCB.setOnCheckedChangeListener(new OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(CompoundButton arg0, boolean arg1) {// TODO Auto-generated method stubif (arg1) {mPasswordCB.setChecked(true);//动态设置密码是否可见mPasswordET.setTransformationMethod(HideReturnsTransformationMethod.getInstance());} else {mPasswordCB.setChecked(false);mPasswordET.setTransformationMethod(PasswordTransformationMethod.getInstance());}}});mSigninBtn.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {// TODO Auto-generated method stubfinal String userName = mUsernameET.getText().toString().trim();final String password = mPasswordET.getText().toString().trim();if (TextUtils.isEmpty(userName)) {Toast.makeText(getApplicationContext(), "请输入用户名",Toast.LENGTH_SHORT).show();} else if (TextUtils.isEmpty(password)) {Toast.makeText(getApplicationContext(), "请输入密码",Toast.LENGTH_SHORT).show();} else {EMChatManager.getInstance().login(userName, password,new EMCallBack() {// 回调@Overridepublic void onSuccess() {runOnUiThread(new Runnable() {public void run() {EMGroupManager.getInstance().loadAllGroups();EMChatManager.getInstance().loadAllConversations();Log.d("main", "登陆聊天服务器成功!");Toast.makeText(getApplicationContext(),"登陆成功", Toast.LENGTH_SHORT).show();startActivity(new Intent(ChatLoginActivity.this,MainActivity.class));
//                                          mApplication.mSharedPreferences
//                                                  .edit()
//                                                  .putString("loginName",
//                                                          userName).commit();}});}@Overridepublic void onProgress(int progress,String status) {}@Overridepublic void onError(int code, String message) {if (code == -1005) {message = "用户名或密码错误";}final String msg = message;runOnUiThread(new Runnable() {public void run() {Log.d("main", "登陆聊天服务器失败!");Toast.makeText(getApplicationContext(),msg, Toast.LENGTH_SHORT).show();}});}});}}});mSignupTV.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {// TODO Auto-generated method stubstartActivity(new Intent(ChatLoginActivity.this,ChatRegisterActivity.class));}});}@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) {if (keyCode == KeyEvent.KEYCODE_BACK) {new AlertDialog.Builder(ChatLoginActivity.this).setTitle("应用提示").setMessage("确定要退出"+ getResources().getString(R.string.app_name) + "客户端吗?").setPositiveButton("确定",new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog,int which) {AppManager.getInstance().AppExit(ChatLoginActivity.this);ChatLoginActivity.this.finish();}}).setNegativeButton("取消",new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog,int whichButton) {}}).show();}return super.onKeyDown(keyCode, event);}
}

ChatRegisterActivity.java

public class ChatRegisterActivity extends BaseActivity {private EditText mUsernameET;private EditText mPasswordET;private EditText mCodeET;private Button mSignupBtn;private Handler mHandler;private CheckBox mPasswordCB;private TextView mBackTV;private ImageView mCodeIV;private String currCode;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.activity_chat_register);mHandler = new Handler() {public void handleMessage(android.os.Message msg) {switch (msg.what) {case 1000:Toast.makeText(getApplicationContext(), "注册成功",Toast.LENGTH_SHORT).show();break;case 1001:Toast.makeText(getApplicationContext(), "网络异常,请检查网络!",Toast.LENGTH_SHORT).show();break;case 1002:Toast.makeText(getApplicationContext(), "用户已存在!",Toast.LENGTH_SHORT).show();break;case 1003:Toast.makeText(getApplicationContext(), "注册失败,无权限",Toast.LENGTH_SHORT).show();break;case 1004:Toast.makeText(getApplicationContext(),"注册失败: " + (String) msg.obj, Toast.LENGTH_SHORT).show();break;default:break;}};};mUsernameET = (EditText) findViewById(R.id.chat_register_username);mPasswordET = (EditText) findViewById(R.id.chat_register_password);mCodeET = (EditText) findViewById(R.id.chat_register_code);mSignupBtn = (Button) findViewById(R.id.chat_register_signup_btn);mPasswordCB = (CheckBox) findViewById(R.id.chat_register_password_checkbox);mBackTV = (TextView) findViewById(R.id.chat_register_back);mCodeIV = (ImageView) findViewById(R.id.chat_register_password_code);mCodeIV.setImageBitmap(IdentifyCode.getInstance().createBitmap());currCode = IdentifyCode.getInstance().getCode();mCodeIV.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {// TODO Auto-generated method stubmCodeIV.setImageBitmap(IdentifyCode.getInstance().createBitmap());currCode = IdentifyCode.getInstance().getCode();Log.i("TAG", "currentCode==>" + currCode);}});mBackTV.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {// TODO Auto-generated method stubfinish();}});mPasswordCB.setOnCheckedChangeListener(new OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(CompoundButton arg0, boolean arg1) {// TODO Auto-generated method stubif (arg1) {mPasswordCB.setChecked(true);mPasswordET.setTransformationMethod(HideReturnsTransformationMethod.getInstance());} else {mPasswordCB.setChecked(false);mPasswordET.setTransformationMethod(PasswordTransformationMethod.getInstance());}}});mSignupBtn.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {// TODO Auto-generated method stubfinal String userName = mUsernameET.getText().toString().trim();final String password = mPasswordET.getText().toString().trim();final String code = mCodeET.getText().toString().trim();if (TextUtils.isEmpty(userName)) {Toast.makeText(getApplicationContext(), "请输入用户名",Toast.LENGTH_SHORT).show();} else if (TextUtils.isEmpty(password)) {Toast.makeText(getApplicationContext(), "请输入密码",Toast.LENGTH_SHORT).show();} else if (TextUtils.isEmpty(code)) {Toast.makeText(getApplicationContext(), "请输入验证码",Toast.LENGTH_SHORT).show();} else if (!code.equals(currCode.toLowerCase())) {Toast.makeText(getApplicationContext(), "验证码输入不正确",Toast.LENGTH_SHORT).show();} else {new Thread(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubtry {// 调用sdk注册方法EMChatManager.getInstance().createAccountOnServer(userName,password);mHandler.sendEmptyMessage(1000);} catch (final EaseMobException e) {// 注册失败Log.i("TAG", "getErrorCode:" + e.getErrorCode());int errorCode = e.getErrorCode();if (errorCode == EMError.NONETWORK_ERROR) {mHandler.sendEmptyMessage(1001);} else if (errorCode == EMError.USER_ALREADY_EXISTS) {mHandler.sendEmptyMessage(1002);} else if (errorCode == EMError.UNAUTHORIZED) {mHandler.sendEmptyMessage(1003);} else {Message msg = Message.obtain();msg.what = 1004;msg.obj = e.getMessage();mHandler.sendMessage(msg);}}}}).start();}}});}
}

MainActivity.java

public class MainActivity extends BaseActivity {private ListView mListView;private Button mAddBtn;private Button logoutBtn;private View addView;private EditText mIdET;private EditText mReasonET;private TextView mUserTV;private TextView mGoTV;private FriendListAdapter mAdapter;private List<String> userList = new ArrayList<String>();/* 常量 */private final int CODE_ADD_FRIEND = 0x00001;@Overrideprotected void onDestroy() {// TODO Auto-generated method stubsuper.onDestroy();}@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.activity_chat_friends);mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {// TODO Auto-generated method stubsuper.handleMessage(msg);switch (msg.what) {case CODE_ADD_FRIEND:Toast.makeText(getApplicationContext(), "请求发送成功,等待对方验证",Toast.LENGTH_SHORT).show();break;default:break;}}};EMContactManager.getInstance().setContactListener(new MyContactListener());EMChat.getInstance().setAppInited();mListView = (ListView) findViewById(R.id.chat_listview);mAddBtn = (Button) findViewById(R.id.chat_add_btn);mUserTV = (TextView) findViewById(R.id.current_user);mGoTV = (TextView) findViewById(R.id.friend_list_go);logoutBtn = (Button) findViewById(R.id.chat_logout_btn);mUserTV.setText(EMChatManager.getInstance().getCurrentUser());initList();mAddBtn.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {// TODO Auto-generated method stubaddView = LayoutInflater.from(MainActivity.this).inflate(R.layout.chat_add_friends, null);mIdET = (EditText) addView.findViewById(R.id.chat_add_friend_id);mReasonET = (EditText) addView.findViewById(R.id.chat_add_friend_reason);new AlertDialog.Builder(MainActivity.this).setTitle("添加好友").setView(addView).setPositiveButton("确定",new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog,int which) {dialog.dismiss();String idStr = mIdET.getText().toString().trim();String reasonStr = mReasonET.getText().toString().trim();try {EMContactManager.getInstance().addContact(idStr,reasonStr);mHandler.sendEmptyMessage(CODE_ADD_FRIEND);} catch (EaseMobException e) {// TODO Auto-generated catch blocke.printStackTrace();Log.i("TAG", "addContacterrcode==>"+ e.getErrorCode());}// 需异步处理}}).setNegativeButton("取消",new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog,int whichButton) {dialog.dismiss();}}).create().show();}});logoutBtn.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {// TODO Auto-generated method stubshowLogoutDialog();}});mListView.setOnItemClickListener(new OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {// TODO Auto-generated method stubstartActivity(new Intent(MainActivity.this,ChatListActivity.class).putExtra("userid",userList.get(arg2)));}});mListView.setOnItemLongClickListener(new OnItemLongClickListener() {@Overridepublic boolean onItemLongClick(AdapterView<?> arg0, View arg1,int arg2, long arg3) {// TODO Auto-generated method stubshowDeleteDialog(userList.get(arg2));return true;}});}private void initList() {try {userList.clear();userList = EMContactManager.getInstance().getContactUserNames();mAdapter = new FriendListAdapter(MainActivity.this, userList);mListView.setAdapter(mAdapter);} catch (EaseMobException e1) {// TODO Auto-generated catch blocke1.printStackTrace();Log.i("TAG", "usernames errcode==>" + e1.getErrorCode());Log.i("TAG", "usernames errcode==>" + e1.getMessage());}// 需异步执行}private class MyContactListener implements EMContactListener {@Overridepublic void onContactAgreed(String username) {// 好友请求被同意Log.i("TAG", "onContactAgreed==>" + username);// 提示有新消息EMNotifier.getInstance(getApplicationContext()).notifyOnNewMsg();Toast.makeText(getApplicationContext(), username + "同意了你的好友请求",Toast.LENGTH_SHORT).show();}@Overridepublic void onContactRefused(String username) {// 好友请求被拒绝Log.i("TAG", "onContactRefused==>" + username);}@Overridepublic void onContactInvited(String username, String reason) {// 收到好友添加请求Log.i("TAG", username + "onContactInvited==>" + reason);showAgreedDialog(username, reason);EMNotifier.getInstance(getApplicationContext()).notifyOnNewMsg();}@Overridepublic void onContactDeleted(List<String> usernameList) {// 好友被删除时回调此方法Log.i("TAG", "usernameListDeleted==>" + usernameList.size());}@Overridepublic void onContactAdded(List<String> usernameList) {// 添加了新的好友时回调此方法for (String str : usernameList) {Log.i("TAG", "usernameListAdded==>" + str);}}}@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) {if (keyCode == KeyEvent.KEYCODE_BACK) {showExitDialog();}return super.onKeyDown(keyCode, event);}private void showLogoutDialog() {new AlertDialog.Builder(MainActivity.this).setTitle("应用提示").setMessage("确定要注销" + EMChatManager.getInstance().getCurrentUser()+ "用户吗?").setPositiveButton("确定", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {// EMChatManager.getInstance().logout();logout(new EMCallBack() {@Overridepublic void onSuccess() {// TODO Auto-generated method stubstartActivity(new Intent(MainActivity.this,ChatLoginActivity.class));}@Overridepublic void onProgress(int arg0, String arg1) {// TODO Auto-generated method stub}@Overridepublic void onError(int arg0, String arg1) {// TODO Auto-generated method stub}});}}).setNegativeButton("取消", new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog, int whichButton) {}}).show();}public void logout(final EMCallBack callback) {// setPassword(null);EMChatManager.getInstance().logout(new EMCallBack() {@Overridepublic void onSuccess() {// TODO Auto-generated method stubif (callback != null) {callback.onSuccess();}}@Overridepublic void onError(int code, String message) {// TODO Auto-generated method stub}@Overridepublic void onProgress(int progress, String status) {// TODO Auto-generated method stubif (callback != null) {callback.onProgress(progress, status);}}});}private void showAgreedDialog(final String user, String reason) {new AlertDialog.Builder(MainActivity.this).setTitle("应用提示").setMessage("用户 " + user + " 想要添加您为好友,是否同意?\n" + "验证信息:" + reason).setPositiveButton("同意", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {try {EMChatManager.getInstance().acceptInvitation(user);initList();} catch (EaseMobException e) {// TODO Auto-generated catch blocke.printStackTrace();Log.i("TAG","showAgreedDialog1==>" + e.getErrorCode());}}}).setNegativeButton("拒绝", new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog, int whichButton) {try {EMChatManager.getInstance().refuseInvitation(user);} catch (EaseMobException e) {// TODO Auto-generated catch blocke.printStackTrace();Log.i("TAG","showAgreedDialog2==>" + e.getErrorCode());}}}).setNeutralButton("忽略", new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog, int whichButton) {dialog.dismiss();}}).show();}private void showDeleteDialog(final String user) {new AlertDialog.Builder(MainActivity.this).setTitle("应用提示").setMessage("确定删除好友  " + user + " 吗?\n").setPositiveButton("确定", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {try {EMContactManager.getInstance().deleteContact(user);initList();} catch (EaseMobException e) {// TODO Auto-generated catch blocke.printStackTrace();Log.i("TAG","showAgreedDialog1==>" + e.getErrorCode());}}}).setNegativeButton("取消", new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog, int whichButton) {dialog.dismiss();}}).show();}private void showExitDialog() {new AlertDialog.Builder(MainActivity.this).setTitle("应用提示").setMessage("确定要退出" + getResources().getString(R.string.app_name)+ "客户端吗?").setPositiveButton("确定", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {AppManager.getInstance().AppExit(MainActivity.this);MainActivity.this.finish();}}).setNegativeButton("取消", new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog, int whichButton) {}}).show();}}

IdentifyCode.java

public class IdentifyCode {private static final char[] CHARS = { '2', '3', '4', '5', '6', '7', '8','9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'l', 'm','n', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A','B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N','P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };private static IdentifyCode bmpCode;public static IdentifyCode getInstance() {if (bmpCode == null)bmpCode = new IdentifyCode();return bmpCode;}// default settingsprivate static final int DEFAULT_CODE_LENGTH = 3;private static final int DEFAULT_FONT_SIZE = 25;private static final int DEFAULT_LINE_NUMBER = 2;private static final int BASE_PADDING_LEFT = 5, RANGE_PADDING_LEFT = 15,BASE_PADDING_TOP = 15, RANGE_PADDING_TOP = 20;private static final int DEFAULT_WIDTH = 60, DEFAULT_HEIGHT = 40;// settings decided by the layout xml// canvas width and heightprivate int width = DEFAULT_WIDTH, height = DEFAULT_HEIGHT;// random word space and pading_topprivate int base_padding_left = BASE_PADDING_LEFT,range_padding_left = RANGE_PADDING_LEFT,base_padding_top = BASE_PADDING_TOP,range_padding_top = RANGE_PADDING_TOP;// number of chars, lines; font sizeprivate int codeLength = DEFAULT_CODE_LENGTH,line_number = DEFAULT_LINE_NUMBER, font_size = DEFAULT_FONT_SIZE;// variablesprivate String code;private int padding_left, padding_top;private Random random = new Random();// 验证码图�?public Bitmap createBitmap() {padding_left = 0;Bitmap bp = Bitmap.createBitmap(width, height, Config.ARGB_8888);Canvas c = new Canvas(bp);code = createCode();c.drawColor(Color.WHITE);Paint paint = new Paint();paint.setTextSize(font_size);for (int i = 0; i < code.length(); i++) {randomTextStyle(paint);randomPadding();c.drawText(code.charAt(i) + "", padding_left, padding_top, paint);}for (int i = 0; i < line_number; i++) {drawLine(c, paint);}c.save(Canvas.ALL_SAVE_FLAG);// 保存c.restore();//return bp;}public String getCode() {return code;}// 验证�?private String createCode() {StringBuilder buffer = new StringBuilder();for (int i = 0; i < codeLength; i++) {buffer.append(CHARS[random.nextInt(CHARS.length)]);}return buffer.toString();}private void drawLine(Canvas canvas, Paint paint) {int color = randomColor();int startX = random.nextInt(width);int startY = random.nextInt(height);int stopX = random.nextInt(width);int stopY = random.nextInt(height);paint.setStrokeWidth(1);paint.setColor(color);canvas.drawLine(startX, startY, stopX, stopY, paint);}private int randomColor() {return randomColor(1);}private int randomColor(int rate) {int red = random.nextInt(256) / rate;int green = random.nextInt(256) / rate;int blue = random.nextInt(256) / rate;return Color.rgb(red, green, blue);}private void randomTextStyle(Paint paint) {int color = randomColor();paint.setColor(color);paint.setFakeBoldText(random.nextBoolean()); // true为粗体,false为非粗体float skewX = random.nextInt(11) / 10;skewX = random.nextBoolean() ? skewX : -skewX;paint.setTextSkewX(skewX); // float类型参数,负数表示右斜,整数左斜// paint.setUnderlineText(true); //true为下划线,false为非下划线?// paint.setStrikeThruText(true); //true为删除线,false为非删除线?}private void randomPadding() {padding_left += base_padding_left + random.nextInt(range_padding_left);padding_top = base_padding_top + random.nextInt(range_padding_top);}
}

布局文件就相对简单很多了,登录页面很简单,还是贴出来吧。
activity_chat_login.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><TextView
        android:id="@+id/chat_login_title"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="#131313"android:gravity="center"android:paddingBottom="10dp"android:paddingTop="10dp"android:text="登录"android:textColor="#fff" /><LinearLayout
        android:layout_width="match_parent"android:layout_height="match_parent"android:layout_weight="1"android:background="#CAFFFF"android:orientation="vertical"android:paddingBottom="30dp"android:paddingLeft="30dp"android:paddingRight="30dp"android:paddingTop="60dp" ><LinearLayout
            android:layout_width="match_parent"android:layout_height="wrap_content"android:background="#131313"android:orientation="vertical" ><EditText
                android:id="@+id/chat_login_username"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_margin="5dp"android:background="#00000000"android:drawableLeft="@drawable/login_user"android:drawablePadding="5dp"android:ems="10"android:hint="用户名"android:inputType="textPersonName"android:textColor="#fff"android:textSize="12sp" /><View
                android:id="@+id/textView2"android:layout_width="match_parent"android:layout_height="1dp"android:background="#000000" /><LinearLayout
                android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal" ><EditText
                    android:id="@+id/chat_login_password"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_margin="5dp"android:layout_weight="1"android:background="#00000000"android:drawableLeft="@drawable/login_password"android:drawablePadding="5dp"android:ems="10"android:hint="密码"android:inputType="textPassword"android:textColor="#fff"android:textSize="12sp" /><CheckBox
                    android:id="@+id/chat_login_password_checkbox"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_vertical"android:layout_marginRight="5dp"android:button="@drawable/password_checkbox" /></LinearLayout></LinearLayout><Button
            android:id="@+id/chat_login_signin_btn"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="20dp"android:background="#359D90"android:paddingBottom="10dp"android:paddingTop="10dp"android:text="登录"android:textColor="#fff" /><RelativeLayout
            android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="10dp"android:orientation="horizontal" ><TextView
                android:id="@+id/chat_login_signup0"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text=""android:textColor="#5D5D5D"android:textSize="12sp" /><TextView
                android:id="@+id/chat_login_signup"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_toRightOf="@id/chat_login_signup0"android:text="注册用户"android:textColor="#6F6F6F"android:textSize="12sp"android:textStyle="bold" /><TextView
                android:id="@+id/chat_login_forget_password"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentRight="true"android:text="忘记密码"android:textColor="#5D5D5D"android:textSize="12sp" /></RelativeLayout></LinearLayout></LinearLayout>

好友列表页
activity_chat_friends.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><RelativeLayout
        android:layout_width="match_parent"android:layout_height="wrap_content"android:background="#359D90"android:orientation="horizontal"android:paddingBottom="5dp"android:paddingTop="5dp" ><TextView
            android:id="@+id/current_user"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:text="我的好友"android:textColor="#fff" /><Button
            android:id="@+id/chat_logout_btn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentRight="true"android:layout_marginRight="5dp"android:background="@drawable/chat_logout_icon" /></RelativeLayout><TextView
        android:id="@+id/friend_list_go"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_margin="10dp"android:textStyle="bold|italic"android:textColor="#000fff"android:text="好友列表" /><View
        android:layout_width="match_parent"android:layout_height="1px"android:layout_marginTop="5dp"android:background="#DDDDDD" /><ListView
        android:id="@+id/chat_listview"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_weight="1"android:scrollbars="none" /><Button
        android:id="@+id/chat_add_btn"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_gravity="bottom"android:background="@drawable/send_btn_bg"android:paddingBottom="12dp"android:paddingLeft="10dp"android:paddingRight="10dp"android:paddingTop="12dp"android:text="Add Friends"android:textColor="#fff" /></LinearLayout>

聊天页面
activity_chat_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><RelativeLayout
        android:layout_width="match_parent"android:layout_height="wrap_content"android:background="#359D90"android:orientation="horizontal"android:paddingBottom="10dp"android:paddingTop="10dp" ><TextView
            android:id="@+id/chat_list_name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:text="OnePiece Chat"android:textColor="#fff" /></RelativeLayout><ListView
        android:id="@+id/chat_listview"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="10dp"android:scrollbars="none"android:layout_weight="1"android:divider="@null"android:dividerHeight="@null" /><LinearLayout
        android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginBottom="5dp"android:layout_marginTop="10dp"android:orientation="horizontal" ><EditText
            android:id="@+id/chat_content"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="5dp"android:layout_weight="3"android:background="@drawable/edit_btn_bg"android:ems="10"android:imeOptions="actionSend"android:hint="send what ?"android:paddingBottom="10dp"android:paddingLeft="5dp"android:paddingTop="10dp" ></EditText><Button
            android:id="@+id/chat_send_btn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="bottom"android:layout_marginLeft="5dp"android:layout_marginRight="5dp"android:layout_weight="1"android:background="@drawable/send_btn_bg"android:paddingBottom="12dp"android:paddingLeft="10dp"android:paddingRight="10dp"android:paddingTop="12dp"android:text="Send"android:textColor="#fff" /></LinearLayout></LinearLayout>

chat_listview_item.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="horizontal"android:paddingBottom="5dp"android:paddingTop="5dp"tools:context=".ChatListActivity" ><RelativeLayout
        android:id="@+id/rl01"android:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_marginLeft="10dp" ><Button
            android:id="@+id/listview_item_receive_avatar"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentLeft="true"android:layout_alignParentTop="true"android:background="@drawable/user_icon_l"android:focusable="false" /><TextView
            android:id="@+id/name1"style="@style/chat_text_name_style"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentLeft="true"android:layout_below="@id/listview_item_receive_avatar"android:layout_toLeftOf="@id/name1"android:textSize="8dp" /><TextView
            android:id="@+id/listview_item_receive_content"style="@style/chat_content_date_style"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="10dp"android:layout_toRightOf="@id/listview_item_receive_avatar"android:background="@drawable/chatfrom_bg" /></RelativeLayout><TextView
        android:id="@+id/listview_item_time"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:layout_marginRight="5dp"android:text="17:05:06"android:textSize="12dp" /><RelativeLayout
        android:id="@+id/rl02"android:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_alignParentRight="true"android:layout_marginRight="10dp"android:gravity="center_vertical"android:orientation="horizontal" ><Button
            android:id="@+id/listview_item_send_avatar"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentRight="true"android:layout_alignParentTop="true"android:background="@drawable/user_icon_l"android:focusable="false" /><TextView
            android:id="@+id/listview_item_send_content"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginRight="10dp"android:layout_toLeftOf="@id/listview_item_send_avatar"android:background="@drawable/chatto_bg"android:clickable="true"android:focusable="true"android:gravity="left|center"android:lineSpacingExtra="2dp"android:minHeight="50dp"android:textColor="#ff000000"android:textSize="15sp" /><TextView
            android:id="@+id/name2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentRight="true"android:layout_below="@id/listview_item_send_avatar"android:layout_toRightOf="@id/listview_item_send_content"android:gravity="center"android:textColor="#818181"android:textSize="8dp" /></RelativeLayout></RelativeLayout>

添加好友
chat_add_friends.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:padding="10dp" ><TextView
        android:id="@+id/textView1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="好友ID"android:textColor="#fff" /><EditText
        android:id="@+id/chat_add_friend_id"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="@drawable/add_btn_bg"android:ems="10"android:hint="好友ID"android:paddingBottom="5dp"android:paddingLeft="5dp"android:paddingTop="5dp"android:textColor="#fff" ><requestFocus /></EditText><TextView
        android:id="@+id/textView2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="10dp"android:text="请输入验证信息"android:textColor="#fff" /><EditText
        android:id="@+id/chat_add_friend_reason"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="@drawable/add_btn_bg"android:ems="10"android:hint="我是..."android:paddingBottom="5dp"android:paddingLeft="5dp"android:paddingTop="5dp"android:textColor="#fff" /></LinearLayout>

主要的来了,AndroidManifest.xml添加权限

    <uses-permission android:name="android.permission.GET_TASKS" /><uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.VIBRATE" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

还有刚刚第一步的AppKey别忘了

<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.xmliu.imsample"android:versionCode="1"android:versionName="1.0" ><uses-sdk
        android:minSdkVersion="11"android:targetSdkVersion="19" /><uses-permission android:name="android.permission.GET_TASKS" /><uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.VIBRATE" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><application
        android:name="com.xmliu.imsample.BaseApplication"android:allowBackup="true"android:icon="@drawable/ic_launcher"android:label="@string/app_name"android:theme="@style/AppTheme" ><activity
            android:name="com.xmliu.imsample.ui.ChatLoginActivity"android:label="@string/app_name"android:windowSoftInputMode="adjustPan" ><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><activity
            android:name="com.xmliu.imsample.ui.ChatRegisterActivity"android:label="@string/app_name"android:windowSoftInputMode="adjustPan" ></activity><activity
            android:name="com.xmliu.imsample.ui.ChatListActivity"android:label="@string/app_name"android:windowSoftInputMode="adjustPan" ></activity><activity
            android:name="com.xmliu.imsample.ui.MainActivity"android:label="@string/app_name"android:windowSoftInputMode="adjustPan" ></activity><!-- 设置环信应用的appkey --><meta-data
            android:name="EASEMOB_APPKEY"android:value="在这里写你的AppKey" /><!-- 声明sdk所需的service SDK核心功能 --><service android:name="com.easemob.chat.EMChatService" /></application></manifest>

其他的页面就不说了,都是些item,不懂的问我,我QQ:1453022932,集成最主要的是要注意,登录,注册,很有多问题就是接受不到信息,这个是因为回调的时候出了问题或者是忘记注册广播了。
好了,我们运行一下,开两个模拟器,刚刚我已近新建了两个测试IM用户,分别登陆两个模拟器

添加好友

这里有一点Bug,就是好友请求不会立马收到,好友方要注销一下账号,重新登陆再能收到,目前在处理,各位也可以处理下这个问题,

点击同意之后注销一下账号,重新登陆,两个都注销一下,这可能是我代码写的有点问题吧,有兴趣的可以改一下,

点击好友进入聊天页面

还有一些问题,我正在处理,欢迎意见,谢谢大家了。

源码下载地址:http://download.csdn.net/detail/qq_19067845/9515271

环信即时通讯单聊集成,添加好友,实现单聊相关推荐

  1. 环信即时通讯的基本集成

    项目中是基于环信SDK2.0集成开发,所以本文只介绍SDK2.0的基本集成. 第一,前期准备工作,上传推送证书,注册环信开发者账号.然后开始导入环信SDK,EaseMobSDK,导入环信文档2.x需求 ...

  2. vue2集成声网-环信即时通讯SDK,建议实现两人聊天

    1.注册登陆环信并创建用户 步骤:注册 => 登录 => 创建应用 => 创建应用用户 登录注册:环信登陆注册页面(https://console.easemob.com/user/ ...

  3. android环信集成单聊,环信即时通讯单聊集成

    [实例简介] 环信即时通讯单聊集成,添加好友,实现单聊,可以学习下 [实例截图] [核心代码] IM └── IM ├── AndroidManifest.xml ├── bin │   ├── An ...

  4. 环信即时通讯SDK集成——如何使用Swift快速集成环信IM iOS SDK并实现单聊

    本文介绍如何使用swift快速集成环信即时通讯 IM iOS SDK 实现单聊. 前提条件 • Xcode (推荐最新版本). • 安装 iOS 10.0 或更高版本的 iOS 模拟器或 Apple ...

  5. 环信即时通讯SDK集成——实战:快速实现iOS应用中集成即时通讯IM和UI

    准备 熟练objective-c语言 有一台mac电脑,并安装了xcode 和 cocoapods 目标 手把手教大家在iOS应用中集成即时通讯IM 功能 内容篇幅较长,需要内心平和耐心看下去,务必戒 ...

  6. android 环信集成,Android Studio下的环信即时通讯简单集成

    环信即时通讯云是全球最大的即时通讯云 PaaS 平台,可以快速实现APP的即时通讯的功能,官方的DEMO是基于Eclipse开发的,对于新版本的Android Studio支持不太好,下面就简单说一下 ...

  7. 环信即时通讯——集成客户端

    最近公司在开发一款 APP,需要使用环信即时通讯来做及时聊天和直播,找了好多官方的 REST API 发现并没有把直播集成服务写完,于是自己完善了一下,与大家分享 O (∩_∩) O 话不多说上代码 ...

  8. Android 环信即时通讯集成

    1.  首先需要注册环信即时通讯    主要是获取到appkey 2. 下载Android  的 sdk  和 demo 3. 第三步 我先忙需要导入  easeui 声明一点 libs.lite  ...

  9. 环信即时通讯云iOS版V2.0.9.1服务评测

    集成测试 评测环境 2G/3G/WiFi网络下: 测评环境 MAC OS(10.9.2)+ XCode(5.1) + iPhone 测试对象 环信即时通讯云 IOS SDK Version 2.0.9 ...

最新文章

  1. Hibernate的generator属性之意义【转】
  2. Selenium简介以及selenium环境搭建
  3. $_server['php_self'] 漏洞,Discuz! $_SERVER['PHP_SELF'] XSS Vulnerability
  4. Mysql union联合查询_Mysql联合查询union和union all的使用介绍
  5. 【图像处理基础】基于matlab GUI图像局部放大【含Matlab源码 1016期】
  6. java 制作简历_个人简历java制作.doc
  7. Windows Phone上的相机景深计算器
  8. feedburner怎么用_FeedBurner 不能用了,还有 FeedSky,附个相关插件
  9. python实现单机斗地主_用Python破解斗地主残局
  10. 群英荟萃 | UINO优锘科技ThingJS平台亮相华为开发者大会
  11. facebook登陆按钮_为什么Facebook Like按钮占平均网站代码的16%
  12. electron 调试、问题追踪
  13. 【Matlab】基于皮肤概率建模的人脸检测算法雏形
  14. 【新】CSDN文章一键打印、输出PDF(自动阅读全文、全清爽模式)
  15. x722网卡支持百兆吗_用200M宽带,电脑网卡却只有百兆?这样可以解决!
  16. 小米4C刷回原厂固件
  17. python中字典的循环遍历的两种方式
  18. linux运行不存在的命令报错
  19. vb microsoft html object library,HTML对象库简介(Microsoft HTML Object Library - mshtml.tlb)...
  20. ”未获得合适的许可,你可能是盗版软件的受害者相关解决办法“

热门文章

  1. Java利用if语句来实现中国个人所得税的计算方法
  2. 华为x10max什么时候升级鸿蒙,网传华为鸿蒙 OS 2.0 升级清单曝光,来看看有没有你的...
  3. Eslint讲解及报错解决
  4. jQuery 特效网址(特效大全)
  5. DigiCert SSL证书怎么样?
  6. 00后阿里P6晒出工资单,看完扎心了...
  7. mysql优化 个人笔记 - 非礼勿扰 -m17
  8. [双语阅读]克林顿女儿切尔西订婚
  9. 张一鸣宣布卸任字节跳动CEO,网友:想以个人名义上富豪榜;​腾讯第一季度员工平均月薪7.6万元;谷歌发布自然语言平台LaMDA...
  10. sa-token关闭控制台banner配置