Welcome 微信登录
编程资源 图片资源库 蚂蚁家优选

首页 / 移动开发 / Android / Android聊天工具基于socket实现

特简单, 没有数据库, 还没有处理各种异常。
登录:输入用户名点击的登录即可。
发送消息: 特定格式->toUser:message
1. 服务器:保存在线用户    

public class Online { private static Online mOnline = null; private LinkedHashMap<String, Socket> mOnlines = new LinkedHashMap<String, Socket>(); private Online() { } public synchronized static Online getInstance() {if(null == mOnline) { mOnline = new Online();} return mOnline; } public void put(String key, Socket socket) {if(!mOnlines.containsKey(key)) { mOnlines.put(key, socket);} } public Socket get(String key) {return mOnlines.get(key); } public void remove(String key) {mOnlines.remove(key); }}
2. 服务器:一个简单的socket服务器    

import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket; // login:uid// send:fromuser:touser:message// logout:uidpublic class Server implements Runnable { private Socket mSocket; private Online mOnline;public Server(Socket socket) {mSocket = socket;mOnline = Online.getInstance(); }@Override public void run() {try { BufferedReader reader = new BufferedReader(new InputStreamReader( mSocket.getInputStream())); String cmd = reader.readLine(); // login if (cmd.startsWith("login")) {String userName = cmd.split(":")[1];mOnline.put(userName, mSocket);System.out.println(userName + " login..."); PrintWriter writer = new PrintWriter(mSocket.getOutputStream());writer.println("success");writer.flush(); } else if (cmd.startsWith("send")) {System.out.println(cmd);String[] cmds = cmd.split(":");String from = cmds[1];Socket to = mOnline.get(cmds[2]);String msg = cmds[3]; PrintWriter writer = new PrintWriter(to.getOutputStream());System.out.println("rec:" + from + ":" + cmds[2] + ":" + msg); writer.println("rec:" + from + ":" + cmds[2] + ":" + msg);writer.flush(); }else if (cmd.startsWith("logout")) {System.out.println(cmd); String user = cmd.split(":")[1];mOnline.get(user).close();mOnline.remove(user); PrintWriter writer = new PrintWriter(mSocket.getOutputStream());writer.println("success");writer.flush(); }} catch (Exception e) { e.printStackTrace();} }public static void main(String[] args) throws Exception {ServerSocket server = new ServerSocket(8888);boolean flag = true;while (flag) { new Thread(new Server(server.accept())).start(); System.out.println("user in...");} server.close(); }}
3. 客户端登录界面    

public class MainActivity extends Activity { private EditText mUser; @Override protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main); mUser = (EditText) findViewById(R.id.username); } public void login(View view) {final String userName = mUser.getText().toString().trim();Login login = new Login(userName);login.setOnLoginListener(new Login.LoginCallback() { @Override public void onLogin(boolean success) {if(success) { Intent intent = new Intent(MainActivity.this, Chat.class); intent.putExtra("user", userName); startActivity(intent); finish();}else { Toast.makeText(MainActivity.this, "登录失败", Toast.LENGTH_SHORT).show();} }}); login.login(); }}
4. 处理登录    

public class Login { private String mUserName; private LoginCallback mCallback; public Login(String userName) {mUserName = userName; } public void setOnLoginListener(LoginCallback callback) {mCallback = callback; } private Handler mHandler = new Handler() {public void handleMessage(Message msg) { switch (msg.what) { case Constant.SUCCESS:mCallback.onLogin(true);break; case Constant.FAILED:mCallback.onLogin(false);break; }}; }; public void login() {new Thread(new Runnable() { @Override public void run() {Socket socket = null;try { socket = new Socket(); socket.connect(new InetSocketAddress("192.168.100.100", 8888), 4000); PrintWriter writer = new PrintWriter(socket.getOutputStream()); writer.println("login:" + mUserName); writer.flush(); BufferedReader reader = new BufferedReader( new InputStreamReader(socket.getInputStream())); String line = reader.readLine(); System.out.println(line); if("success".equals(line)) {PConnection.socket = socket;mHandler.sendEmptyMessage(Constant.SUCCESS); }else {mHandler.sendEmptyMessage(Constant.FAILED); }}catch(Exception e) { e.printStackTrace();} }}).start(); } public interface LoginCallback {public void onLogin(boolean success); }}
5. 聊天界面    

public class Chat extends Activity { private String mUserName; private EditText mEdit; private ListView mMessage; private ReceiverMessage mRecMessage; private SendMessage mSendMesage; private List<Map<String, String>> mData = new ArrayList<Map<String, String>>(); private MessagesAdapter mAdapter; @Override protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.chat_layout); mUserName = getIntent().getStringExtra("user");mEdit = (EditText) findViewById(R.id.edit);mMessage = (ListView) findViewById(R.id.message); mRecMessage = new ReceiverMessage();mRecMessage.setOnReceiverListener(new RecListener());mRecMessage.run(); mSendMesage = new SendMessage();mSendMesage.setOnSendListener(new SendListener()); mAdapter = new MessagesAdapter(this, mData);mMessage.setAdapter(mAdapter); } public void send(View view) {String[] content = mEdit.getText().toString().trim().split(":");mSendMesage.send(mUserName, content[0], content[1]); } private class RecListener implements ReceiverMessage.OnReceiverListener {@Overridepublic void onReceiver(String user, String msg) { Map<String, String> temp = new HashMap<String, String>(); temp.put("user", user); temp.put("msg", msg); temp.put("pos", "right"); mData.add(temp); mAdapter.notifyDataSetChanged();} } private class SendListener implements SendMessage.OnSendListener {@Overridepublic void onSend(String[] msg) { Map<String, String> temp = new HashMap<String, String>(); temp.put("user", "我"); temp.put("msg", msg[1]); temp.put("pos", "left"); mData.add(temp); mAdapter.notifyDataSetChanged();} } @Override public boolean onOptionsItemSelected(MenuItem item) {if(R.id.logout == item.getItemId()) { Logout logout = new Logout(); logout.setOnLogoutListener(new Logout.OnLogoutListener() {@Overridepublic void onLogout(boolean success) { if(success) {Toast.makeText(Chat.this, "注销成功", Toast.LENGTH_SHORT).show();finish(); }else {Toast.makeText(Chat.this, "注销失败", Toast.LENGTH_SHORT).show(); }} }); logout.logout(mUserName);} return super.onOptionsItemSelected(item); } @Override public boolean onCreateOptionsMenu(Menu menu) {getMenuInflater().inflate(R.menu.main, menu);return super.onCreateOptionsMenu(menu); }}
6. 发送消息    

public class SendMessage { private OnSendListener mListener; public void setOnSendListener(OnSendListener listener) {mListener = listener; } private Handler mHandler = new Handler() {public void handleMessage(Message msg) { mListener.onSend((String[]) msg.obj);}; }; // send:from:to:message public void send(final String from , final String to, final String msg) {new Thread(new Runnable() { @Override public void run() {Socket socket = null;try { socket = new Socket(); socket.connect(new InetSocketAddress("192.168.100.100", 8888), 4000); PrintWriter writer = new PrintWriter(socket.getOutputStream()); writer.println("send:" + from + ":" + to + ":" + msg); writer.flush(); Message message = mHandler.obtainMessage( Constant.SUCCESS, new String[] {to, msg}); message.sendToTarget();} catch(Exception e) {} finally { try {socket.close(); } catch (IOException e) {e.printStackTrace(); }} }}).start(); } public interface OnSendListener {public void onSend(String[] msg); }}
7. 接收消息,死循环,但阻塞,没啥问题    

public class ReceiverMessage { private OnReceiverListener mListener; public void setOnReceiverListener(OnReceiverListener listener) {mListener = listener; } private Handler mHandler = new Handler() {public void handleMessage(Message msg) { String[] cmds = (String[]) msg.obj; mListener.onReceiver(cmds[0], cmds[1]);}; }; public void run() {new Thread(new Runnable() { @Override public void run() {try { Socket socket = PConnection.socket; while(true) {System.out.println("wait for message...");BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));String line = reader.readLine(); if(line.startsWith("rec")) { //rec:fromuser:touser:message String[] cmds = line.split(":"); System.out.println(cmds[0] + ":" + cmds[1] + ":" + cmds[2] + ":" + cmds[3]); Message msg = mHandler.obtainMessage(Constant.SUCCESS, new String[] {cmds[1], cmds[3]}); msg.sendToTarget();} }} catch (Exception e) { e.printStackTrace();} }}).start(); } public interface OnReceiverListener {public void onReceiver(String user, String msg); }}
8. 注销登录    

public class Logout { public OnLogoutListener mListener; public void setOnLogoutListener(OnLogoutListener listner) {mListener = listner; } private Handler mHandler = new Handler() {public void handleMessage(Message msg) { if(Constant.SUCCESS == msg.what) {mListener.onLogout(true); }else {mListener.onLogout(false); }}; }; public void logout(final String user) {new Thread(new Runnable() { @Override public void run() {try { Socket socket = new Socket(); socket.connect(new InetSocketAddress("192.168.100.100", 8888), 4000); PrintWriter writer = new PrintWriter(socket.getOutputStream()); writer.println("logout:" + user); writer.flush(); BufferedReader reader = new BufferedReader( new InputStreamReader(socket.getInputStream())); if("success".equals(reader.readLine())) {PConnection.socket = null;mHandler.sendEmptyMessage(Constant.SUCCESS); }else {mHandler.sendEmptyMessage(Constant.FAILED); }} catch (Exception e) { e.printStackTrace();} }}).start(); } public interface OnLogoutListener {public void onLogout(boolean success); }}
9. 存放登录后的socket,在发送消息和接收消息时使用该socket    

public class PConnection { public static Socket socket;}
希望本文所述对大家学习有所帮助。