1 基于Socket的Android聊天室

Socket通信是网络通信中最常用的技术之一,通过Socket建立的可靠连接,可以让多个终端与服务器保持通信,最典型的应用是建立一个多人聊天程序。本实例使用ServerSocket建立聊天服务器。将服务器端所有的通讯线程保存到一个集合当中,当有用户发来数据,则转发给所有用户,实现聊天室效果。Android端通过使用Socket建立客户端链接,并且在AsyncTask中执行网络读写的任务,将用户输入的内容发送到服务器,并接收服务器发来的数据,显示到界面上。开启多个虚拟机模拟多人聊天效果。

1.1Socket聊天基本步骤

1,建立socket服务

2,等待连接

3,将建立的连接放在新的线程里

4,由于每个socket客户端连接相互独立,所以他们之间无法通信

5,使用一个类对新建的客户端线程进行管理,然后实现相互通信,管理类要做成单例,保证唯一性,并通过服务类进行转发来实现客户端相互通信

1.2项目使用说明

1,下载源码 基于Socket的Android聊天室

2,将db_chat.sql导入到mysql数据库

3,将SocketChatServer项目导入到Eclipse,配置Tomcat下运行。

修改hibernate配置文件,改成修改成自己的环境


4,将SocketChat项目导入到Eclipse,配置Android环境并编译运行。

1.3java web服务端

1.3.1开启socket服务线程

使用Servlet init方法中调用启动线程,并在web.xml配置自启动。就可以在服务启动的时候启动socket服务。

package com.jie.socket.chat;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;/** * @ClassName: MyServerSocket.java * @Description: TODO(Socket服务端) * @author yangjie * @version V1.0 * @Date 2016年5月23日 下午3:03:16 */public class MyServerSocket extends HttpServlet {private static final long serialVersionUID = 1L;@Overridepublic void init() throws ServletException {// TODO Auto-generated method stubnew ServerListenerThread().start();// 开启线程System.out.println("开启socket服务…………………………");// 在windows cmd下输入// telnet localhost 12345// 即可建立socket连接}}



1.3.2socket服务监听线程(ServerListenerThread.java)

用于开启socket服务,并进行监听客户端连接

客户端首次接入,传递自己的名称,格式“name:***”

将连接的客户端,传入到客户端管理类中。

package com.jie.socket.chat;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.net.ServerSocket;import java.net.Socket;import javax.swing.JOptionPane;/** * @ClassName: ServerListenerThread.java * @Description: TODO(ServerSoket监听线程) * @author yangjie * @version V1.0 * @Date 2016年5月23日 下午3:38:17 */public class ServerListenerThread extends Thread {int i=1001;@Overridepublic void run() {// TODO Auto-generated method stubsuper.run();try {ServerSocket serverSocket = new ServerSocket(12345);// 循环监听连接while (true) {// 阻塞blockSocket socket = serverSocket.accept();// 建立连接// 在浏览器中输入:http://localhost:12345/// 会弹出提示框,点击确定后断开连接//JOptionPane.showMessageDialog(null, "有客户端连接到本机");// 将Socket传递给新的线程,每个socket享受独立的连接// new ChatSocket(socket).start();//开启chatSocket线程BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "utf-8"));String line = null;String name = null;if ((line = br.readLine())!=null) {//接收到客户端数据if(line.indexOf("name:")!=-1){name = line.substring(line.indexOf("name:")+5);System.out.println(name+":连接到本机");}}//br.close();//关闭输入流ChatSocket chatSocket = new ChatSocket(socket, name);chatSocket.start();ChatManager.getChatManager().add(chatSocket);i++;}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}


1.3.3socke客户端线程(ChartSocket.java)

Socket客户端线程,通过该线程类发送和接收信息。

package com.jie.socket.chat;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.UnsupportedEncodingException;import java.net.Socket;/** * @ClassName: ChatSocket.java * @Description: TODO(socket客户端线程) * @author yangjie * @version V1.0 * @Date 2016年5月23日 下午3:41:13 */public class ChatSocket extends Thread {Socket socket;String sName;/** * 构造函数 */public ChatSocket(Socket socket, String sName) {// TODO Auto-generated constructor stubthis.socket = socket;this.sName = sName;}@Overridepublic void run() {// TODO Auto-generated method stub// 输入try {BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "utf-8"));String line = null;while ((line = br.readLine()) != null) {// 接收到客户端数据System.out.println(getsName() + ":" + line);ChatManager.getChatManager().publish(this, line);}br.close();// 关闭输入流} catch (UnsupportedEncodingException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}public void out(String out) {// TODO Auto-generated method stubtry {socket.getOutputStream().write(out.getBytes("UTF-8"));} catch (UnsupportedEncodingException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blockif ("Socket is closed".equals(e.getMessage())) {// 对于已经关闭的连接从管理器中删除System.out.println(e.getMessage());ChatManager.getChatManager().remove(this);}// e.printStackTrace();}}public String getsName() {return sName;}public void setsName(String sName) {this.sName = sName;}}


1.3.4客户端管理类(ChatManager.java)

用于管理客户端,保存所有客户端信息,传输客户端发送的信息。

package com.jie.socket.chat;import java.util.Vector;/** * @ClassName:     ChatManager.java * @Description:   TODO(socket客户端连接管理类,单例)  * @author         yangjie * @version        V1.0   * @Date           2016年5月23日 下午4:25:38  */public class ChatManager {private static final ChatManager chatManager = new ChatManager();private ChatManager(){}public static ChatManager getChatManager(){return chatManager;}Vector<ChatSocket> vector = new Vector<ChatSocket>();/** * @Title: add * @Description: TODO(向集合中增加ChatSocket) * @param chatSocket    * @return: void    * @throws */public void add(ChatSocket chatSocket){vector.add(chatSocket);}public void remove(ChatSocket chatSocket){vector.remove(chatSocket);}/** * @Title: publish * @Description: TODO(向其他ChatSocket连接发送信息) * @param chatSocket * @param out    * @return: void    * @throws */public void publish(ChatSocket chatSocket,String out){for(int i =0;i<vector.size();i++){ChatSocket cs = vector.get(i);if(!cs.equals(chatSocket)){//发给不是自己的其他人cs.out(out+"\n");}}}}


1.3.5Hibernate工具类

hibernate工具类,用于连接数据库,操作数据库

package com.jie.socket.chart.util;import org.hibernate.SessionFactory;import org.hibernate.cfg.Configuration;import org.hibernate.service.ServiceRegistry;import org.hibernate.service.ServiceRegistryBuilder;/** * @ClassName: HibernateUtil.java * @Description: TODO(Hibernate数据库工具类) * @author yangjie * @version V1.0 * @Date 2016-5-16 上午11:42:11 */@SuppressWarnings("deprecation")public class HibernateUtil {private static SessionFactory sessionFacotry = buildSessionFactory();private static SessionFactory buildSessionFactory() {// TODO Auto-generated method stubtry {Configuration cfg = new Configuration();cfg.configure();ServiceRegistry sr = new ServiceRegistryBuilder().applySettings(cfg.getProperties()).buildServiceRegistry();return cfg.buildSessionFactory(sr);} catch (Exception e) {}return null;}public static SessionFactory getSessionFacotry() {return sessionFacotry;}}


1.3.6用户实体

用于保存用户信息,关联数据库中的用户表

package com.jie.socket.chart.vo;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.Id;import javax.persistence.Table;import org.hibernate.annotations.GenericGenerator;/** * @ClassName: User.java * @Description: TODO(用户实体类) * @author yangjie * @version V1.0 * @Date 2016-5-24 下午9:17:10 */@Entity@Table(name = "User")public class User {@Id@GeneratedValue(generator = "userIdGenerator")@GenericGenerator(name = "userIdGenerator", strategy = "uuid")private String id;@Columnprivate String name;@Columnprivate String password;public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}}


1.3.7用户登录Servlet

处理用户登陆验证,通过数据库验证。

package com.jie.socket.chat;import java.io.IOException;import java.io.PrintWriter;import java.util.List;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.hibernate.Criteria;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.criterion.Restrictions;import com.jie.socket.chat.util.HibernateUtil;import com.jie.socket.chat.vo.User;/** * @ClassName:     ChatLogin.java * @Description:   TODO(登陆)  * @author         yangjie * @version        V1.0   * @Date           2016-5-16 上午11:20:16 */public class ChatLogin extends HttpServlet {private static final long serialVersionUID = 1L;public ChatLogin() {super();}protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {//int uuid = Integer.parseInt(request.getParameter("uuid"));String name = request.getParameter("name");String password = request.getParameter("password");//System.out.println(uuid);System.out.println(name);System.out.println(password);//是否登陆boolean islogin = false;if (!islogin) {// 查询用户表,验证登录 SessionFactory sf = HibernateUtil.getSessionFacotry();Session session = sf.openSession();Criteria criteria = session.createCriteria(User.class);//criteria.add(Restrictions.eq("uuid", uuid));criteria.add(Restrictions.eq("name", name));//按照姓名查找criteria.add(Restrictions.eq("password", password));//按照密码查找List<User> result = criteria.list();if (result.size() ==1) {//登陆成功System.out.println(name+",登陆成功");islogin = true;}else{//登录失败System.out.println(password+",登陆失败");}session.close();sf = null;}PrintWriter out = response.getWriter();out.print(islogin);//传递登陆是否成功out.flush();out.close();}}


1.3.8hibernate.cfg.xml配置文件

配置数据库信息,实体类信息。

<?xml version='1.0' encoding='utf-8'?><!DOCTYPE hibernate-configuration PUBLIC        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"><hibernate-configuration><session-factory><!-- Database connection settings --><property name="connection.driver_class">com.mysql.jdbc.Driver</property><property name="connection.url">jdbc:mysql://192.168.0.99:3306/jie-db</property><property name="connection.username">root</property><property name="connection.password">bonc123,</property><!-- JDBC connection pool (use the built-in) --><property name="connection.pool_size">1</property><!-- 方言,针对不同的数据库不一样 --><property name="dialect">org.hibernate.dialect.MySQLDialect</property><!-- Enable Hibernate's automatic session context management --><property name="current_session_context_class">thread</property><!-- Disable the second-level cache --><property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property><!-- 打印sql语句 --><property name="show_sql">true</property><!-- 时候让hibernate自动生成建表语句 --><property name="hbm2ddl.auto">update</property><!-- xml实体类映射文件 --><!-- <mapping resource="com/jie/hibernate/po/Student.hbm.xml"/> --><!-- Annotation实体类映射文件 --><mapping class="com.jie.socket.chat.vo.User" /></session-factory></hibernate-configuration>


1.3.9web.xml

配置servlet登陆类,自启动socket服务。

<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">  <display-name></display-name>  <servlet>    <description>自启动servlet,用于开启socket服务</description>    <servlet-name>myServerSocket</servlet-name>    <servlet-class>com.jie.socket.chat.MyServerSocket</servlet-class>    <load-on-startup>1</load-on-startup>  </servlet>  <servlet>    <description>手机登陆</description>    <servlet-name>chatLogin</servlet-name>    <servlet-class>com.jie.socket.chat.ChatLogin</servlet-class>  </servlet>  <servlet-mapping>    <servlet-name>chatLogin</servlet-name>    <url-pattern>/chatLogin</url-pattern>  </servlet-mapping>  <welcome-file-list>    <welcome-file>index.jsp</welcome-file>  </welcome-file-list></web-app>


1.4Android手机端

基于socket技术,通过网络端开启SocketServer服务,手机端登陆并连接SocketServer服务,通过socket客户端将消息发送到服务端,服务端分发给连接到该服务的所有客户端。实现手机群聊的效果。

1.4.1用户信息类

通过SharedPreferences将用户名称存储到手机中。

package com.jie.socket.chat.info;import java.io.Serializable;import android.app.Activity;import android.content.Context;import android.content.SharedPreferences;public class UserInfo implements Serializable {private static final long serialVersionUID = 1L;private static final String PREFERENCES_TAG = "com.jie.socket.chart";private static UserInfo instance;private String name = "";public static UserInfo getInstance() {if (instance == null) {synchronized (UserInfo.class) {if (instance == null) {instance = new UserInfo();}}}return instance;}public static void saveName(Context context) {SharedPreferences mySharedPreferences = context.getSharedPreferences(PREFERENCES_TAG, Activity.MODE_PRIVATE);SharedPreferences.Editor edit = mySharedPreferences.edit();edit.putString("name", getInstance().getName());edit.commit();}public static String readName(Context context) {SharedPreferences mySharedPreferences = context.getSharedPreferences(PREFERENCES_TAG, Activity.MODE_PRIVATE);String mName = mySharedPreferences.getString("name", "");getInstance().setName(mName);return mName;}public static void readAll(Context context) {readName(context);}public void cleanUserInfo(Context context) {SharedPreferences mySharedPreferences = context.getSharedPreferences(PREFERENCES_TAG, Activity.MODE_PRIVATE);SharedPreferences.Editor editor = mySharedPreferences.edit();editor.remove("name");editor.commit();}public String getName() {return name;}public void setName(String name) {this.name = name;}}


1.4.2activity_main.xml布局

应用启动过渡阶段的时候显示

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context="com.jie.socket.chat.MainActivity" ></RelativeLayout>


1.4.3MainActivity入口类

MainActivity入口,监测用户是否登陆状况,判断进入主界面还是进入登陆界面

package com.jie.socket.chat;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import com.jie.socket.chat.info.UserInfo;/** * @ClassName:     MainActivity.java * @Description:   TODO(Activity入口,监测用户是否登陆状况,判断进入主界面还是进入登陆界面)  * @author         yangjie * @version        V1.0   * @Date           2016年5月25日 下午8:35:48 */public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);checkLogin();}/** * @Title: checkLogin * @Description: TODO(监测是否登陆) * @return: void * @throws */public void checkLogin() {// TODO Auto-generated method stubUserInfo.readAll(getApplicationContext());String name = UserInfo.getInstance().getName();System.out.println("username:" + name);if (name != null && !"".equals(name)) {gotoNext();} else {gotoLogin();}}public void gotoLogin() {Intent intent = new Intent();intent.setClass(MainActivity.this, LoginActivity.class);intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);startActivity(intent);finish();}private void gotoNext() {Intent intent = new Intent();intent.setClass(MainActivity.this, ChatActivity.class);intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);startActivity(intent);finish();}}


1.4.4activity_chat.xml布局文件

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context="com.jie.socket.chat.ChatActivity" >    <LinearLayout        android:id="@+id/layout_link"        android:layout_width="match_parent"        android:layout_height="wrap_content" >        <EditText            android:id="@+id/et_ip"            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_weight="5"            android:hint="请输入连接"            android:text="192.168.0.199" />        <Button            android:id="@+id/btn_connect"            android:layout_width="0dp"            android:layout_height="30dp"            android:layout_weight="2"            android:background="@drawable/btn_selector"            android:text="连接" />    </LinearLayout>    <TextView        android:id="@+id/tv_content"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_below="@id/layout_link"        android:hint="消息" />    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_alignParentBottom="true"        android:orientation="vertical" >        <EditText            android:id="@+id/et_msg"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:hint="输入发送内容" />        <Button            android:id="@+id/btn_send"            android:layout_width="match_parent"            android:layout_height="40dp"            android:background="@drawable/btn_selector"            android:text="发送" />    </LinearLayout></RelativeLayout>

1.4.5ChatActivity聊天类

通过socket连接服务器端,建立连接,然后通过socket接收和发送信息。

package com.jie.socket.chat;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.net.Socket;import java.net.UnknownHostException;import android.annotation.SuppressLint;import android.os.AsyncTask;import android.os.Bundle;import android.util.Log;import android.view.KeyEvent;import android.view.View;import android.view.View.OnClickListener;import android.view.View.OnKeyListener;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast;import com.alibaba.fastjson.JSONObject;import com.jie.socket.chat.info.UserInfo;/** * @ClassName: ChatActivity.java * @Description: TODO(聊天) * @author yangjie * @version V1.0 * @Date 2016年5月25日 下午7:47:00 */public class ChatActivity extends BaseActivity {EditText et_ip;EditText et_msg;TextView tv_conent;Button btn_send;Button btn_connect;Socket socket;BufferedWriter writer;BufferedReader reader;String TAG = "Socket Chart";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_chat);et_ip = (EditText) findViewById(R.id.et_ip);et_msg = (EditText) findViewById(R.id.et_msg);tv_conent = (TextView) findViewById(R.id.tv_content);btn_connect = (Button) findViewById(R.id.btn_connect);btn_send = (Button) findViewById(R.id.btn_send);btn_send.setEnabled(false);et_msg.setEnabled(false);eventListener();}private void eventListener() {// TODO Auto-generated method stubbtn_connect.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubconnnet();}});btn_send.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubsend();}});et_msg.setOnKeyListener(onKey);}StringBuffer text = new StringBuffer();/** * @Title: connnet * @Description: TODO(连接) * @return: void * @throws */private void connnet() {// TODO Auto-generated method stubread.execute();}/** * @Title: send * @Description: TODO(发送消息) * @return: void * @throws */private void send() {// TODO Auto-generated method stubtry {String msg = et_msg.getText().toString();if (msg != null && !"".equals(msg)) {text.append(name + ":" + msg + "\n");tv_conent.setText(text);// 传递给sokect服务,json数据{name:1212,msg:'121212'}JSONObject jsonObject = new JSONObject();jsonObject.put("name", name);jsonObject.put("msg", msg);writer.write(jsonObject.toString() + "\n");writer.flush();// 刷新缓冲区,强制输出Log.i(TAG, msg);et_msg.setText("");} else {showToast("请输入发送内容");}} catch (NullPointerException excNull) {Log.i(TAG, "writer error:" + "空指针异常");showToast("请点击连接,连接到服务器");} catch (Exception e) {// TODO Auto-generated catch blockLog.i(TAG, "Error:" + e.getMessage());e.printStackTrace();}}@SuppressLint("ShowToast")public void showToast(String msg) {Toast.makeText(getApplicationContext(), msg, 1000).show();}OnKeyListener onKey = new OnKeyListener() {// 回车键监听@Overridepublic boolean onKey(View v, int keyCode, KeyEvent event) {// 回车键,并且为鼠标按下,防止按下回车键两次调用if (keyCode == KeyEvent.KEYCODE_ENTER&& event.getAction() == KeyEvent.ACTION_DOWN) {Log.i(TAG, "回车键:" + keyCode);send();return true;}return false;}};OutputStreamWriter outputStreamWriter;InputStreamReader inputStreamReader;AsyncTask<Void, String, Void> read = new AsyncTask<Void, String, Void>() {@Overrideprotected Void doInBackground(Void... params) {// TODO Auto-generated method stubtry {socket = new Socket(et_ip.getText().toString().trim(), 12345);outputStreamWriter = new OutputStreamWriter(socket.getOutputStream());inputStreamReader = new InputStreamReader(socket.getInputStream());writer = new BufferedWriter(outputStreamWriter);reader = new BufferedReader(inputStreamReader);publishProgress("@success");} catch (UnknownHostException e) {// TODO Auto-generated catch blockLog.i("socket", "连接失败");e.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();// showToast("连接失败");Log.i("socket", "连接失败");}String line;// 异步线程未关闭if (!isCancelled()) {while (true) {try {if ((line = reader.readLine()) != null) {publishProgress(line);}} catch (IOException e) {// TODO Auto-generated catch blockif ("Socket closed".equals(e.getMessage())) {Log.i(TAG, "连接已关闭");} else {e.printStackTrace();}break;}}}return null;}@Overrideprotected void onProgressUpdate(String... values) {// TODO Auto-generated method stubif (values[0] != null && !"".equals(values[0])) {if (values[0] == "@success") {// text.append(values[0]);btn_connect.setEnabled(false);Log.i(TAG, "连接服务器成功!");tv_conent.setText("连接服务器成功!");btn_send.setEnabled(true);et_msg.setEnabled(true);name = UserInfo.readName(getApplicationContext());if (name != null && !"".equals(name));{Log.i(TAG, "name:" + name);try {writer.write("name:" + name + "\n");writer.flush();// 强制输出} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}} else {JSONObject obj = JSONObject.parseObject(values[0]);// 将json字符串转换为对象String cName = obj.getString("name");String cMsg = obj.getString("msg");text.append(cName + ":" + cMsg + "\n");Log.i(TAG, values[0]);tv_conent.setText(text);}}}};@Overrideprotected void onDestroy() {// TODO Auto-generated method stubsuper.onDestroy();// Log.i(TAG, "socket != null:"+(socket != null)// +"----socket.isClosed():"+(!socket.isClosed()));if (socket != null && !socket.isClosed()) {Log.i(TAG, "关闭连接");try {read.cancel(true);// 线程关闭socket.close();reader.close();writer.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}// 关闭连接}}}


1.4.6基础Activity

用于设置Activity公用的字段和方法。

package com.jie.socket.chat;import android.app.Activity;import android.os.Bundle;import android.view.KeyEvent;import android.view.Window;import android.widget.Toast;import com.jie.socket.chat.info.UserInfo;public class BaseActivity extends Activity {String name;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);initDatas();}public void findViews() {}public void initDatas() {name = UserInfo.readName(getApplicationContext());}public void clickEvents() {}@Overrideprotected void onDestroy() {// TODO Auto-generated method stubsuper.onDestroy();}@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) {// TODO Auto-generated method stubreturn super.onKeyDown(keyCode, event);}@Overrideprotected void onResume() {// TODO Auto-generated method stubsuper.onResume();}@Overrideprotected void onPause() {// TODO Auto-generated method stubsuper.onPause();}@Overridepublic void onBackPressed() {super.onBackPressed();}public void showToast(CharSequence message) {if (message != null && !"".equals(message)) {Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();} else {Toast.makeText(getApplicationContext(), "连接超时,请检查网络",Toast.LENGTH_SHORT).show();}}}


1.4.7activity_login.xml登陆布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:layout_gravity="center"    android:background="@drawable/gb_background"    android:gravity="center"    android:orientation="vertical"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context="com.jie.socket.chat.LoginActivity" >    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="horizontal" >        <TextView            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_weight="1"            android:text="用户名:"            android:textSize="18px" />        <EditText            android:id="@+id/userName"            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_weight="3"            android:textSize="18px" />    </LinearLayout>    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginTop="15dp"        android:orientation="horizontal" >        <TextView            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_weight="1"            android:text="密   码:"            android:textSize="18px" />        <EditText            android:id="@+id/userPassword"            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_weight="3"            android:password="true"            android:textSize="18px" />    </LinearLayout>    <Button        android:id="@+id/btn_login"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginTop="10dp"        android:background="@drawable/btn_selector"        android:text="登陆" /></LinearLayout>

1.4.8LoginActivity登陆类

package com.jie.socket.chat;import android.content.Intent;import android.os.Bundle;import android.util.Log;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;import com.jie.socket.chat.info.UserInfo;import com.lidroid.xutils.HttpUtils;import com.lidroid.xutils.exception.HttpException;import com.lidroid.xutils.http.RequestParams;import com.lidroid.xutils.http.ResponseInfo;import com.lidroid.xutils.http.callback.RequestCallBack;import com.lidroid.xutils.http.client.HttpRequest.HttpMethod;public class LoginActivity extends BaseActivity {EditText et_userName;EditText et_userPassword;Button btn_login;String name;String password;protected String httpUrl = "http://192.168.0.199:8080/SocketChatServer/chatLogin";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_login);et_userName = (EditText) findViewById(R.id.userName);et_userPassword = (EditText) findViewById(R.id.userPassword);btn_login = (Button) findViewById(R.id.btn_login);btn_login.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubname = et_userName.getText().toString();password = et_userPassword.getText().toString();if (!"".equals(name) && !"".equals(password)) {HttpUtils http = new HttpUtils();RequestParams params = new RequestParams();params.addBodyParameter("name", name);params.addBodyParameter("password", password);http.send(HttpMethod.POST, httpUrl, params,new RequestCallBack<String>() {@Overridepublic void onFailure(HttpException arg0,String arg1) {// TODO Auto-generated method stubLog.i("http.send", "failuer");}@Overridepublic void onSuccess(ResponseInfo<String> arg0) {// TODO Auto-generated method stubString isLogin = arg0.result;if ("true".equals(isLogin)) {// 登陆成功Intent intent = new Intent();intent.setClass(LoginActivity.this,ChatActivity.class);intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);startActivity(intent);finish();Log.i("http.send", "success" + isLogin);UserInfo.getInstance().setName(name);UserInfo.saveName(getApplicationContext());} else {showToast("用户名或密码错误");}}});}}});}}

1.5 源码下载

基于Socket的Android聊天室

更多相关文章

  1. Nginx系列教程(二)| 一文带你读懂Nginx的正向与反向代理
  2. RHEL 6 下 DHCP+TFTP+FTP+PXE+Kickstart 实现无人值守安装
  3. android用户界面-事件处理
  4. Android异步消息处理机制(2)源码解析
  5. Android(安卓)UI--提高Android(安卓)UI体验
  6. Android(安卓)java面试题收集
  7. Android的Socket 通信
  8. Android(安卓)Phone蓝牙通信方式总结(Socket与Gatt)
  9. 项目总结:华南师范大学校园开发教育android客户端总结

随机推荐

  1. Android 实时动态刷新更改菜单
  2. android:numeric="integer"属性
  3. android 获取通讯模块制式类型
  4. android 实现圆形头像
  5. 初学Android,从手势库识别手势(五十一)
  6. android 控件背景添加圆角
  7. Android 应用签名
  8. Android调试工具之Logcat
  9. android部分BUG
  10. Android Studio 项目运行错误,弹出“Detec