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玩剩下的功能.另外,新版支持微信运动查看步数图表. ...
随机推荐
- Linux静态库和动态库
Linux 工具 ❑ GCC: The GNU Compiler Collection, containing the GNU C compiler❑ G++: A C++ compiler, inc ...
- redhat6修改主机名
1.临时修改主机名 sudo hostname lyhost 2.永久修改主机名 vim /etc/sysconfig/network 修改里面的hostname字段即可,重启后生效.
- 安卓RadioButton的使用
学习目的: 1.掌握在Android中如何建立RadioGroup和RadioButton 2.掌握RadioGroup的常用属性 3.理解RadioButton和CheckBox的区别 4.掌握Ra ...
- 什么是A股、B股、H股、蓝筹股、红筹股
A股 A股的正式名称是人民币普通股票.它是由我同境内的公司发行,供境内机构.组织或个人(不含台.港.澳投资者)以人民币认购和交易的普通股股票,我国A股股票市场经过几年快速发展,已经初具规模. B股 B ...
- 本博客不再更新,欢迎访问本人托管在GitHub上的博客:www.wshunli.com
本博客不再更新. 欢迎访问本人托管在GitHub上的博客:www.wshunli.com
- CentOS7安装配置FTP服务器
假设我们有以下要求 路径 权限 备注 /ftp/open 公司所有人员包括来宾均可以访问 只读 /ftp/private 仅允许Alice.Jack.Tom三个人访问 Alice.Jack只允许下载, ...
- CentOS 加载/挂载 U盘
1.以root用户登陆 先加载USB模块 modprobe usb-storage 用fdisk -l 看看U盘的设备 假如U盘是sda1 2.确定在 目录 /mnt 下建立了 文件夹 ...
- Linux系统安装MySQL步骤及支持远程操作配置方法
一.数据库安装(安装在/usr/local目录) 1. 压缩包拷贝到/users/lengyufang/tools 2. groupadd mysql3. useradd -r -g mysql -s ...
- Docker基础技术:AUFS
AUFS是一种Union File System,所谓UnionFS就是把不同物理位置的目录合并mount到同一个目录中.UnionFS的一个最主要的应用是,把一张CD/DVD和一个硬盘目录给联合 m ...
- 卷积神经网络和CIFAR-10:Yann LeCun专访 Convolutional Nets and CIFAR-10: An Interview with Yann LeCun
Recently Kaggle hosted a competition on the CIFAR-10 dataset. The CIFAR-10 dataset consists of 60k 3 ...