在这只做了一个简单的例子,没有用到数据库,思路就是客户端发送信息到服务器端,服务器端转发所有数据到客户端,校验服务器端发来消息是否是自己发出的,如果是自己发出的,则不显示自己的消息
贴一下Android客户端的源码 -
MainActivity.Java
package com.zml.chatproject;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;
import com.google.gson.Gson;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
/**
* @author 郑明亮 @email 1072307340@qq.com
* @Time:2016/4/20 14:25
* @version 1.0
* TODO
*/
public class MainActivity extends AppCompatActivity implements View.OnClickListener, TextWatcher {
private static final String TAG = "MainActivity";
public static final int SENDMESSAGE = 0x004;
public static final String name = System.currentTimeMillis()+"";
List<Msg> list ;
ListView mListView;
EditText edit;
Button bt_send;
Socket socket;
public static final int SHOWMSG = 0x003;
private DataInputStream mDataInputStream = null;
private DataOutputStream mDataOutputStream = null;
private boolean Conneted = false;
Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.i(TAG,"执行到handle");
if (msg.what == SENDMESSAGE) {
Msg xiaoxi = (Msg) msg.obj;
Log.i(TAG,"handler:"+xiaoxi.toString());
list.add(xiaoxi);
//设置适配器
mListView.setAdapter(new MyAdapter(MainActivity.this, list));
mListView.setSelection(mListView.getCount()-1);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mListView = (ListView) findViewById(R.id.listView);
edit = (EditText) findViewById(R.id.et_edit);
edit.addTextChangedListener(this);
bt_send = (Button) findViewById(R.id.bt_send);
bt_send.setOnClickListener(this);
list = new ArrayList<>();
new AsyncTask<Void,Void,String>(){
@Override
protected String doInBackground(Void... params) {
try {
socket = new Socket("172.18.40.182", 9999);
// socket = new Socket("115.28.167.152", 9999);
connect();
ClientThread thread = new ClientThread();
thread.run();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}.execute();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (event.getAction()){
case KeyEvent.KEYCODE_HOME:
Toast.makeText(MainActivity.this,"就是不让你退出,O(∩_∩)O哈哈哈~",Toast.LENGTH_LONG).show();
Log.i(TAG,"KeyEvent.KEYCODE_HOME"+KeyEvent.KEYCODE_HOME);
break;
case KeyEvent.KEYCODE_MOVE_HOME:
Toast.makeText(MainActivity.this,"就是不让你退出,O(∩_∩)O哈哈哈~",Toast.LENGTH_LONG).show();
Log.i(TAG,"KeyEvent.KEYCODE_MOVE_HOME"+KeyEvent.KEYCODE_MOVE_HOME);
break;
}
return true;
}
@Override
public void onAttachedToWindow()
{ // TODO Auto-generated method stub
this.getWindow().setType(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
super.onAttachedToWindow();
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.bt_send:
String show = edit.getText().toString().trim();
if (TextUtils.isEmpty(show)){
}else {
edit.setText("");
Msg msg = new Msg();
msg.setFlag(Msg.TO);
msg.setMsg(show);
msg.setUsername(name);
list.add(msg);
mListView.setAdapter(new MyAdapter(MainActivity.this,list));
mListView.setSelection(mListView.getCount()-1);
try {if (mDataOutputStream==null){
mDataOutputStream = new DataOutputStream(socket.getOutputStream());
}
Gson gson = new Gson();
show = gson.toJson(msg);
mDataOutputStream.writeUTF(show);
mDataOutputStream.flush();
Log.i(TAG,"发送成功:"+show);
} catch (IOException e) {
e.printStackTrace();
}
}
break;
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
bt_send.setEnabled(false);
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (s.length()>0){
bt_send.setEnabled(true);
}
}
@Override
public void afterTextChanged(Editable s) {
}
/**
* 开启线程,接收消息
*/
private class ClientThread implements Runnable {
@Override
public void run() {
while (Conneted) {
try {
String str = mDataInputStream.readUTF();
Log.i(TAG,"子线程得到数据:"+str);
Gson gson = new Gson();
Msg msg = gson.fromJson(str,Msg.class);
msg.setFlag(Msg.FROM);
Message message = mHandler.obtainMessage();
message.what = SENDMESSAGE;
message.obj = msg;
mHandler.sendMessage(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 打开连接
*/
public void connect() {
try {
mDataInputStream = new DataInputStream(socket.getInputStream());
mDataOutputStream = new DataOutputStream(socket.getOutputStream());
if (socket.isConnected()){
Log.i(TAG, "连接上了");
}else {
Log.i(TAG, "连接失败");
}
Conneted = true;
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 断开与服务器的连接
*/
public void disconnect() {
try {
mDataInputStream.close();
mDataOutputStream.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
disconnect();
}
}
Msg.java 消息实体类
package com.zml.chatproject;
/**
* Created by bri on 2016/4/16.
*/
/**
* 消息实体类
*/
public class Msg {
public static final int FROM = 0x001;
public static final int TO = 0x002;
/**
* 发送聊天消息
*/
private String msg;
/**
* 标识符,表示是发送方还是接收方
*/
private int flag;
/**
* 用户名
*/
private String username;
@Override
public String toString() {
return "Msg{" +
"msg='" + msg + '\\'' +
", flag=" + flag +
", username='" + username + '\\'' +
'}';
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public int getFlag() {
return flag;
}
public void setFlag(int flag) {
this.flag = flag;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
MyAdapter 数据适配器
package com.zml.chatproject;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListAdapter;
import android.widget.TextView;
import java.util.List;
/**
* Created by bri on 2016/4/17.
*/
public class MyAdapter extends BaseAdapter implements ListAdapter {
private static final String TAG = "MyAdapter";
Context context;
List<Msg> message;
public MyAdapter(Context context, List<Msg> message) {
this.context = context;
this.message = message;
}
@Override
public int getCount() {
return message.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null){
convertView = LayoutInflater.from(context).inflate(R.layout.activity_main_item,null);
}
TextView tv_from = ViewHolder.get(convertView,R.id.tv_chatting_from);
TextView tv_to = ViewHolder.get(convertView,R.id.tv_chatting_to);
// tv_from.setText(message.getMsg());
Log.i(TAG,"接收成功"+message.get(position).getMsg());
if (message.get(position).getFlag()==(Msg.FROM)){
if (message.get(position).getUsername().equals(MainActivity.name)){
tv_from.setVisibility(View.GONE);
tv_to.setVisibility(View.GONE);}
else { Log.i(TAG,"接收成功FROM"+message.get(position).getMsg());
tv_from.setText(message.get(position).getMsg());
tv_from.setVisibility(View.VISIBLE);
tv_to.setVisibility(View.GONE);}
// Toast.makeText(context,"from:"+message.get(position).getMsg(),Toast.LENGTH_LONG).show();
}if (message.get(position).getFlag()==(Msg.TO)){
// Toast.makeText(context,"to:"+message.get(position).getMsg(),Toast.LENGTH_LONG).show();
Log.i(TAG,"接收成功TO"+message.get(position).getMsg());
tv_to.setText(message.get(position).getMsg());
tv_from.setVisibility(View.GONE);
tv_to.setVisibility(View.VISIBLE);
}
return convertView;
}
}
ViewHoder 一个超实用的通用ViewHoder类
package com.zml.chatproject;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListAdapter;
import android.widget.TextView;
import java.util.List;
/**
* Created by bri on 2016/4/17.
*/
public class MyAdapter extends BaseAdapter implements ListAdapter {
private static final String TAG = "MyAdapter";
Context context;
List<Msg> message;
public MyAdapter(Context context, List<Msg> message) {
this.context = context;
this.message = message;
}
@Override
public int getCount() {
return message.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null){
convertView = LayoutInflater.from(context).inflate(R.layout.activity_main_item,null);
}
TextView tv_from = ViewHolder.get(convertView,R.id.tv_chatting_from);
TextView tv_to = ViewHolder.get(convertView,R.id.tv_chatting_to);
// tv_from.setText(message.getMsg());
Log.i(TAG,"接收成功"+message.get(position).getMsg());
if (message.get(position).getFlag()==(Msg.FROM)){
if (message.get(position).getUsername().equals(MainActivity.name)){
tv_from.setVisibility(View.GONE);
tv_to.setVisibility(View.GONE);}
else { Log.i(TAG,"接收成功FROM"+message.get(position).getMsg());
tv_from.setText(message.get(position).getMsg());
tv_from.setVisibility(View.VISIBLE);
tv_to.setVisibility(View.GONE);}
// Toast.makeText(context,"from:"+message.get(position).getMsg(),Toast.LENGTH_LONG).show();
}if (message.get(position).getFlag()==(Msg.TO)){
// Toast.makeText(context,"to:"+message.get(position).getMsg(),Toast.LENGTH_LONG).show();
Log.i(TAG,"接收成功TO"+message.get(position).getMsg());
tv_to.setText(message.get(position).getMsg());
tv_from.setVisibility(View.GONE);
tv_to.setVisibility(View.VISIBLE);
}
return convertView;
}
}
好了,客户端的源码贴完了,接下来服务器端的源码就比较简单了
Client.java 重写一个子线程
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/**
* @author 郑明亮
* @Time:2016年4月16日 下午9:01:53
* @version 1.0
*/
public class Client implements Runnable {
Socket socket;
List<Client> clients ;
public static final int SHOWMSG = 0x003;
private DataInputStream mDataInputStream = null;
private DataOutputStream mDataOutputStream = null;
private boolean Conneted = false;
public Client(Socket socket){
this.socket = socket;
try {
mDataInputStream = new DataInputStream(socket.getInputStream());
mDataOutputStream = new DataOutputStream(socket.getOutputStream());
Conneted = true;
clients =new ArrayList<Client>();
} catch (IOException e) {
e.printStackTrace();
}
};
/**
* 发送消息
*/
public void send(String string){
try {
mDataOutputStream.writeUTF(string);//向输入流中写入数据
System.out.println("向输入流中写入数据");
} catch (IOException e) {
e.printStackTrace();
// Server.clients.remove(this);//出错时,客户端可能已断线,移除当前客户端
System.out.println("出错时,客户端可能已断线,移除当前客户端");
}
}
@Override
public void run() {
while(Conneted){
try {
System.out.println("连接成功!");
//读取数据
String str = mDataInputStream.readUTF();
clients = Server.clients;
synchronized (clients) {
Iterator<Client> iterator =clients.iterator();
while (iterator.hasNext()) {
Client client = iterator.next();
//将读取的数据发送回去
System.out.println("将读取的数据发送回去"+str);
client.send(str);
}
// Conneted = false;
}
} catch (IOException e) {
e.printStackTrace();
Server.clients.remove(this);
System.out.println("线程出现异常");
}finally{
// try {
//// mDataOutputStream.close();
//// mDataInputStream.close();
// } catch (IOException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
}
}
}
}
Server 服务器端,先运行起它来,再去部署客户端即可
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* @author 郑明亮
* @Time:2016年4月16日 下午9:01:43
* @version 1.0
*/
public class Server {
static boolean started = false;
public static List<Client> clients = new ArrayList<>();
public static void main(String a[]){
try {
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("开启服务,等待监听");
started = true;
while (started) {
System.out.println("开始监听");
Socket socket = serverSocket.accept();
Client client = new Client(socket);
new Thread(client).start();
clients.add(client);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}