Android聊天工具基于socket实现
特简单,没有数据库,还没有处理各种异常。
登录:输入用户名点击的登录即可。
发送消息:特定格式->toUser:message
1.服务器:保存在线用户
publicclassOnline{ privatestaticOnlinemOnline=null; privateLinkedHashMap<String,Socket>mOnlines=newLinkedHashMap<String,Socket>(); privateOnline(){ } publicsynchronizedstaticOnlinegetInstance(){ if(null==mOnline){ mOnline=newOnline(); } returnmOnline; } publicvoidput(Stringkey,Socketsocket){ if(!mOnlines.containsKey(key)){ mOnlines.put(key,socket); } } publicSocketget(Stringkey){ returnmOnlines.get(key); } publicvoidremove(Stringkey){ mOnlines.remove(key); } }
2.服务器:一个简单的socket服务器
importjava.io.BufferedReader; importjava.io.IOException; importjava.io.InputStreamReader; importjava.io.PrintWriter; importjava.net.ServerSocket; importjava.net.Socket; //login:uid //send:fromuser:touser:message //logout:uid publicclassServerimplementsRunnable{ privateSocketmSocket; privateOnlinemOnline; publicServer(Socketsocket){ mSocket=socket; mOnline=Online.getInstance(); } @Override publicvoidrun(){ try{ BufferedReaderreader=newBufferedReader(newInputStreamReader( mSocket.getInputStream())); Stringcmd=reader.readLine(); //login if(cmd.startsWith("login")){ StringuserName=cmd.split(":")[1]; mOnline.put(userName,mSocket); System.out.println(userName+"login..."); PrintWriterwriter=newPrintWriter(mSocket.getOutputStream()); writer.println("success"); writer.flush(); }elseif(cmd.startsWith("send")){ System.out.println(cmd); String[]cmds=cmd.split(":"); Stringfrom=cmds[1]; Socketto=mOnline.get(cmds[2]); Stringmsg=cmds[3]; PrintWriterwriter=newPrintWriter(to.getOutputStream()); System.out.println("rec:"+from+":"+cmds[2]+":"+msg); writer.println("rec:"+from+":"+cmds[2]+":"+msg); writer.flush(); }elseif(cmd.startsWith("logout")){ System.out.println(cmd); Stringuser=cmd.split(":")[1]; mOnline.get(user).close(); mOnline.remove(user); PrintWriterwriter=newPrintWriter(mSocket.getOutputStream()); writer.println("success"); writer.flush(); } }catch(Exceptione){ e.printStackTrace(); } } publicstaticvoidmain(String[]args)throwsException{ ServerSocketserver=newServerSocket(8888); booleanflag=true; while(flag){ newThread(newServer(server.accept())).start(); System.out.println("userin..."); } server.close(); } }
3.客户端登录界面
publicclassMainActivityextendsActivity{ privateEditTextmUser; @Override protectedvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mUser=(EditText)findViewById(R.id.username); } publicvoidlogin(Viewview){ finalStringuserName=mUser.getText().toString().trim(); Loginlogin=newLogin(userName); login.setOnLoginListener(newLogin.LoginCallback(){ @Override publicvoidonLogin(booleansuccess){ if(success){ Intentintent=newIntent(MainActivity.this,Chat.class); intent.putExtra("user",userName); startActivity(intent); finish(); }else{ Toast.makeText(MainActivity.this,"登录失败",Toast.LENGTH_SHORT).show(); } } }); login.login(); } }
4.处理登录
publicclassLogin{ privateStringmUserName; privateLoginCallbackmCallback; publicLogin(StringuserName){ mUserName=userName; } publicvoidsetOnLoginListener(LoginCallbackcallback){ mCallback=callback; } privateHandlermHandler=newHandler(){ publicvoidhandleMessage(Messagemsg){ switch(msg.what){ caseConstant.SUCCESS: mCallback.onLogin(true); break; caseConstant.FAILED: mCallback.onLogin(false); break; } }; }; publicvoidlogin(){ newThread(newRunnable(){ @Override publicvoidrun(){ Socketsocket=null; try{ socket=newSocket(); socket.connect(newInetSocketAddress("192.168.100.100",8888),4000); PrintWriterwriter=newPrintWriter(socket.getOutputStream()); writer.println("login:"+mUserName); writer.flush(); BufferedReaderreader=newBufferedReader( newInputStreamReader(socket.getInputStream())); Stringline=reader.readLine(); System.out.println(line); if("success".equals(line)){ PConnection.socket=socket; mHandler.sendEmptyMessage(Constant.SUCCESS); }else{ mHandler.sendEmptyMessage(Constant.FAILED); } }catch(Exceptione){ e.printStackTrace(); } } }).start(); } publicinterfaceLoginCallback{ publicvoidonLogin(booleansuccess); } }
5.聊天界面
publicclassChatextendsActivity{ privateStringmUserName; privateEditTextmEdit; privateListViewmMessage; privateReceiverMessagemRecMessage; privateSendMessagemSendMesage; privateList<Map<String,String>>mData=newArrayList<Map<String,String>>(); privateMessagesAdaptermAdapter; @Override protectedvoidonCreate(BundlesavedInstanceState){ 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=newReceiverMessage(); mRecMessage.setOnReceiverListener(newRecListener()); mRecMessage.run(); mSendMesage=newSendMessage(); mSendMesage.setOnSendListener(newSendListener()); mAdapter=newMessagesAdapter(this,mData); mMessage.setAdapter(mAdapter); } publicvoidsend(Viewview){ String[]content=mEdit.getText().toString().trim().split(":"); mSendMesage.send(mUserName,content[0],content[1]); } privateclassRecListenerimplementsReceiverMessage.OnReceiverListener{ @Override publicvoidonReceiver(Stringuser,Stringmsg){ Map<String,String>temp=newHashMap<String,String>(); temp.put("user",user); temp.put("msg",msg); temp.put("pos","right"); mData.add(temp); mAdapter.notifyDataSetChanged(); } } privateclassSendListenerimplementsSendMessage.OnSendListener{ @Override publicvoidonSend(String[]msg){ Map<String,String>temp=newHashMap<String,String>(); temp.put("user","我"); temp.put("msg",msg[1]); temp.put("pos","left"); mData.add(temp); mAdapter.notifyDataSetChanged(); } } @Override publicbooleanonOptionsItemSelected(MenuItemitem){ if(R.id.logout==item.getItemId()){ Logoutlogout=newLogout(); logout.setOnLogoutListener(newLogout.OnLogoutListener(){ @Override publicvoidonLogout(booleansuccess){ if(success){ Toast.makeText(Chat.this,"注销成功",Toast.LENGTH_SHORT).show(); finish(); }else{ Toast.makeText(Chat.this,"注销失败",Toast.LENGTH_SHORT).show(); } } }); logout.logout(mUserName); } returnsuper.onOptionsItemSelected(item); } @Override publicbooleanonCreateOptionsMenu(Menumenu){ getMenuInflater().inflate(R.menu.main,menu); returnsuper.onCreateOptionsMenu(menu); } }
6.发送消息
publicclassSendMessage{ privateOnSendListenermListener; publicvoidsetOnSendListener(OnSendListenerlistener){ mListener=listener; } privateHandlermHandler=newHandler(){ publicvoidhandleMessage(Messagemsg){ mListener.onSend((String[])msg.obj); }; }; //send:from:to:message publicvoidsend(finalStringfrom,finalStringto,finalStringmsg){ newThread(newRunnable(){ @Override publicvoidrun(){ Socketsocket=null; try{ socket=newSocket(); socket.connect(newInetSocketAddress("192.168.100.100",8888),4000); PrintWriterwriter=newPrintWriter(socket.getOutputStream()); writer.println("send:"+from+":"+to+":"+msg); writer.flush(); Messagemessage=mHandler.obtainMessage( Constant.SUCCESS,newString[]{to,msg}); message.sendToTarget(); }catch(Exceptione){ }finally{ try{ socket.close(); }catch(IOExceptione){ e.printStackTrace(); } } } }).start(); } publicinterfaceOnSendListener{ publicvoidonSend(String[]msg); } }
7.接收消息,死循环,但阻塞,没啥问题
publicclassReceiverMessage{ privateOnReceiverListenermListener; publicvoidsetOnReceiverListener(OnReceiverListenerlistener){ mListener=listener; } privateHandlermHandler=newHandler(){ publicvoidhandleMessage(Messagemsg){ String[]cmds=(String[])msg.obj; mListener.onReceiver(cmds[0],cmds[1]); }; }; publicvoidrun(){ newThread(newRunnable(){ @Override publicvoidrun(){ try{ Socketsocket=PConnection.socket; while(true){ System.out.println("waitformessage..."); BufferedReaderreader=newBufferedReader( newInputStreamReader(socket.getInputStream())); Stringline=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]); Messagemsg=mHandler.obtainMessage(Constant.SUCCESS,newString[]{cmds[1],cmds[3]}); msg.sendToTarget(); } } }catch(Exceptione){ e.printStackTrace(); } } }).start(); } publicinterfaceOnReceiverListener{ publicvoidonReceiver(Stringuser,Stringmsg); } }
8.注销登录
publicclassLogout{ publicOnLogoutListenermListener; publicvoidsetOnLogoutListener(OnLogoutListenerlistner){ mListener=listner; } privateHandlermHandler=newHandler(){ publicvoidhandleMessage(Messagemsg){ if(Constant.SUCCESS==msg.what){ mListener.onLogout(true); }else{ mListener.onLogout(false); } }; }; publicvoidlogout(finalStringuser){ newThread(newRunnable(){ @Override publicvoidrun(){ try{ Socketsocket=newSocket(); socket.connect(newInetSocketAddress("192.168.100.100",8888),4000); PrintWriterwriter=newPrintWriter(socket.getOutputStream()); writer.println("logout:"+user); writer.flush(); BufferedReaderreader=newBufferedReader( newInputStreamReader(socket.getInputStream())); if("success".equals(reader.readLine())){ PConnection.socket=null; mHandler.sendEmptyMessage(Constant.SUCCESS); }else{ mHandler.sendEmptyMessage(Constant.FAILED); } }catch(Exceptione){ e.printStackTrace(); } } }).start(); } publicinterfaceOnLogoutListener{ publicvoidonLogout(booleansuccess); } }
9.存放登录后的socket,在发送消息和接收消息时使用该socket
publicclassPConnection{ publicstaticSocketsocket; }
希望本文所述对大家学习有所帮助。