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

前段时间由于项目需要,了解一下环信即时通讯,然后自己通过查资料写了一个基于环信的单聊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;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mApplication = (BaseApplication) getApplication();
        AppManager.getInstance().addActivity(this);
//      check netwotk
        context = this;
    }

    @Override
    public void onBackPressed() {
        // TODO Auto-generated method stub
        super.onBackPressed();
    }

    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
    }

    @Override
    protected void onPause() {
        // TODO Auto-generated method stub
        super.onPause();
    }

    @Override
    protected void onResume() {
        // TODO Auto-generated method stub
        super.onResume();
    }

}

BaseApplication.java

public class BaseApplication extends Application {

    private static final String TAG = BaseApplication.class.getSimpleName();

    private static BaseApplication mInstance = null;

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
    }

    /*
     * (non-Javadoc)
     *
     * @see android.app.Application#onCreate()
     */
    @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        super.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());
        // 在做代码混淆的时候需要设置成false
        EMChat.getInstance().setDebugMode(true);
        initHXOptions();
        mInstance = this;

    }

    protected void initHXOptions() {
        Log.d(TAG, "init HuanXin Options");

        // 获取到EMChatOptions对象
        EMChatOptions options = EMChatManager.getInstance().getChatOptions();
        // 默认添加好友时,是不需要验证的true,改成需要验证false
        options.setAcceptInvitationAlways(false);
        // 默认环信是不维护好友关系列表的,如果app依赖环信的好友关系,把这个属性设置为true
        options.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;
    }

    @Override
    public void onLowMemory() {
        // TODO Auto-generated method stub
        super.onLowMemory();
        Log.i(TAG, "onLowMemory");
    }

    @Override
    public void onTerminate() {
        // TODO Auto-generated method stub
        Log.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;
    }

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return mListData.size();
    }

    @Override
    public Object getItem(int arg0) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public long getItemId(int arg0) {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public View getView(int index, View cView, ViewGroup arg2) {
        // TODO Auto-generated method stub

        Holder 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;
    }

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return mListData.size();
    }

    @Override
    public Object getItem(int arg0) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public long getItemId(int arg0) {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public View getView(int index, View cView, ViewGroup arg2) {
        // TODO Auto-generated method stub
        FHolder 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;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_chat_main);

        mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                // TODO Auto-generated method stub
                super.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 stub
        sendBtn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                sendMsg();
            }
        });

        contentET.setOnKeyListener(new OnKeyListener() {

            @Override
            public boolean onKey(View arg0, int keycode, KeyEvent arg2) {
                // TODO Auto-generated method stub
                if (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);
        // 设置消息body
        TextMessageBody txtBody = new TextMessageBody(content);
        message.addBody(txtBody);
        // 设置接收人
        message.setReceipt(username);
        // 把消息加入到此会话对象中
        conversation.addMessage(message);
        // 发送消息
        EMChatManager.getInstance().sendMessage(message, new EMCallBack() {

            @Override
            public void onError(int arg0, String arg1) {
                // TODO Auto-generated method stub
                Log.i("TAG", "消息发送失败");
            }

            @Override
            public void onProgress(int arg0, String arg1) {
                // TODO Auto-generated method stub
                Log.i("TAG", "正在发送消息");
            }

            @Override
            public void onSuccess() {
                // TODO Auto-generated method stub
                Log.i("TAG", "消息发送成功");
                ChatListData data = new ChatListData();
                data.setSendContent(content);
                data.setType(1);
                mListData.add(data);
                mHandler.sendEmptyMessage(0x00001);
            }
        });
    }

    private class NewMessageBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            // 注销广播
            abortBroadcast();

            // 消息id(每条消息都会生成唯一的一个id,目前是SDK生成)
            String msgId = intent.getStringExtra("msgid");
            // 发送方
            String username = intent.getStringExtra("from");
            // 收到这个广播的时候,message已经在db和内存里了,可以通过id获取mesage对象
            EMMessage message = EMChatManager.getInstance().getMessage(msgId);
            EMConversation conversation = EMChatManager.getInstance()
                    .getConversation(username);

            MessageBody tmBody = message.getBody();

            ChatListData data = new ChatListData();
            data.setReceiveContent(((TextMessageBody) tmBody).getMessage());
            data.setType(2);
            mListData.add(data);
            mHandler.sendEmptyMessage(0x00001);

            Log.i("TAG", "收到消息:" + ((TextMessageBody) tmBody).getMessage());
            // 如果是群聊消息,获取到group id
            if (message.getChatType() == ChatType.GroupChat) {
                username = message.getTo();
            }

            if (!username.equals(username)) {
                // 消息不是发给当前会话,return
                return;
            }
        }
    }

    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        super.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;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.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() {

            @Override
            public void onCheckedChanged(CompoundButton arg0, boolean arg1) {
                // TODO Auto-generated method stub
                if (arg1) {
                    mPasswordCB.setChecked(true);
                    //动态设置密码是否可见
                    mPasswordET
                            .setTransformationMethod(HideReturnsTransformationMethod
                                    .getInstance());
                } else {
                    mPasswordCB.setChecked(false);
                    mPasswordET
                            .setTransformationMethod(PasswordTransformationMethod
                                    .getInstance());
                }
            }
        });

        mSigninBtn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                final 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() {// 回调
                                @Override
                                public 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();
                                        }
                                    });
                                }

                                @Override
                                public void onProgress(int progress,
                                        String status) {

                                }

                                @Override
                                public void onError(int code, String message) {
                                    if (code == -1005) {
                                        message = "用户名或密码错误";
                                    }
                                    final String msg = message;
                                    runOnUiThread(new Runnable() {
                                        public void run() {
                                            Log.d("main", "登陆聊天服务器失败!");
                                            Toast.makeText(
                                                    getApplicationContext(),
                                                    msg, Toast.LENGTH_SHORT)
                                                    .show();
                                        }
                                    });
                                }
                            });
                }
            }
        });

        mSignupTV.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                startActivity(new Intent(ChatLoginActivity.this,
                        ChatRegisterActivity.class));
            }
        });
    }

    @Override
    public 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() {
                                @Override
                                public 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;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.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() {

            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                mCodeIV.setImageBitmap(IdentifyCode.getInstance()
                        .createBitmap());
                currCode = IdentifyCode.getInstance().getCode();
                Log.i("TAG", "currentCode==>" + currCode);
            }
        });

        mBackTV.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                finish();
            }
        });
        mPasswordCB.setOnCheckedChangeListener(new OnCheckedChangeListener() {

            @Override
            public void onCheckedChanged(CompoundButton arg0, boolean arg1) {
                // TODO Auto-generated method stub
                if (arg1) {
                    mPasswordCB.setChecked(true);
                    mPasswordET
                            .setTransformationMethod(HideReturnsTransformationMethod
                                    .getInstance());
                } else {
                    mPasswordCB.setChecked(false);
                    mPasswordET
                            .setTransformationMethod(PasswordTransformationMethod
                                    .getInstance());
                }
            }
        });
        mSignupBtn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                final 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() {

                        @Override
                        public void run() {
                            // TODO Auto-generated method stub
                            try {
                                // 调用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;

    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_chat_friends);

        mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                // TODO Auto-generated method stub
                super.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() {

            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                addView = 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() {
                                    @Override
                                    public 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 block
                                            e.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() {

            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub

                showLogoutDialog();

            }
        });

        mListView.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
                    long arg3) {
                // TODO Auto-generated method stub
                startActivity(new Intent(MainActivity.this,
                        ChatListActivity.class).putExtra("userid",
                        userList.get(arg2)));
            }
        });

        mListView.setOnItemLongClickListener(new OnItemLongClickListener() {

            @Override
            public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
                    int arg2, long arg3) {
                // TODO Auto-generated method stub
                showDeleteDialog(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 block
            e1.printStackTrace();
            Log.i("TAG", "usernames errcode==>" + e1.getErrorCode());
            Log.i("TAG", "usernames errcode==>" + e1.getMessage());
        }// 需异步执行
    }

    private class MyContactListener implements EMContactListener {

        @Override
        public void onContactAgreed(String username) {
            // 好友请求被同意
            Log.i("TAG", "onContactAgreed==>" + username);
            // 提示有新消息
            EMNotifier.getInstance(getApplicationContext()).notifyOnNewMsg();
            Toast.makeText(getApplicationContext(), username + "同意了你的好友请求",
                    Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onContactRefused(String username) {
            // 好友请求被拒绝
            Log.i("TAG", "onContactRefused==>" + username);
        }

        @Override
        public void onContactInvited(String username, String reason) {
            // 收到好友添加请求
            Log.i("TAG", username + "onContactInvited==>" + reason);
            showAgreedDialog(username, reason);
            EMNotifier.getInstance(getApplicationContext()).notifyOnNewMsg();
        }

        @Override
        public void onContactDeleted(List<String> usernameList) {
            // 好友被删除时回调此方法
            Log.i("TAG", "usernameListDeleted==>" + usernameList.size());
        }

        @Override
        public void onContactAdded(List<String> usernameList) {
            // 添加了新的好友时回调此方法
            for (String str : usernameList) {
                Log.i("TAG", "usernameListAdded==>" + str);
            }
        }
    }

    @Override
    public 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() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        // EMChatManager.getInstance().logout();
                        logout(new EMCallBack() {

                            @Override
                            public void onSuccess() {
                                // TODO Auto-generated method stub
                                startActivity(new Intent(MainActivity.this,
                                        ChatLoginActivity.class));
                            }

                            @Override
                            public void onProgress(int arg0, String arg1) {
                                // TODO Auto-generated method stub

                            }

                            @Override
                            public 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() {

            @Override
            public void onSuccess() {
                // TODO Auto-generated method stub
                if (callback != null) {
                    callback.onSuccess();
                }
            }

            @Override
            public void onError(int code, String message) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onProgress(int progress, String status) {
                // TODO Auto-generated method stub
                if (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() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        try {
                            EMChatManager.getInstance().acceptInvitation(user);
                            initList();
                        } catch (EaseMobException e) {
                            // TODO Auto-generated catch block
                            e.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 block
                            e.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() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        try {
                            EMContactManager.getInstance().deleteContact(user);
                            initList();
                        } catch (EaseMobException e) {
                            // TODO Auto-generated catch block
                            e.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() {
                    @Override
                    public 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 settings
    private 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 height
    private int width = DEFAULT_WIDTH, height = DEFAULT_HEIGHT;

    // random word space and pading_top
    private 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 size
    private int codeLength = DEFAULT_CODE_LENGTH,
            line_number = DEFAULT_LINE_NUMBER, font_size = DEFAULT_FONT_SIZE;

    // variables
    private 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

时间: 2024-10-11 20:57:36

环信即时通讯单聊集成,添加好友,实现单聊的相关文章

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

1.环信官网介绍 2.准备工作: 登录环信开发者账号并创建应用.制作并上传推送证书(开发.生产): 3.下载SDK:通过Cocoapods下载或到官网下载 ,对于Cocoapods下载: 不包含实时语音版本SDK(EaseMobClientSDKLite),引用时 #import <EaseMobSDK/EaseMob.h> pod 'EaseMobSDK', :git => 'https://github.com/easemob/sdk-ios-cocoapods.git'  包含实时

环信即时通讯 —— 消息、会话

1.消息EMMessage 环信支持文字.图片.位置.语音.视频.文件.透传.自定义八种消息构造.消息,即IM交互实体,在SDK中对应的类型是 **EMMessage**,EMMessage可以由多个符合<IEMMessageBody>协议的body组成,但是 推荐使用一个body. 2.消息构造 1> 设置消息的内容 文字消息: EMChatText *msgChat = [[EMChatText alloc] initWithText:@"要发送的消息"]; 图片

Android 基于环信即时云的IM开发

假如我们想要快速实现一个即时通讯功能,最快捷的方法就是借助网络上的即时云服务.下面我们讲述一下如何利用环信实现一个IM功能. 首先下载环信的SDK,也就是几个库,把demo里面的HXSDKHelper.java,HXSDKModel.java,DefaultHXSDKModel.java,HXPreferenceUtils.java四个文件复制到新建的工程下.稍作修改. 首先在Application中实现初始化SDK public static DemoHXSDKHelper hxSDKHelp

环信即时聊天步骤

1:注册账号 2:下载sdk 3:导入modle EaseUI 4:讲model加入到主项目 5:登陆功能:代码如下: EMClient.getInstance().login(userName,password,new EMCallBack() {//回调 @Override public void onSuccess() { EMClient.getInstance().groupManager().loadAllGroups(); EMClient.getInstance().chatMa

iOS 即时通讯SDK的集成,快速搭建自己的聊天系统

现在的外包项目需求变态的各种各样,今天要做社交,明天要加电商,后天又要加直播了,这些系统如果要自己开发,除非大公司技术和人力都够,不然短时间是几乎实现不了的.所以学会灵活利用市面上的各种SDK是灰常重要的技能. 最近继续在做的项目是一个气象救灾类APP,里面需要进行聊天的即时通讯模块.目前已经实现,效果如下: 一.市面上的即时通讯SDK 目前市面上的即时通讯SDK大概有:融云.网易云信.容联云等.非常多. 较为稳定.功能较全的应该是网易云信了,界面如下: 但是我们的应用需要的即时通讯是一个模块,

iOS环信即时聊天

一.注册登陆环形开发者账号,并且创建应用,获得对应的AppKey 二.根据实际情况制作并上传推送证书(开发环境推送证书sandbox,请选择 Apple Push Notification service SSL  / 生产环境证书production,请选择 Apple Push Notification service SSL ) 详细制作步骤属于iOS开发基本知识,这里不再做详细说明. 三.集成iOS 环信SDK.为了方便快速,这里我们直接使用Cocoapods集成 在终端cd到该工程跟目

环信开源计划开启即时通讯云开源平台时代

12月22日,在"首届移动社交创新价值峰会"上,环信即时通讯云(http://www.easemob.com)发布了被称为"4X100计划"的<环信开源平台计划>,此计划将推动即时通讯云行业进入开源平台时代.而一个中国IT界崭新的开放共赢的生态体系也将随之逐步建立起来. 图注:环信CEO刘俊彦在峰会上解读环信开源平台计划 "2014年,即时通讯云获得了很好的发展,环信也帮助了很多合作伙伴实现了移动社交的创新.那么2015年,如何驱动移动社交创新

源码提供!Android即时通讯和sns开源项目汇总

博客原地址: Android即时通讯和sns开源项目汇总 这是一个整理即时通讯(IM)和社交系统(SNS)优秀开源项目的文档,项目上传github欢迎提交更新. github地址:https://github.com/CameloeAnthony/Perfect_IM_SNS 一 即时通讯和社交系统平台 1 环信(推荐) 2 阿里百川 云旺 3 融云 4 OpenSNS -- #二 基于环信的即时通讯开源项目 数据整理自环信官网,网络数据和github.更多信息请参考环信官方网站和ImGeek

李洪强iOS开发之-环信02.2_环信官网下载环信 SDK

李洪强iOS开发之-环信02.2_环信官网下载环信 SDK 移动客服即时通讯云 iOS SDK 当前版本:V3.1.4 2016-07-08 [ 版本历史 ] | 开发指南 | 知识库 | Demo源码 | 最新SDK下载Demo扫码安装 切换至v2.x版本 iOS SDK v2.x 当前版本:V2.2.6 2016-06-28 [ 版本历史 ] | 开发指南 | 知识库 | Demo源码 | 最新SDK下载Demo扫码安装 返回v3.x版本 Android SDK 当前版本:V3.1.4 20