为了提高自己在Android开发上的能力,博主决定写一个类似于QQ、微信的聊天软件。不过,简单的想想之后发现,要实现这样的一个聊天软件,需要学习和掌握的东西还很多。作为一个Android开发的小白,也没有足够的实力能很快对这个APP的开发有很大的突破。
于是,博主参考《疯狂Android讲义》中关于“Android网络应用”部分。首先从简单的聊天功能进行实现。第一阶段,主要实现的是一个多人聊天室,通过socket以及多线程进行实现。
具体过程为:
- Client A、Client B、Client C 分别与Server建立socket连接。
- 每建立一个连接Server将把这个socket存储在一个socketList的列表里。
- 每当其中一个客户端“说话”时(以Client A 为例),Server收到Client A 发出的消息将会遍历整个socketList,将这条信息广播给当前所有已经建立了socket连接的Client。
下面,博主将从服务器端以及Android客户端,对这个实现过程进行详细的介绍:
- Server
主要实现功能:与客户端建立socket连接;对Client发送的消息进行转发。
MyServer.java
ServerTread.javapublic class MyServer { static BufferedReader br; static int index = 0; public static ArrayListsocketList = new ArrayList<>(); public static void main(String[] args) throws IOException { ServerSocket ss =new ServerSocket(30000); //开启30000号端口 while(true ){ Socket s = ss.accept(); socketList.add(s); new Thread(new ServerThread(s)).start(); } //持续接收来自Client的socket连接,并将socket加入列表 }} public class ServerThread implements Runnable { Socket s = null; BufferedReader br = null; public ServerThread(Socket s) throws IOException{ this.s = s; br = new BufferedReader(new InputStreamReader(s.getInputStream() , "utf-8" )); } @Override public void run() { try { String content = null; while((content = readFromClient()) != null){ for(Socket s : MyServer.socketList){ OutputStream os = s.getOutputStream(); os.write((content + "\n").getBytes("utf-8" )); } } //遍历整个socketList,将信息写入输出流进行广播 } catch (Exception e) { e.printStackTrace(); } } private String readFromClient() { try { return br .readLine(); } catch (Exception e) { MyServer. socketList.remove(s ); //读取信息失败则移除socket } return null ; }}
- Client
主要实现功能:与服务器建立socket连接;实现消息的发送与接受。
Chat.java
public class Chat extends Activity { TextView tv_name; EditText et_input; Button bt_send; ClientThread clientThread; private ListView listview ; private ListmData ; private ChatMessageAdapter mAdapter ; private static final String tag = "Chat"; private Handler handler = new Handler(){ @Override public void handleMessage(android.os.Message msg) { if(msg.what == 0x123){ ChatMessage receiveMsg = (ChatMessage) msg. obj; mData.add(receiveMsg); mAdapter.notifyDataSetChanged(); listview.setSelection(mData .size() - 1); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window. FEATURE_NO_TITLE); setContentView(R.layout. chat); initView(); //初始化view initData(); //初始化数据 clientThread = new ClientThread(handler); new Thread(clientThread ).start(); //启动新线程发送信息 bt_send.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { final String inputMsg = et_input.getText().toString(); Log. v(tag, "inputMsg: " + inputMsg); if(TextUtils.isEmpty(inputMsg)){ Toast. makeText(Chat.this, "发送消息不能为空!" , Toast. LENGTH_SHORT).show(); } try { ChatMessage cm = new ChatMessage(); cm.setDate( new Date()); cm.setMsg(inputMsg); cm.setType(Type. OUTCOMING); cm.setName( "paul"); mData.add(cm); mAdapter.notifyDataSetChanged(); listview.setSelection(mData .size() - 1); Message msg = new Message(); msg. what = 0x345; msg. obj = inputMsg; et_input.setText("" ); clientThread.revHandler .sendMessage(msg); //发送信息 } catch (Exception e) { e.printStackTrace(); } } }); } private void initData() { mData = new ArrayList (); String data = et_input.getText().toString(); mAdapter = new ChatMessageAdapter(Chat.this, mData); listview.setAdapter(mAdapter ); } private void initView() { tv_name = (TextView) findViewById(R.id.tv_name); et_input = (EditText) findViewById(R.id.et_input); bt_send = (Button) findViewById(R.id.bt_send); listview = (ListView) findViewById(R.id.id_listview); } ClientTread.java
public class ClientThread implements Runnable { private Socket s ; private Handler handler ; public Handler revHandler ; BufferedReader br = null; OutputStream os = null; public ClientThread(Handler handler) { this.handler = handler; } @Override public void run() { try { s = new Socket("10.105.36.51" , 30000); //通过ip地址和端口号连接服务器 br = new BufferedReader(new InputStreamReader(s.getInputStream())); os = s.getOutputStream(); new Thread(){ @Override public void run() { String content = null; try { while((content = br .readLine()) != null){ ChatMessage cm =new ChatMessage(); cm.setDate( new Date()); cm.setMsg(content); cm.setType(Type. INCOMING); cm.setName( "paul"); Message msg = new Message(); msg. what = 0x123; msg. obj = cm; handler.sendMessage(msg); } } catch (IOException e) { e.printStackTrace(); } } }.start(); Looper. prepare(); revHandler = new Handler(){ @Override public void handleMessage(Message msg) { if(msg.what == 0x345){ try { os.write((msg. obj.toString() + "\r\n").getBytes("utf-8" )); //将信息写入输出流发送给服务器 } catch (IOException e) { e.printStackTrace(); } } } }; Looper. loop(); } catch (SocketTimeoutException e) { System. out.println("网络连接超时!" ); } catch (Exception e) { e.printStackTrace(); } }}