基本信息
源码名称:仿QQ 聊天源码(含数据库脚本、客户端、服务端完整源码)
源码大小:2.68M
文件格式:.zip
开发语言:Java
更新时间:2015-08-18
友情提示:(无需注册或充值,赞助后即可获取资源下载链接)
嘿,亲!知识可是无价之宝呢,但咱这精心整理的资料也耗费了不少心血呀。小小地破费一下,绝对物超所值哦!如有下载和支付问题,请联系我们QQ(微信同号):813200300
本次赞助数额为: 2 元×
微信扫码支付:2 元
×
请留下您的邮箱,我们将在2小时内将文件发到您的邮箱
源码介绍
服务端:
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; } } }