内容摘要
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
;
}
}
五、运行效果
代码下载
出处:http://www.cnblogs.com/GoodHelper/archive/2011/07/08/android_socket_chart.html
欢迎转载,但需保留版权!