实例介绍
【实例简介】
【实例截图】
【核心代码】
服务端:
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小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明
网友评论
我要评论