实例介绍
【实例简介】
【实例截图】
【核心代码】
服务端:
package com.way.chat.server;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import com.way.chat.common.bean.TextMessage;
import com.way.chat.common.bean.User;
import com.way.chat.common.tran.bean.TranObject;
import com.way.chat.common.tran.bean.TranObjectType;
import com.way.chat.common.util.MyDate;
import com.way.chat.dao.UserDao;
import com.way.chat.dao.impl.UserDaoFactory;
/**
* 读消息线程和处理方法
*
* @author way
*
*/
public class InputThread extends Thread {
private Socket socket;// socket对象
private OutputThread out;// 传递进来的写消息线程,因为我们要给用户回复消息啊
private OutputThreadMap map;// 写消息线程缓存器
private ObjectInputStream ois;// 对象输入流
private boolean isStart = true;// 是否循环读消息
public InputThread(Socket socket, OutputThread out, OutputThreadMap map) {
this.socket = socket;
this.out = out;
this.map = map;
try {
ois = new ObjectInputStream(socket.getInputStream());// 实例化对象输入流
} catch (IOException e) {
e.printStackTrace();
}
}
public void setStart(boolean isStart) {// 提供接口给外部关闭读消息线程
this.isStart = isStart;
}
@Override
public void run() {
try {
while (isStart) {
// 读取消息
readMessage();
}
if (ois != null)
ois.close();
if (socket != null)
socket.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 读消息以及处理消息,抛出异常
*
* @throws IOException
* @throws ClassNotFoundException
*/
public void readMessage() throws IOException, ClassNotFoundException {
Object readObject = ois.readObject();// 从流中读取对象
UserDao dao = UserDaoFactory.getInstance();// 通过dao模式管理后台
if (readObject != null && readObject instanceof TranObject) {
TranObject read_tranObject = (TranObject) readObject;// 转换成传输对象
switch (read_tranObject.getType()) {
case REGISTER:// 如果用户是注册
User registerUser = (User) read_tranObject.getObject();
int registerResult = dao.register(registerUser);
System.out.println(MyDate.getDateCN() " 新用户注册:"
registerResult);
// 给用户回复消息
TranObject<User> register2TranObject = new TranObject<User>(
TranObjectType.REGISTER);
User register2user = new User();
register2user.setId(registerResult);
register2TranObject.setObject(register2user);
out.setMessage(register2TranObject);
break;
case LOGIN:
User loginUser = (User) read_tranObject.getObject();
ArrayList<User> list = dao.login(loginUser);
TranObject<ArrayList<User>> login2Object = new TranObject<ArrayList<User>>(
TranObjectType.LOGIN);
if (list != null) {// 如果登录成功
TranObject<User> onObject = new TranObject<User>(
TranObjectType.LOGIN);
User login2User = new User();
login2User.setId(loginUser.getId());
onObject.setObject(login2User);
for (OutputThread onOut : map.getAll()) {
onOut.setMessage(onObject);// 广播一下用户上线
}
map.add(loginUser.getId(), out);// 先广播,再把对应用户id的写线程存入map中,以便转发消息时调用
login2Object.setObject(list);// 把好友列表加入回复的对象中
} else {
login2Object.setObject(null);
}
out.setMessage(login2Object);// 同时把登录信息回复给用户
System.out.println(MyDate.getDateCN() " 用户:"
loginUser.getId() " 上线了");
break;
case LOGOUT:// 如果是退出,更新数据库在线状态,同时群发告诉所有在线用户
User logoutUser = (User) read_tranObject.getObject();
int offId = logoutUser.getId();
System.out
.println(MyDate.getDateCN() " 用户:" offId " 下线了");
dao.logout(offId);
isStart = false;// 结束自己的读循环
map.remove(offId);// 从缓存的线程中移除
out.setMessage(null);// 先要设置一个空消息去唤醒写线程
out.setStart(false);// 再结束写线程循环
TranObject<User> offObject = new TranObject<User>(
TranObjectType.LOGOUT);
User logout2User = new User();
logout2User.setId(logoutUser.getId());
offObject.setObject(logout2User);
for (OutputThread offOut : map.getAll()) {// 广播用户下线消息
offOut.setMessage(offObject);
}
break;
case MESSAGE:// 如果是转发消息(可添加群发)
// 获取消息中要转发的对象id,然后获取缓存的该对象的写线程
int id2 = read_tranObject.getToUser();
OutputThread toOut = map.getById(id2);
if (toOut != null) {// 如果用户在线
toOut.setMessage(read_tranObject);
} else {// 如果为空,说明用户已经下线,回复用户
TextMessage text = new TextMessage();
text.setMessage("亲!对方不在线哦,您的消息将暂时保存在服务器");
TranObject<TextMessage> offText = new TranObject<TextMessage>(
TranObjectType.MESSAGE);
offText.setObject(text);
offText.setFromUser(0);
out.setMessage(offText);
}
break;
case REFRESH:
List<User> refreshList = dao.refresh(read_tranObject
.getFromUser());
TranObject<List<User>> refreshO = new TranObject<List<User>>(
TranObjectType.REFRESH);
refreshO.setObject(refreshList);
out.setMessage(refreshO);
break;
default:
break;
}
}
}
}
客户端:
package com.way.chat.activity;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.way.chat.common.bean.TextMessage;
import com.way.chat.common.bean.User;
import com.way.chat.common.tran.bean.TranObject;
import com.way.chat.common.tran.bean.TranObjectType;
import com.way.chat.common.util.Constants;
import com.way.client.Client;
import com.way.client.ClientOutputThread;
import com.way.util.MessageDB;
import com.way.util.MyDate;
import com.way.util.SharePreferenceUtil;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
/**
* 聊天Activity
*
* @author way
*/
public class ChatActivity extends MyActivity implements OnClickListener {
private Button mBtnSend;// 发送btn
private Button mBtnBack;// 返回btn
private EditText mEditTextContent;
private TextView mFriendName;
private ListView mListView;
private ChatMsgViewAdapter mAdapter;// 消息视图的Adapter
private List<ChatMsgEntity> mDataArrays = new ArrayList<ChatMsgEntity>();// 消息对象数组
private SharePreferenceUtil util;
private User user;
private MessageDB messageDB;
private MyApplication application;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);// 去掉标题栏
setContentView(R.layout.chat);
application = (MyApplication) getApplicationContext();
messageDB = new MessageDB(this);
user = (User) getIntent().getSerializableExtra("user");
util = new SharePreferenceUtil(this, Constants.SAVE_USER);
initView();// 初始化view
initData();// 初始化数据
}
/**
* 初始化view
*/
public void initView() {
mListView = (ListView) findViewById(R.id.listview);
mBtnSend = (Button) findViewById(R.id.chat_send);
mBtnSend.setOnClickListener(this);
mBtnBack = (Button) findViewById(R.id.chat_back);
mBtnBack.setOnClickListener(this);
mFriendName = (TextView) findViewById(R.id.chat_name);
mFriendName.setText(util.getName());
mEditTextContent = (EditText) findViewById(R.id.chat_editmessage);
}
/**
* 加载消息历史,从数据库中读出
*/
public void initData() {
List<ChatMsgEntity> list = messageDB.getMsg(user.getId());
if (list.size() > 0) {
for (ChatMsgEntity entity : list) {
if (entity.getName().equals("")) {
entity.setName(user.getName());
}
if (entity.getImg() < 0) {
entity.setImg(user.getImg());
}
mDataArrays.add(entity);
}
Collections.reverse(mDataArrays);
}
mAdapter = new ChatMsgViewAdapter(this, mDataArrays);
mListView.setAdapter(mAdapter);
mListView.setSelection(mAdapter.getCount() - 1);
}
@Override
protected void onDestroy() {
super.onDestroy();
messageDB.close();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.chat_send:// 发送按钮点击事件
send();
break;
case R.id.chat_back:// 返回按钮点击事件
finish();// 结束,实际开发中,可以返回主界面
break;
}
}
/**
* 发送消息
*/
private void send() {
String contString = mEditTextContent.getText().toString();
if (contString.length() > 0) {
ChatMsgEntity entity = new ChatMsgEntity();
entity.setName(util.getName());
entity.setDate(MyDate.getDateEN());
entity.setMessage(contString);
entity.setImg(util.getImg());
entity.setMsgType(false);
messageDB.saveMsg(user.getId(), entity);
mDataArrays.add(entity);
mAdapter.notifyDataSetChanged();// 通知ListView,数据已发生改变
mEditTextContent.setText("");// 清空编辑框数据
mListView.setSelection(mListView.getCount() - 1);// 发送一条消息时,ListView显示选择最后一项
MyApplication application = (MyApplication) this
.getApplicationContext();
Client client = application.getClient();
ClientOutputThread out = client.getClientOutputThread();
if (out != null) {
TranObject<TextMessage> o = new TranObject<TextMessage>(
TranObjectType.MESSAGE);
TextMessage message = new TextMessage();
message.setMessage(contString);
o.setObject(message);
o.setFromUser(Integer.parseInt(util.getId()));
o.setToUser(user.getId());
out.setMsg(o);
}
// 下面是添加到最近会话列表的处理,在按发送键之后
RecentChatEntity entity1 = new RecentChatEntity(user.getId(),
user.getImg(), 0, user.getName(), MyDate.getDate(),
contString);
application.getmRecentList().remove(entity1);
application.getmRecentList().addFirst(entity1);
application.getmRecentAdapter().notifyDataSetChanged();
}
}
@Override
public void getMessage(TranObject msg) {
// TODO Auto-generated method stub
switch (msg.getType()) {
case MESSAGE:
TextMessage tm = (TextMessage) msg.getObject();
String message = tm.getMessage();
ChatMsgEntity entity = new ChatMsgEntity(user.getName(),
MyDate.getDateEN(), message, user.getImg(), true);// 收到的消息
if (msg.getFromUser() == user.getId() || msg.getFromUser() == 0) {// 如果是正在聊天的好友的消息,或者是服务器的消息
messageDB.saveMsg(user.getId(), entity);
mDataArrays.add(entity);
mAdapter.notifyDataSetChanged();
mListView.setSelection(mListView.getCount() - 1);
MediaPlayer.create(this, R.raw.msg).start();
} else {
messageDB.saveMsg(msg.getFromUser(), entity);// 保存到数据库
Toast.makeText(ChatActivity.this,
"您有新的消息来自:" msg.getFromUser() ":" message, 0)
.show();// 其他好友的消息,就先提示,并保存到数据库
MediaPlayer.create(this, R.raw.msg).start();
}
break;
case LOGIN:
User loginUser = (User) msg.getObject();
Toast.makeText(ChatActivity.this, loginUser.getId() "上线了", 0)
.show();
MediaPlayer.create(this, R.raw.msg).start();
break;
case LOGOUT:
User logoutUser = (User) msg.getObject();
Toast.makeText(ChatActivity.this, logoutUser.getId() "下线了", 0)
.show();
MediaPlayer.create(this, R.raw.msg).start();
break;
default:
break;
}
}
}
好例子网口号:伸出你的我的手 — 分享!
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明


网友评论
我要评论