Android之Socket群组聊天
在这只做了一个简单的例子,没有用到数据库,思路就是客户端发送信息到服务器端,服务器端转发所有数据到客户端,校验服务器端发来消息是否是自己发出的,如果是自己发出的,则不显示自己的消息
- 贴一下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();
- }
- }
- }
Android之Socket群组聊天的更多相关文章
- Android 内置群组,联系人
这样一个需求,手机第一次启动的时候,需要内置一个群组,并且里面有给定的联系人信息, 本来打算写双进程守护的,结果昨天接到一个这样的任务,就先把它做了,发现里面有些操作数据库的东西还是值得看一下. 首先 ...
- vue-cli3.0 Typescript 项目集成环信WebIM 群组聊天
项目背景 环信webim 官方没有vue版本的,自己就根据sdk重写了个vue版本的,只实现了基础的 登录 群组功能,其他的可以根据需要参考官方文档,添加相应的功能. 环信webim SDK相关文档: ...
- ASP.NET SignalR 系列(五)之群组推送
在上一章介绍了 一对一推送的方式,这章重点介绍下群组推送和多人推送 群组主要就是用到了方法:Groups.Add(Context.ConnectionId, groupName); 将不同的连接id加 ...
- nodejs之socket.io 私发消息和选择群组发消息
写在前面:其实有的时候忙碌是好的,比如忙碌起来的自己手机可以一天耗费掉只有20%的电,忙碌的自己很专心于一件事情,但是忙碌不等于过度疲劳,本周忙碌有点上脑,迷糊了一天,都在补觉,还是要去平衡下自己一天 ...
- Android 基于Socket的聊天应用(二)
很久没写BLOG了,之前在写Android聊天室的时候答应过要写一个客户(好友)之间的聊天demo,Android 基于Socket的聊天室已经实现了通过Socket广播形式的通信功能. 以下是我写的 ...
- java ssm 后台框架平台 项目源码 websocket即时聊天发图片文字 好友群组 SSM源码
官网 http://www.fhadmin.org/D 集成安全权限框架shiro Shiro 是一个用 Java 语言实现的框架,通过一个简单易用的 API 提供身份验证和授权,更安全,更可靠E ...
- Activiti6.0 工作流引擎 websocket即时聊天发图片文字 好友群组 SSM源码
即时通讯:支持好友,群组,发图片.文件,消息声音提醒,离线消息,保留聊天记录 (即时聊天功能支持手机端,详情下面有截图) 工作流模块---------------------------------- ...
- java工作流引擎 Activiti6.0 websocket 即时聊天发图片文字 好友群组 SSM源码
时通讯:支持好友,群组,发图片.文件,消息声音提醒,离线消息,保留聊天记录 工作流模块--------------------------------------------------------- ...
- Android/iOS微信6.3.5同时发布更新 支持群视频聊天、群公告
下午微信6.3.5发布更新,新版最大变化就是支持群视频聊天,又一次向手机QQ靠拢.在群管理方面,支持发布群公告,支持群主转让给其他群成员,同样都是QQ玩剩下的功能.另外,新版支持微信运动查看步数图表. ...
随机推荐
- 李洪强经典iOS面试题11
#import 跟#include 又什么区别,@class呢, #import<> 跟 #import””又什么区别? #import是Objective-C导入头文件的关键字, ...
- 540B :School Marks
题目链接 题意: 输入: 第一个: n k p x y 第二行:k个数 n: 数的数量 k:n个数中已经知道的k个数 p:n个数取值的上界,下界是1 x:n个数的和的上界x y:n个数的中位数至少是 ...
- React编写文本评论框
一.需求分析 二.代码 <!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset= ...
- Java-数据结构与算法-逢3减1
1.要求:有一群人围成一圈数数,逢3退1人,要求算出最后留下来的人的下标 2.代码: package Test; public class Count3Quit1 { //要求:有一群人围成一圈数数, ...
- linux下python启动第三方程序,并控制关闭
import subprocess import os import signal p = subprocess.Popen("recordmydesktop -o /home/test/t ...
- iOS:Git分布式版本控制器系统
Git的使用 1.Git简介: Git是一个开源的分布式版本控制系统.与SVN.CVS相比 分布式 不需要中心仓库 Git的版本号都是生成的一个哈希值,比如:bbaf6fb5060b4875b1 ...
- Cocos2dx+lua中Color参数的坑
cocos2x的lua中有如下几种颜色定义 --Color3B function cc.c3b( _r,_g,_b ) return { r = _r, g = _g, b = _b } end -- ...
- java 无法找到main类解决办法
java 无法找到main类解决办法 如果Java类有包名,你必须建相应的包文件夹并把文件编译或拷贝到到相应的文件夹下: 如下: 1.源文件文件: E:\test\src\tes ...
- QQ2013手工去广告
QQ的广告令人讨厌,虽然网上有很多去广告补丁或者是去广告版,但是总是害怕有被盗号的风险,那除了付费会员还有其他什么方法可以安全的去除qq广告吗?显然有,那就是手动去广告. 很简单,不会比使用去广告补丁 ...
- flex 实时更新的一些方法总结
诚为大家所知,Flash之所以优秀,就是它可以带来良好的用户体验和交互特性.既然涉及到交互性,开发人员在开发过程中必然会遇到实时更新的问题,那么,当后台数据发现变化的时候,如何让Flash端实时刷新显 ...