学习了3个月安卓了,今天开始写点东西。
这个安卓的聊天demo,还是分为客户端、服务器两大部分,先来看看客户端:
界面代码如下:
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); this.requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); init(); //打开应用就默认连接 cHandler.sendEmptyMessage(0x01); } private void init() { cButtonSend = (Button) findViewById(R.id.btn); cName = (EditText) findViewById(R.id.yhm); cToName = (EditText) findViewById(R.id.jsm); cEditTextContent = (EditText) findViewById(R.id.et); cList = (ListView) findViewById(R.id.listview); mAdapter = new ChatMsgViewAdapter(this, mDataArrays); cList.setAdapter(mAdapter); cButtonSend.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if( cName.getText().toString().equals("") || cName.getText().toString()==null || cToName.getText().toString().equals("") || cToName.getText().toString()==null || cEditTextContent.getText().toString().equals("") || cEditTextContent.getText().toString()==null){ new AlertDialog.Builder( MainActivity.this) .setTitle("") .setMessage("请填写完整!") .setPositiveButton("确定", null).show(); }else{ //发送信息展现 ChatMsgEntity entity = new ChatMsgEntity(); entity.setDate(getDate()); entity.setName(cName.getText().toString()); entity.setMsgType(false); entity.setText(cEditTextContent.getText().toString()); mDataArrays.add(entity); mAdapter.notifyDataSetChanged(); cList.setSelection(cList.getCount() - 1); cHandler.sendEmptyMessage(0x01); //清楚输入框内容 cEditTextContent.setText(""); } } }); }socket相关代码:
Handler cHandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case 0x01: cThread = new Thread() { @Override public void run() { super.run(); DataInputStream dis = null; DataOutputStream dos = null; try { // 阻塞函数,正常连接后才会向下继续执行 cSocket = new Socket(ADDRESS, PORT); dis = new DataInputStream(cSocket.getInputStream()); dos = new DataOutputStream(cSocket.getOutputStream()); if(mDataArrays.isEmpty()){//刚打开应用,只是建立连接 }else{ // 向服务器写数据 ChatMsgEntity e = new ChatMsgEntity(); e = mDataArrays.get(mDataArrays.size()-1); dos.writeUTF(e.getName()); dos.writeUTF(cToName.getText().toString()); dos.writeUTF(e.getText().toString()); // 读取服务器发来的数据 //cContent += dis.readUTF(); recive1 = dis.readUTF(); recive2 = dis.readUTF(); if(recive1.equals("错误*001\n我不在线")){ //对方不在线,发送失败 cHandler.sendEmptyMessage(0x03); }else{ //接收信息展现 cHandler.sendEmptyMessage(0x04); } } } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (dis == null) { dis.close(); } if (dos == null) { dos.close(); } } catch (IOException e) { e.printStackTrace(); } // cHandler.sendEmptyMessage(0x02); } } }; cThread.start(); break; case 0x02: // cTextViewContent.setText(cContent); break; case 0x03://对方不在线,发送失败 recive(recive2, recive1); break; case 0x04://接收信息展现 recive(recive1, recive2); break; default: break; } } };
下面是接收服务端返回的消息(包括他人发送给你,和你发送消息,但是对方不在线返回的消息)
其中关键是修改界面必须要在主线程中完成:mAdapter.notifyDataSetChanged();
public void recive(String a, String b){ ChatMsgEntity e = new ChatMsgEntity(); e.setName(a); e.setMsgType(true); e.setText(b); e.setDate(getDate()); mDataArrays.add(e); mAdapter.notifyDataSetChanged(); cList.setSelection(cList.getCount() - 1); }
最后不要忘了配置相关权限,
<!-- 添加联网权限 --> <uses-permission android:name="android.permission.INTERNET" />
接下去看服务端代码:
public class MultiThreadServer { private int port=8888; private ServerSocket serverSocket; private static ExecutorService executorService;//线程池 private final int POOL_SIZE=10;//单个CPU线程池大小 static HashMap<String, Socket> map=new HashMap<String, Socket>();//保存链接 public MultiThreadServer() throws IOException{ serverSocket=new ServerSocket(port); //Runtime的availableProcessor()方法返回当前系统的CPU数目. setExecutorService(Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()*POOL_SIZE)); System.out.println("服务器启动"); } public void service(){ while(true){ Socket socket=null; try { //接收客户连接,只要客户进行了连接,就会触发accept();从而建立连接 socket=serverSocket.accept(); getExecutorService().execute(new Handler(socket)); } catch (Exception e) { e.printStackTrace(); } } } public static void main(String[] args) throws IOException { new MultiThreadServer().service(); } public static ExecutorService getExecutorService() { return executorService; } public void setExecutorService(ExecutorService executorService) { MultiThreadServer.executorService = executorService; } } class Handler implements Runnable{ private Socket socket; public Handler(Socket socket){ this.socket=socket; } public void run(){ DataInputStream dis = null; DataOutputStream dos = null; try { while (true) { System.out.println("正在等待客户连接..."); // 这里处于等待状态,如果没有客户端连接,程序不会向下执行 dis = new DataInputStream(socket.getInputStream()); dos = new DataOutputStream(socket.getOutputStream()); // 读取数据 String fp = dis.readUTF(); String tp = dis.readUTF(); String clientStr = dis.readUTF(); System.out.println("---客户端已成功连接---"); MultiThreadServer.map.put(fp, socket); // 得到客户端的IP System.out.println("客户端的IP=" + socket.getInetAddress()); // 得到客户端的端口号 System.out.println("客户端的端口号=" + socket.getPort()); // 得到本地端口号 System.out.println("本地服务器端口号=" + socket.getLocalPort()); System.out.println("信息:" + fp +"对"+ tp +"说:"+ clientStr); System.out.println("---------------------------------"); //判断接收方 是否在线 if(MultiThreadServer.map.containsKey(tp)){ Socket socket1=MultiThreadServer.map.get(tp); DataOutputStream out=new DataOutputStream(socket1.getOutputStream()); out.writeUTF(fp); out.writeUTF(clientStr); out.flush(); }else{ // 写出数据 dos.writeUTF("错误*001\n我不在线"); dos.writeUTF(tp); } //消息转发不能新建一个socket,原来端口被占用 会报错 // MultiThreadServer.getExecutorService().execute(new Handler1(socket.getInetAddress().toString(),socket.getPort(),clientStr,fp)); } }catch (EOFException e) { System.out.println("这是合法的,客户端连接已断开"); }catch (IOException e) { e.printStackTrace(); } finally { try { if (dis != null) { dis.close(); } if (dos != null) { dos.close(); } // if(socket!=null){ // socket.close(); // } } catch (IOException e) { e.printStackTrace(); } } } }
下面看一下运行效果:
如上图,是自己发送消息给自己,下图为发送给别人。
安卓文本聊天的至此完结,虽然还有很多不足,以后有机会再改了。