正文  网络通信 > Socket >

以C#编写的Socket服务器的Android手机聊天室Demo

内容摘要 1.程序架构 2.通信协议 3.服务器源代码 4.客户端源代码 5.运行效果 一、程序架构 在开发一个聊天室程序时,我们可以使用Socket、Remoting、WCF这些具有双向通信的协议或框架。而现在,我正要实......

  内容摘要

   1.程序架构

   2.通信协议

   3.服务器源代码

   4.客户端源代码

   5.运行效果

 

  一、程序架构

  在开发一个聊天室程序时,我们可以使用Socket、Remoting、WCF这些具有双向通信的协议或框架。而现在,我正要实现一个C#语言作为服务器 端、Android作为客户端的聊天室。由于服务器端和客户端不是同一语言(C#和java),所有我选择了Socket作为通信协议。

  图1.1所示,我们可以看出:android手机客户端A向服务器端发送消息,服务器端收到消息后,又把消息推送到android手机客户端B。

 图1.1

 

  二、通信协议

我们知道,在C#语言中使用Socket技术需要“四部曲”,即“Bind”,“Listen”,“Accept”,“Receive”。然而 Socket编程不像WCF那样面向对象。而且对应每个请求都用同一种方式处理。作为习惯面向对象编程的我来说,编写一个传统的Socket程序很不爽。 绞尽脑汁,我们将数据传输的格式改为json(JavaScript Object Notation 是一种轻量级的数据交换格式),面对对象的问题就解决了。

   假设程序的服务契约有两个方法:“登陆”和“发送消息”。调用登陆的方法,就传送方法名(Method Name)为“Logon”的json数据;调用发送消息的方法,就传送方法名为“Send”的json数据。返回的数据中也使用json格式,这样在 android客户端中也能知道是哪个方法的返回值了。

 

  三、服务器源代码

 首先需要编写一个处理客户端消息的接口:IResponseManager。

 

     public   interface  IResponseManager
    {
         void  Write(Socket sender, IList < Socket >  cliens, IDictionary < string ,  object >  param);
    }

 

 

其次,我们知道,换了是WCF编程的话,就需要在服务契约中写两个方法:“登陆”和“发送消息”。由于这里是Socket编程,我们实现之前写的IResponseManager接口,一个实现作为“登陆”的方法,另一个实现作为“发送消息”的方法。

 

public   class  LogonResponseManager : IResponseManager
    {
         public   void  Write(System.Net.Sockets.Socket sender, IList < System.Net.Sockets.Socket >  cliens, IDictionary < string ,  object >  param)
        {
            Console.WriteLine( " 客户端({0})登陆 " , sender.Handle);
            var response  =   new  SocketResponse
            {
                Method  =   " Logon " ,
                DateTime  =  DateTime.Now.ToString( " yyyy-MM-dd HH:mm:ss " ),
                Result  =   new  { UserName  =  param[ " UserName " ].ToString() }
            };

            JavaScriptSerializer jss  =   new  JavaScriptSerializer();
             string  context  =  jss.Serialize(response);
            Console.WriteLine( " 登陆发送的数据为:{0} " , context);
            sender.Send(Encoding.UTF8.GetBytes(context  +   " \n " ));
        }
    }

 

 

public   class  SendResponseManager : IResponseManager
    {
         public   void  Write(System.Net.Sockets.Socket sender, IList < System.Net.Sockets.Socket >  cliens, IDictionary < string ,  object >  param)
        {
            Console.WriteLine( " 客户端({0})发送消息 " , sender.Handle);
            var msgList  =  param[ " Message " ]  as  IEnumerable < object > ;
             if  (msgList  ==   null )
            {
                 return ;
            }

            var response  =   new  SocketResponse
            {
                Method  =   " Send " ,
                DateTime  =  DateTime.Now.ToString( " yyyy-MM-dd HH:mm:ss " ),
                Result  =   new
                { 
                    UserName  =  param[ " UserName " ].ToString(),
                    Message  =  msgList.Select(s  =>  s.ToString()).ToArray() 
                }
            };

            JavaScriptSerializer jss  =   new  JavaScriptSerializer();
             string  context  =  jss.Serialize(response);
            Console.WriteLine( " 消息发送的数据为:{0} " , context);

            Parallel.ForEach(cliens, (item)  =>
            {
                 try
                {
                    item.Send(Encoding.UTF8.GetBytes(context  +   " \n " ));
                }
                 catch  { };
            });
        }
    }

 

最后在Socket程序中使用反射加“策略模式”调用这两个接口实现类。

 

            var typeName  =   " SocketServer. "   +  request.Method  +   " ResponseManager, SocketServer " ;
            Console.WriteLine( " 反射类名为: "   +  typeName);

            Type type  =  Type.GetType(typeName);
             if  (type  ==   null )
            {
                 return ;
            }

            var manager  =  Activator.CreateInstance(type)  as  IResponseManager;
            manager.Write(sender,  this .socketClientSesson.Select(s  =>  s.Key).ToList(),
                request.Param  as  IDictionary < string ,  object > );

 

完整的Socket服务器代码如下:

 

public   class  SocketHost
    {
         private  IDictionary < Socket,  byte [] >  socketClientSesson  =   new  Dictionary < Socket,  byte [] > ();

         public   int  Port {  get ;  set ; }

         public   void  Start()
        {
            var socketThread  =   new  Thread(()  =>
            {
                Socket socket  =   new  Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPEndPoint iep  =   new  IPEndPoint(IPAddress.Any,  this .Port);

                 // 绑定到通道上
                socket.Bind(iep);

                 // 侦听
                socket.Listen( 6 );

                 // 通过异步来处理
                socket.BeginAccept( new  AsyncCallback(Accept), socket);

            });

            socketThread.Start();

            Console.WriteLine( " 服务器已启动 " );
        }

         private   void  Accept(IAsyncResult ia)
        {
            Socket socket  =  ia.AsyncState  as  Socket;
            var client  =  socket.EndAccept(ia);

            socket.BeginAccept( new  AsyncCallback(Accept), socket);

             byte [] buf  =   new   byte [ 1024 ];
             this .socketClientSesson.Add(client, buf);

             try
            {
                client.BeginReceive(buf,  0 , buf.Length, SocketFlags.None,  new  AsyncCallback(Receive), client);
                 string  sessionId  =  client.Handle.ToString();
                Console.WriteLine( " 客户端({0})已连接 " , sessionId);
            }
             catch  (Exception ex)
            {
                Console.WriteLine( " 监听请求时出错:\r\n "   +  ex.ToString());
            }
        }

         private   void  Receive(IAsyncResult ia)
        {
            var client  =  ia.AsyncState  as  Socket;

             if  (client  ==   null   ||   ! this .socketClientSesson.ContainsKey(client))
            {
                 return ;
            }

             int  count  =  client.EndReceive(ia);

             byte [] buf  =   this .socketClientSesson[client];

             if  (count  >   0 )
            {
                 try
                {
                    client.BeginReceive(buf,  0 , buf.Length, SocketFlags.None,  new  AsyncCallback(Receive), client);
                     string  context  =  Encoding.UTF8.GetString(buf,  0 , count);
                    Console.WriteLine( " 接收的数据为: " , context);

                     this .Response(client, context);
                }
                 catch  (Exception ex)
                {
                    Console.WriteLine( " 接收的数据出错:\r\n{0} " , ex.ToString());
                }
            }
             else
            {
                 try
                {
                     string  sessionId  =  client.Handle.ToString();
                    client.Disconnect( true );
                     this .socketClientSesson.Remove(client);
                    Console.WriteLine( " 客户端({0})已断开 " , sessionId);
                }
                 catch  (Exception ex)
                {
                    Console.WriteLine( " 客户端已断开出错 "   +  ex.ToString());
                }
            }
        }

         private   void  Response(Socket sender,  string  context)
        {
            SocketRequest request  =   null ;
            JavaScriptSerializer jss  =   new  JavaScriptSerializer();
            request  =  jss.Deserialize(context,  typeof (SocketRequest))  as  SocketRequest;

             if  (request  ==   null )
            {
                 return ;
            }

            var typeName  =   " SocketServer. "   +  request.Method  +   " ResponseManager, SocketServer " ;
            Console.WriteLine( " 反射类名为: "   +  typeName);

            Type type  =  Type.GetType(typeName);
             if  (type  ==   null )
            {
                 return ;
            }

            var manager  =  Activator.CreateInstance(type)  as  IResponseManager;
            manager.Write(sender,  this .socketClientSesson.Select(s  =>  s.Key).ToList(),
                request.Param  as  IDictionary < string ,  object > );
        }
    }

 

 

最后,json数据传输的实体对象为:

 

   [Serializable]
     public   class  SocketRequest
    {
         public   string  Method {  get ;  set ; }

         public   string  DateTime {  get ;  set ; }

         public   object  Param {  get ;  set ; }
    }

 

 

    [Serializable]
     public   class  SocketResponse
    {
         public   string  Method {  get ;  set ; }

         public   string  DateTime {  get ;  set ; }

         public   object  Result {  get ;  set ; }
    }

 

 四、客户端源代码

1.布局文件

logon.xml:

 

<? xml version="1.0" encoding="utf-8" ?>
< LinearLayout  xmlns:android ="http://schemas.android.com/apk/res/android"
    android:orientation ="vertical"  android:layout_width ="fill_parent"
    android:layout_height ="fill_parent"  android:background ="@drawable/background" >

     < LinearLayout  android:orientation ="vertical"
        android:layout_width ="fill_parent"  android:layout_height ="60dip"
        android:background ="@drawable/logon"   />

     < LinearLayout  android:orientation ="vertical"
        android:layout_width ="fill_parent"  android:layout_height ="fill_parent"
        android:paddingLeft ="10dp"  android:paddingRight ="10dp" >

         < View  android:layout_width ="fill_parent"  android:layout_height ="20dip"   />

         < TextView  android:id ="@+id/feedback_title"  android:textColor ="#FFFFFF"
            android:layout_width ="fill_parent"  android:layout_height ="wrap_content"
            android:text ="用户名:"   />
         < EditText  android:id ="@+id/edtUserName"  android:layout_width ="fill_parent"
            android:layout_height ="wrap_content"   />

         < View  android:layout_width ="fill_parent"  android:layout_height ="2dip"
            android:background ="#FF909090"   />

         < TextView  android:layout_width ="fill_parent"
            android:textColor ="#FFFFFF"  android:layout_height ="wrap_content"
            android:text ="IP地址:"   />
         < EditText  android:id ="@+id/edtIp"  android:layout_width ="fill_parent"
            android:layout_height ="wrap_content"  android:digits ="1234567890."  
            android:text ="192.168.1.101" />

         < View  android:layout_width ="fill_parent"  android:layout_height ="2dip"
            android:background ="#FF909090"   />

         < TextView  android:layout_width ="fill_parent"
            android:textColor ="#FFFFFF"  android:layout_height ="wrap_content"
            android:text ="端口号:"   />
         < EditText  android:id ="@+id/edtPort"  android:layout_width ="fill_parent"
            android:layout_height ="wrap_content"  android:inputType ="number"
            android:numeric ="integer"  android:text ="1234" />

         < LinearLayout  android:orientation ="horizontal"
            android:layout_width ="fill_parent"  android:layout_height ="wrap_content"
            android:layout_marginTop ="10dp" >
         </ LinearLayout >
         < RelativeLayout  android:layout_width ="fill_parent"
            android:layout_height ="fill_parent" >
             < View  android:id ="@+id/feedback_content"  android:layout_width ="fill_parent"
                android:layout_height ="fill_parent"  android:maxEms ="10"
                android:minEms ="10"  android:gravity ="top"
                android:layout_marginBottom ="50dip"   />
             < Button  android:id ="@+id/btnLogon"  android:layout_width ="fill_parent"
                android:layout_height ="50dp"  android:text ="登陆"  android:textSize ="19dp"
                android:layout_gravity ="center_horizontal"
                android:layout_alignParentBottom ="true"   />
         </ RelativeLayout >
     </ LinearLayout >
</ LinearLayout >

 

main.xml:

<? xml version="1.0" encoding="utf-8" ?>
< LinearLayout  xmlns:android ="http://schemas.android.com/apk/res/android"
    android:orientation ="vertical"  android:layout_width ="fill_parent"
    android:layout_height ="fill_parent"  android:background ="@drawable/background" >

     < ListView  android:layout_width ="fill_parent"
        android:layout_height ="wrap_content"  android:id ="@+id/ltvMessage" >
     </ ListView >

     < RelativeLayout  android:layout_width ="fill_parent"
        android:layout_height ="wrap_content" >

         < EditText  android:layout_width ="fill_parent"
            android:layout_height ="wrap_content"  android:id ="@+id/edtMessage"
            android:hint ="请输入消息"  android:layout_alignTop ="@+id/btnSend"
            android:layout_toLeftOf ="@+id/btnSend"   />

         < Button  android:text ="SEND"  android:id ="@+id/btnSend"
            android:layout_height ="wrap_content"  android:layout_width ="wrap_content"
            android:layout_alignParentRight ="true"   />
     </ RelativeLayout >

</ LinearLayout >

 

listview_item.xml:

 

<? xml version="1.0" encoding="utf-8" ?>
< LinearLayout  xmlns:android ="http://schemas.android.com/apk/res/android"
    android:layout_width ="fill_parent"  android:layout_height ="wrap_content"
    android:orientation ="vertical"  android:paddingBottom ="3dip"
    android:paddingLeft ="10dip" >

     < TextView  android:layout_height ="wrap_content"
        android:layout_width ="fill_parent"  android:id ="@+id/itmMessage"
        android:textSize ="20dip" >
     </ TextView >

     < LinearLayout  android:layout_width ="fill_parent"
        android:orientation ="horizontal"  android:layout_height ="20dip" >
         < TextView  android:layout_height ="fill_parent"
            android:layout_width ="100dip"  android:id ="@+id/itmUserName"   >
         </ TextView >

         < TextView  android:layout_height ="fill_parent"
            android:layout_width ="200dip"  android:id ="@+id/itmTime"   >
         </ TextView >

     </ LinearLayout >

</ LinearLayout >

 

SocketClient:

 

package  ld.socket;

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  java.text.SimpleDateFormat;
import  java.util.Date;
import  java.util.HashMap;
import  java.util.Map;

import  org.json.JSONArray;
import  org.json.JSONException;
import  org.json.JSONObject;

import  android.os.Handler;
import  android.os.Message;
import  android.util.Log;

public   class  SocketClient {

     private   static  Socket client;

     private   static  SocketClient instance  =   null ;

     public   static  SocketClient getInstance() {
         if  (instance  ==   null ) {

             synchronized  (ChartInfo. class ) {
                 if  (instance  ==   null ) {
                     try  {
                        ChartInfo chartInfo  =  ChartInfo.getInstance();
                        client  =   new  Socket(chartInfo.getIp(), chartInfo
                                .getPort());
                        instance  =   new  SocketClient();
                    }  catch  (UnknownHostException e) {
                         //  TODO Auto-generated catch block
                    }  catch  (IOException e) {
                         //  TODO Auto-generated catch block
                    }
                }
            }
        }
         return  instance;
    }

     private  SocketClient() {
         this .initMap();
         this .startThread();
    }

     private   void  initMap() {
         this .handlerMap  =   new  HashMap < String, Handler > ();
    }

     public   void  close() {
         try  {
            client.close();
        }  catch  (IOException e) {
             //  TODO Auto-generated catch block
             // e.printStackTrace();
        }
        instance  =   null ;
    }
    
     private   void  startThread() {
        Thread thread  =   new  Thread() {
            @Override
             public   void  run() {

                 while  ( true ) {
                     if  (client  ==   null   ||   ! client.isConnected()) {
                         continue ;
                    }

                    BufferedReader reader;
                     try  {
                        reader  =   new  BufferedReader( new  InputStreamReader(
                                client.getInputStream()));
                        String line  =  reader.readLine();
                        Log.d( " initSocket " ,  " line: "   +  line);
                         if  (line.equals( "" )) {
                             continue ;
                        }

                        JSONObject json  =   new  JSONObject(line);
                        String method  =  json.getString( " Method " );
                        Log.d( " initSocket " ,  " method: "   +  method);
                         if  (method.equals( "" )
                                 ||   ! handlerMap.containsKey(method)) {
                            Log.d( " initSocket " ,  " handlerMap not method " );
                             continue ;
                        }

                        Handler handler  =  handlerMap.get(method);
                         if  (handler  ==   null ) {
                            Log.d( " initSocket " ,  " handler is null " );
                             continue ;
                        }
                        Log.d( " initSocket " ,  " handler: "   +  method);
                        Object obj  =  json.getJSONObject( " Result " );
                        Log.d( " initSocket " ,  " Result: "   +  obj);
                        Message msg  =   new  Message();
                        msg.obj  =  obj;
                        handler.sendMessage(msg);

                    }  catch  (IOException e) {

                    }  catch  (JSONException e) {

                    }
                }
            }
        };
        thread.start();
    }

     private  Map < String, Handler >  handlerMap;

     public   void  putHandler(String methodnName, Handler handler) {
         this .removeHandler(methodnName);
         this .handlerMap.put(methodnName, handler);
    }

     public   void  removeHandler(String methodnName) {
         if  ( this .handlerMap.containsKey(methodnName)) {
             this .handlerMap.remove(methodnName);
        }
    }

     public   void  logon(String userName) {
        Log.d( " initSocket " ,  " logon " );
         try  {
            OutputStreamWriter osw  =   new  OutputStreamWriter(client
                    .getOutputStream());

            BufferedWriter writer  =   new  BufferedWriter(osw);

            JSONObject param  =   new  JSONObject();
            param.put( " UserName " , userName.replace( " \n " ,  "   " ));

            JSONObject json  =   this .getJSONData( " Logon " , param);

            writer.write(json.toString());
            writer.flush();
        }  catch  (IOException e) {
             //  TODO Auto-generated catch block
            e.printStackTrace();
        }  catch  (JSONException e) {
             //  TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

     public   void  sendMessage(String message) {
        Log.d( " initSocket " ,  " Send " );
         try  {
            OutputStreamWriter osw  =   new  OutputStreamWriter(client
                    .getOutputStream());

            BufferedWriter writer  =   new  BufferedWriter(osw);

            JSONArray array  =   new  JSONArray();
             for  (String item : message.split( " \n " )) {
                array.put(item);
            }

            JSONObject param  =   new  JSONObject();
            param.put( " Message " , array);

            param.put( " UserName " , ChartInfo.getInstance().getUserName());

            JSONObject json  =   this .getJSONData( " Send " , param);

            writer.write(json.toString());
            writer.flush();
        }  catch  (IOException e) {
             //  TODO Auto-generated catch block
            e.printStackTrace();
        }  catch  (JSONException e) {
             //  TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

     private  JSONObject getJSONData(String methodName, JSONObject param) {
        JSONObject json  =   new  JSONObject();
         try  {
            json.put( " Method " , methodName);
            SimpleDateFormat format  =   new  SimpleDateFormat(
                     " yyyy-MM-dd HH:mm:ss " );
            json.put( " DateTime " , format.format( new  Date()));
            json.put( " Param " , param);
             return  json;
        }  catch  (JSONException e) {
             return   null ;
        }
    }
}

 

LogonActivity:

 

package  ld.socket;

import  org.json.JSONException;
import  org.json.JSONObject;

import  android.app.Activity;
import  android.app.AlertDialog;
import  android.content.ComponentName;
import  android.content.DialogInterface;
import  android.content.Intent;
import  android.os.Bundle;
import  android.os.Handler;
import  android.os.Message;
import  android.util.Log;
import  android.view.KeyEvent;
import  android.view.View;
import  android.view.View.OnClickListener;
import  android.widget.Button;
import  android.widget.EditText;

public   class  LogonActivity  extends  Activity {

     private  EditText edtUserName;
     private  EditText edtIp;
     private  EditText edtPort;

     private  Button btnLogon;

    @Override
     protected   void  onCreate(Bundle savedInstanceState) {
         //  TODO Auto-generated method stub
         super .onCreate(savedInstanceState);

        setContentView(R.layout.logon);

         this .initViews();
    }

     private   void  initViews() {
         this .edtUserName  =  (EditText)  this .findViewById(R.id.edtUserName);
         this .edtIp  =  (EditText)  this .findViewById(R.id.edtIp);
         this .edtPort  =  (EditText)  this .findViewById(R.id.edtPort);

         this .btnLogon  =  (Button)  this .findViewById(R.id.btnLogon);
         this .btnLogon.setOnClickListener( new  OnClickListener() {

            @Override
             public   void  onClick(View v) {
                 //  TODO Auto-generated method stub

                 //  showAlert(edtUserName.getText().toString());
                 if  (edtUserName.getText().toString().equals( "" )) {
                    showDialog( " 请输入用户名 " );
                     return ;
                }

                 if  (edtIp.getText().toString().equals( "" )) {
                    showDialog( " 请输入IP地址 " );
                     return ;
                }

                 if  (edtPort.getText().toString().equals( "" )) {
                    showDialog( " 请输入端口号 " );
                     return ;
                }

                 int  port  =  Integer.parseInt(edtPort.getText().toString());
                ChartInfo chartInfo  =  ChartInfo.getInstance();
                chartInfo.setIp(edtIp.getText().toString());
                chartInfo.setPort(port);
                SocketClient proxy  =  SocketClient.getInstance();

                 if  (proxy  ==   null ) {
                    showDialog( " 未接入互联网 " );
                    setWireless();
                     return ;
                }

                proxy.putHandler( " Logon " ,  new  Handler() {
                    @Override
                     public   void  handleMessage(Message msg) {

                        SocketClient proxy  =  SocketClient.getInstance();
                        proxy.removeHandler( " Logon " );
                        Log.d( " initSocket " ,  " handleMessage " );
                         if  (msg  ==   null   ||  msg.obj  ==   null ) {
                             return ;
                        }

                        JSONObject json  =  (JSONObject) msg.obj;
                         try  {
                            String userName  =  json.getString( " UserName " );
                            Log.d( " initSocket " ,  " userName: "   +  userName);
                            ChartInfo.getInstance().setUserName(userName);
                            Intent itt  =   new  Intent();
                            itt
                                    .setClass(LogonActivity. this ,
                                            MainActivity. class );
                            LogonActivity. this .startActivity(itt);
                        }  catch  (JSONException e) {
                             //  TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                });
                proxy.logon(edtUserName.getText().toString());
            }
        });
    }

     private   void  setWireless() {
        Intent mIntent  =   new  Intent( " / " );
        ComponentName comp  =   new  ComponentName( " com.android.settings " ,
                 " com.android.settings.WirelessSettings " );
        mIntent.setComponent(comp);
        mIntent.setAction( " android.intent.action.VIEW " );
        startActivityForResult(mIntent,  0 );
    }

     private   void  showDialog(String mess) {
         new  AlertDialog.Builder( this ).setTitle( " 信息 " ).setMessage(mess)
                .setNegativeButton( " 确定 " ,  new  DialogInterface.OnClickListener() {
                     public   void  onClick(DialogInterface dialog,  int  which) {
                    }
                }).show();
    }

    @Override
     public   boolean  onKeyDown( int  keyCode, KeyEvent event) {

         if  (keyCode  ==  KeyEvent.KEYCODE_BACK  &&  event.getRepeatCount()  ==   0 ) {

            AlertDialog alertDialog  =   new  AlertDialog.Builder(
                    LogonActivity. this ).setTitle( " 退出程序 " ).setMessage( " 是否退出程序 " )
                    .setPositiveButton( " 确定 " ,
                             new  DialogInterface.OnClickListener() {

                                 public   void  onClick(DialogInterface dialog,
                                         int  which) {
                                    LogonActivity. this .finish();
                                }

                            }).setNegativeButton( " 取消 " ,

                     new  DialogInterface.OnClickListener() {
                         public   void  onClick(DialogInterface dialog,  int  which) {
                             return ;
                        }
                    }).create();  //  创建对话框

            alertDialog.show();  //  显示对话框

             return   false ;

        }

         return   false ;
    }

    @Override
     protected   void  onDestroy() {
         //  TODO Auto-generated method stub
         super .onDestroy();
        SocketClient proxy  =  SocketClient.getInstance();
         if  (proxy  !=   null ) {
            proxy.close();
        }
    }

}

 

 

MainActivity:

 

package  ld.socket;

import  org.json.JSONException;
import  org.json.JSONObject;

import  android.app.Activity;
import  android.app.AlertDialog;
import  android.content.DialogInterface;
import  android.os.Bundle;
import  android.os.Handler;
import  android.os.Message;
import  android.util.Log;
import  android.view.KeyEvent;
import  android.view.View;
import  android.view.WindowManager;
import  android.view.View.OnClickListener;
import  android.widget.Button;
import  android.widget.EditText;
import  android.widget.ListView;

public   class  MainActivity  extends  Activity {

     private  EditText edtMessage;

     private  Button btnSend;

     private  ListView ltvMessage;

     private  MessageAdapter adapter;

     /**  Called when the activity is first created.  */
    @Override
     public   void  onCreate(Bundle savedInstanceState) {
         super .onCreate(savedInstanceState);
        setContentView(R.layout.main);

         //  隐藏键盘
         this .getWindow().setSoftInputMode(
                WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

        Log.d( " initSocket " ,  " MessageAdapter " );
         this .adapter  =   new  MessageAdapter( this );
        Log.d( " initSocket " ,  " adapter is ok " );

         this .findThisViews();
         this .initHandler();

         this .serOnClick();

        Log.d( " initSocket " ,  " onCreate " );
    }

     private   void  findThisViews() {
         this .edtMessage  =  (EditText)  this .findViewById(R.id.edtMessage);
         this .btnSend  =  (Button)  this .findViewById(R.id.btnSend);

         this .ltvMessage  =  (ListView)  this .findViewById(R.id.ltvMessage);
         //  this.ltvMessage.setEnabled(false);
         this .ltvMessage.setAdapter( this .adapter);
    }

     private   void  initHandler() {

        Handler handler  =   new  Handler() {
            @Override
             public   void  handleMessage(Message msg) {
                 if  (msg.obj  ==   null ) {
                    Log.d( " initSocket " ,  " handleMessage is null " );
                     return ;
                }

                Log.d( " initSocket " ,  " handleMessage " );
                 try  {
                    JSONObject json  =  (JSONObject) msg.obj;
                    String userName  =  json.getString( " UserName " );

                    StringBuilder sb  =   new  StringBuilder();
                     int  length  =  json.getJSONArray( " Message " ).length();
                     for  ( int  i  =   0 ; i  <  length; i ++ ) {
                        String item  =  json.getJSONArray( " Message " ).getString(i);
                         if  (item.equals( "" )) {
                             continue ;
                        }
                         if  (length  >  i  +   1 ) {
                            Log.d( " initSocket " ,  " length: "   +  length);
                            Log.d( " initSocket " ,  " i: "   +  i);
                            Log.d( " initSocket " ,  " item: "   +  item);
                            item  +=   " \n " ;
                        }
                        sb.append(item);
                    }

                    MessageRecord record  =   new  MessageRecord();
                    record.setUserName(userName);
                    record.setMessage(sb.toString());

                    MainActivity. this .adapter.add(record);
                    adapter.notifyDataSetChanged();
                }  catch  (JSONException e) {
                     //  TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        };
        SocketClient proxy  =  SocketClient.getInstance();
        proxy.putHandler( " Send " , handler);
    }

     private   void  serOnClick() {
         this .btnSend.setOnClickListener( new  OnClickListener() {

            @Override
             public   void  onClick(View v) {
                 //  TODO Auto-generated method stub
                btnSend.setEnabled( false );
                String txt  =  edtMessage.getText().toString();
                 if  (txt.equals( "" )) {
                    btnSend.setEnabled( true );
                     return ;
                }
                SocketClient proxy  =  SocketClient.getInstance();
                proxy.sendMessage(txt);
                edtMessage.setText( "" );
                btnSend.setEnabled( true );
            }
        });
    }

    @Override
     public   boolean  onKeyDown( int  keyCode, KeyEvent event) {

         if  (keyCode  ==  KeyEvent.KEYCODE_BACK  &&  event.getRepeatCount()  ==   0 ) {

            AlertDialog alertDialog  =   new  AlertDialog.Builder(
                    MainActivity. this ).setTitle( " 询问 " ).setMessage( " 是否注销登录? " )
                    .setPositiveButton( " 确定 " ,
                             new  DialogInterface.OnClickListener() {

                                 public   void  onClick(DialogInterface dialog,
                                         int  which) {
                                    MainActivity. this .finish();
                                }

                            }).setNegativeButton( " 取消 " ,

                     new  DialogInterface.OnClickListener() {
                         public   void  onClick(DialogInterface dialog,  int  which) {
                             return ;
                        }
                    }).create();  //  创建对话框

            alertDialog.show();  //  显示对话框

             return   false ;

        }

         return   false ;
    }
}

 

 五、运行效果

 

 

 

 

  代码下载