如果某位朋友也打算做这个Socket聊天工具,本人有个小小的建议,你可以不必太着急些代码,先想清楚自己最终要做到怎样效果,然后把自己的思路都写下来,有一个基本的实现方法。在写代码时就按照自己的思路一步一步地写下去,这样可以很好地避免写代码时由于思路不清左删右改。
以下是本人程序的设计思路
客户端设计思路:
一 用户登录界面
1 用一个EditText作为用户名输入口,用一个按键确定。
2 注册一个广播接收器,专门接收由后来的聊天界面发过来的消息广播(包括发信人,收信人,消息体)。
3 创建一个客户端连接服务端的方法(要在线程中启动该方法),连接成功并获取输入输出流以后,再在里面启动一个输入流管理线程(接受并处理由服务端发送过来的消息)。并通过intent启动下一个好友列表界面(同时把自身用户名发给下一界面)。
4 对于输入流管理线程,要先判断接收到的是好友名单还是聊天消息发送两种广播,(服务端发送两种信息时可以加个标签以便线程区分)。然后分发出两种广播,一种广播后面的好友列表界面接受的在线好友名单,另一种广播出聊天界面接收的聊天信息。
5 在菜单下做一个退出Activity按键,方便用户退出程序。
6 当一切准备好以后,用户在输入用户名并点击确定,就可以实现以上操作,同时进入了好友列表界面(前提是能正确连接上服务端)。
二 好友列表界面
1 注册一个广播接收器,专门接收由登录界面的输入流管理线程发送过来的好友名单广播
2 用listView逐个显示好友名单。
3 获取用户登录界面发过来的自身用户名。
4 给listView绑定一个监听器,当用户点击listView上的某一好友时,通过intent启动下一个聊天界面,并把所点击到的好友用户名以及自身用户名发给下一个界面。
三 聊天界面
1 获取好友列表界面发送过来的聊天好友用户名以及自身用户名,并在Title上显示。
2 用一个EditText作为聊天消息输入口,用一个按键确定输出。
3 当用户点击确定以后,发送一个消息广播(包含发信人,收信人,消息体),让用户登录界面的消息广播接收器接收。
4 注册一个广播接收器接受用户登录界面的输入流管理线程发送过来的消息。
服务端设计思路:
消息处理界面(只有一个界面)
1 创建一个监听连接请求方法 (监听客户端发送连接请求,需要在线程中启动)。
A 当用户发送连接请求时,生成socket对象。由该socket对象生成输出流和输入流,从输入流中提取出客户端发送过来的用户名,把用户名放到sickName数组上,把输出流放在ArrayOut数组中。
B 发送新客户端XXX连接成功广播。
C 预先用sickName数组和ArrayOut数组创建发送好友列表方法(给各已连接客户端发送好友名单),在这里调用方法。
D 新生成并启动输入流管理线程(接受并处理客户端发送过来的消息,由于有一个新用户生成,就新生一个输入流管理线程,所以客户端发送的消息不会混乱)。
2 创建发送好友列表方法。
3 注册两个广播接收器,一个接收新客户端XXX连接成功广播;另一个接收输入流管理线程发送过来的聊天消息,识别出目标对象,并向目标对象分别发送消息。
4 在onResume方法中启动监听线程。
5 在菜单下做一个退出Activity按键和刷新按钮(再次发送已连接用户名单给各客户端)。
可完善地方:
可考虑好友退出时显示离线。
非正在聊天好友发送信息时提醒。
只要登录了,未接信息可以一直保存,当进入聊天界面时可以再度显示。
可考虑添加LQ头像与聊天表情。
。。。。。。
客户端代码:
1 用户登录界面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
|
package
cn.text2;
import
java.io.BufferedWriter;
import
java.io.OutputStreamWriter;
import
java.io.PrintWriter;
import
java.net.InetAddress;
import
java.net.Socket;
import
android.app.Activity;
import
android.content.BroadcastReceiver;
import
android.content.Context;
import
android.content.Intent;
import
android.content.IntentFilter;
import
android.os.Bundle;
import
android.view.Menu;
import
android.view.MenuItem;
import
android.view.View;
import
android.widget.Button;
import
android.widget.EditText;
public
class
Text2Activity
extends
Activity {
Button buttonSure;
Button buttonDump;
EditText editTextName;
PrintWriter output ;
Text2Helper text2helper;
int
k =
0
;
/** Called when the activity is first created. */
@Override
public
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.main);
buttonSure = (Button)findViewById(R.id.buttonSure);
editTextName = (EditText)findViewById(R.id.editTextName);
}
/*****确定按键*******/
public
void
buttonsure(View v) {
new
Thread(){
public
void
run(){
Connect();
System.out.println(
"注册Text2ClientActivity的发送信息广播"
);
}
}.start();
System.out.println(
"注册Text2ClientActivity的发送信息广播"
);
OpenBroadcastReceiver();
}
/****注册广播方法*******/
public
void
OpenBroadcastReceiver(){
//生成BroadcastReceiver对象
Text2ClientActivityReceiver Receiver =
new
Text2ClientActivityReceiver();
//生成过滤器IntentFilter对象
IntentFilter filter =
new
IntentFilter();
//为过滤器添加识别标签
filter.addAction(
"android.intent.action.VOICE_COMMAND"
);
//读取Text2ClientActivity的发送信息广播
//接收广播状态
Text2Activity.
this
.registerReceiver(Receiver, filter);
System.out.println(
"注册广播完成!"
);
}
/********广播接收器类***********/
//专门读取Text2ClientActivity的发送信息广播
public
class
Text2ClientActivityReceiver
extends
BroadcastReceiver {
@Override
public
void
onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
String yourself = intent.getStringExtra(
"SendYourself"
);
//接收要发送的对象名称以及信息
String target = intent.getStringExtra(
"SendTarget"
);
String message = intent.getStringExtra(
"SendMessage"
);
if
(k>
0
){
output.println(yourself);
//yourself
output.flush();
output.println(target);
//target
output.flush();
output.println(message);
//内容
output.flush();
System.out.println(
"接收器接收到Text2ClientActivity的广播,并发送到服务端"
);
}
}
}
/*********启动客户端方法***********/
public
void
Connect(){
try
{
InetAddress addr = InetAddress.getByName(
"192.168.22.10"
);
//服务端手机网络IP地址,连一下wifi就可以知道
System.out.println(
"客户端发出请求"
);
//客户端向服务端发出连接请求
Socket socket =
new
Socket(addr,
6666
);
System.out.println(
"连接成功,socket="
+ socket);
//通过该条socket通道得到输出流
output =
new
PrintWriter(
new
BufferedWriter(
new
OutputStreamWriter(socket.getOutputStream())),
true
);
System.out.println(
"输出流获取成功"
);
output.println(editTextName.getEditableText().toString());
output.flush();
k++;
//启动getMessage线程
text2helper =
new
Text2Helper(socket,
this
);
//生成新的CGetMessage对象即调用一次CGetMessage
Thread gt =
new
Thread(text2helper);
gt.start();
/**跳转到下一个FriendListActivity**/
Intent intentdump =
new
Intent();
intentdump.putExtra(
"ClientName"
,editTextName.getText().toString());
intentdump.setClass(Text2Activity.
this
, Text2FriendActivity.
class
);
Text2Activity.
this
.startActivity(intentdump);
}
catch
(Exception e) {
e.printStackTrace();
}
}
/********菜单功能**********/
@Override
public
boolean
onCreateOptionsMenu(Menu menu) {
menu.add(
0
,
1
,
1
,
"退出"
);
menu.add(
0
,
2
,
2
,
"连接"
);
return
true
;
}
@Override
public
boolean
onMenuItemSelected(
int
featureId, MenuItem item) {
if
(item.getItemId() ==
1
){
finish();
}
if
(item.getItemId() ==
2
){
new
Thread(){
public
void
run()
{
Connect();
}
}.start();
}
return
super
.onMenuItemSelected(featureId, item);
}
}
|
2 好友列表界面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
package
cn.text2;
import
java.util.ArrayList;
import
java.util.HashMap;
import
android.app.Activity;
import
android.content.BroadcastReceiver;
import
android.content.Context;
import
android.content.Intent;
import
android.content.IntentFilter;
import
android.os.Bundle;
import
android.view.Menu;
import
android.view.MenuItem;
import
android.view.View;
import
android.widget.AdapterView;
import
android.widget.ListView;
import
android.widget.SimpleAdapter;
import
android.widget.TextView;
import
android.widget.Toast;
import
android.widget.AdapterView.OnItemClickListener;
public
class
Text2FriendActivity
extends
Activity {
TextView textViewfriendlist;
ListView listViewfriendlist;
static
Toast tt =
null
;
int
i =
1
;
String Clients[] = {
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
};
String YourName;
SimpleAdapter simpleAdapter;
ArrayList<HashMap<String, String>> listItem;
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.friend);
Intent intentdump = getIntent();
YourName = intentdump.getStringExtra(
"ClientName"
);
listViewfriendlist = (ListView)findViewById(R.id.listViewfriendlist);
textViewfriendlist = (TextView)findViewById(R.id.textViewfriendlist);
/**********listView数据数组与适配器的定义*************/
listItem =
new
ArrayList<HashMap<String,String>>();
//定义列表数组
HashMap<String, String> map =
new
HashMap<String, String>();
map.put(
"LvMessage"
,
"好友:"
);
listItem.add(map);
simpleAdapter =
new
SimpleAdapter(
this
,listItem,
R.layout.text2user,
new
String[] {
"LvMessage"
},
new
int
[] {R.id.LvTextViewMessage});
//定义适配器
listViewfriendlist.setAdapter(simpleAdapter);
listViewfriendlist.setOnItemClickListener(
new
ListViewListener());
OpenBroadcastReceiver();
//注册接收UpLoadActivity发送过来的好友名单广播
Clients[
0
]=
"Jack"
;
}
/*******listView的监听器**********/
class
ListViewListener
implements
OnItemClickListener{
@Override
public
void
onItemClick(AdapterView<?> arg0, View arg1,
int
arg2,
long
arg3) {
// TODO Auto-generated method stub
setTitle(
"你点击了第"
+arg2+
"行"
);
//设置标题栏显示点击的行 (从0开始)
// if(arg2>0){
/**跳转到下一个Text2ClientActivity**/
Intent intentdump2 =
new
Intent();
intentdump2.putExtra(
"Target"
,Clients[arg2]);
//目标联系人
intentdump2.putExtra(
"Yourself"
, YourName);
//自身用户名
intentdump2.setClass(Text2FriendActivity.
this
, Text2TalkActivity.
class
);
Text2FriendActivity.
this
.startActivity(intentdump2);
// }
}
}
/****注册广播方法*******/
public
void
OpenBroadcastReceiver(){
//生成BroadcastReceiver对象
FriendListReceiver Receiver =
new
FriendListReceiver();
//生成过滤器IntentFilter对象
IntentFilter filter =
new
IntentFilter();
//为过滤器添加识别标签
filter.addAction(
"android.intent.action.DIAL"
);
//接收广播状态
Text2FriendActivity.
this
.registerReceiver(Receiver, filter);
System.out.println(
"注册广播完成!"
);
}
/********广播接收器类***********/
//接收UpLoadActivity发送过来的好友名单
public
class
FriendListReceiver
extends
BroadcastReceiver {
@Override
public
void
onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
String msg = intent.getStringExtra(
"FriendListmessage"
);
//给列表添加数据
Clients[i] = msg;
HashMap<String, String> map =
new
HashMap<String, String>();
map.put(
"LvMessage"
,msg);
listItem.add(map);
listViewfriendlist.setAdapter(simpleAdapter);
System.out.println(
"接收器接收到广播--->"
+msg+
",并显示在listView上"
);
i++;
}
}
/********菜单功能**********/
@Override
public
boolean
onCreateOptionsMenu(Menu menu) {
menu.add(
0
,
1
,
1
,
"退出"
);
return
true
;
}
@Override
public
boolean
onMenuItemSelected(
int
featureId, MenuItem item) {
if
(item.getItemId() ==
1
){
finish();
}
return
super
.onMenuItemSelected(featureId, item);
}
}
|
3 聊天界面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
|
package
cn.text2;
import
java.io.BufferedWriter;
import
java.io.DataInputStream;
import
java.io.OutputStreamWriter;
import
java.io.PrintWriter;
import
java.net.InetAddress;
import
java.net.Socket;
import
java.util.ArrayList;
import
java.util.HashMap;
import
android.app.Activity;
import
android.content.DialogInterface;
import
android.content.DialogInterface.OnClickListener;
import
android.content.BroadcastReceiver;
import
android.content.Context;
import
android.content.Intent;
import
android.content.IntentFilter;
import
android.os.Bundle;
import
android.os.Message;
import
android.os.Vibrator;
import
android.text.Editable;
import
android.view.Menu;
import
android.view.MenuItem;
import
android.view.View;
import
android.widget.Button;
import
android.widget.EditText;
import
android.widget.ListView;
import
android.widget.SimpleAdapter;
import
android.widget.TextView;
import
android.widget.Toast;
public
class
Text2TalkActivity
extends
Activity {
TextView textViewMessage;
Button buttonSend;
EditText editText;
ListView listView;
Vibrator vibrator;
static
Toast tt =
null
;
SimpleAdapter simpleAdapter;
ArrayList<HashMap<String, String>> listItem;
String Yourself;
String Target;
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.talk);
Intent intent2 = getIntent();
Yourself = intent2.getStringExtra(
"Yourself"
);
Target = intent2.getStringExtra(
"Target"
);
setTitle(
"I am "
+Yourself+
" --->"
+Target);
textViewMessage = (TextView)findViewById(R.id.textViewMessage);
buttonSend = (Button)findViewById(R.id.buttonSend);
editText = (EditText)findViewById(R.id.editText);
listView = (ListView)findViewById(R.id.listView);
tt = Toast.makeText(Text2TalkActivity.
this
,
"有消息"
, Toast.LENGTH_SHORT);
/**********listView数据数组与适配器的定义*************/
listItem =
new
ArrayList<HashMap<String,String>>();
//定义列表数组
HashMap<String, String> map =
new
HashMap<String, String>();
map.put(
"LvMessage"
,
"聊天内容:"
);
listItem.add(map);
simpleAdapter =
new
SimpleAdapter(
this
,listItem,
R.layout.text2user,
new
String[] {
"LvMessage"
},
new
int
[] {R.id.LvTextViewMessage});
//定义适配器
listView.setAdapter(simpleAdapter);
Text2TalkBroadcastReceiver();
}
/******发送信息按钮监听器********/
public
void
buttonsend(View v) {
HashMap<String, String> map =
new
HashMap<String, String>();
map.put(
"LvMessage"
, Yourself +
":"
+editText.getEditableText());
listItem.add(map);
listView.setAdapter(simpleAdapter);
Intent intent =
new
Intent();
intent.setAction(intent.ACTION_VOICE_COMMAND);
//给UploadActivity发送广播yourself
intent.putExtra(
"SendYourself"
,Yourself);
intent.putExtra(
"SendTarget"
,Target);
intent.putExtra(
"SendMessage"
,editText.getEditableText().toString());
Text2TalkActivity.
this
.sendBroadcast(intent);
System.out.println(
"向服务端发送信息:"
+editText.getEditableText());
}
/****注册广播方法*******/
public
void
Text2TalkBroadcastReceiver(){
//生成BroadcastReceiver对象
Text2TalkbroadcastReceiver Receiver =
new
Text2TalkbroadcastReceiver();
//生成过滤器IntentFilter对象
IntentFilter filter =
new
IntentFilter();
//为过滤器添加识别标签
filter.addAction(
"android.intent.action.PICK"
);
//接收由Text2FriendActivity发送过来的信息
//接收广播状态
Text2TalkActivity.
this
.registerReceiver(Receiver, filter);
System.out.println(
"注册广播完成!"
);
}
/********广播接收器类***********/
//接收由Text2FriendActivity发送过来的信息
public
class
Text2TalkbroadcastReceiver
extends
BroadcastReceiver {
@Override
public
void
onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
String msg = intent.getStringExtra(
"TextMessage"
);
//给列表添加数据
HashMap<String, String> map =
new
HashMap<String, String>();
map.put(
"LvMessage"
, msg);
listItem.add(map);
listView.setAdapter(simpleAdapter);
System.out.println(
"Text2Talk接收器接收到广播--->"
+msg+
",并显示在listView上"
);
vibrator();
//震动
}
}
/******震动30ms方法******/
public
void
vibrator(){
vibrator = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(
30
);
System.out.println(
"震动30ms"
);
}
/*************菜单*******************/
@Override
public
boolean
onCreateOptionsMenu(Menu menu) {
menu.add(
0
,
0
,
0
,
"清除"
);
menu.add(
0
,
1
,
1
,
"退出"
);
return
true
;
}
@Override
public
boolean
onMenuItemSelected(
int
featureId, MenuItem item) {
if
(item.getItemId() ==
0
){
ArrayList<HashMap<String, String>> listItem1 =
new
ArrayList<HashMap<String,String>>();
/*在数组中存放数据*/
HashMap<String, String> map =
new
HashMap<String, String>();
map.put(
"ItemText"
,
"聊天内容:"
);
listItem1.add(map);
SimpleAdapter simpleAdapter1 =
new
SimpleAdapter(
this
,listItem1,
R.layout.text2user,
new
String[] {
"ItemText"
},
new
int
[] {R.id.LvTextViewMessage});
listView.setAdapter(simpleAdapter1);
}
if
(item.getItemId() ==
1
){
finish();
}
return
super
.onMenuItemSelected(featureId, item);
}
}
|
服务端代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
|
package
cn.Text2Server;
import
java.io.BufferedReader;
import
java.io.BufferedWriter;
import
java.io.DataInputStream;
import
java.io.DataOutputStream;
import
java.io.IOException;
import
java.io.InputStreamReader;
import
java.io.OutputStreamWriter;
import
java.io.PrintWriter;
import
java.net.InetAddress;
import
java.net.ServerSocket;
import
java.net.Socket;
import
java.net.SocketAddress;
import
java.util.ArrayList;
import
java.util.HashMap;
import
java.util.Map;
import
android.app.Activity;
import
android.content.BroadcastReceiver;
import
android.content.Context;
import
android.content.Intent;
import
android.content.IntentFilter;
import
android.os.Bundle;
import
android.view.Menu;
import
android.view.MenuItem;
import
android.view.View;
import
android.widget.Button;
import
android.widget.EditText;
import
android.widget.ListView;
import
android.widget.SimpleAdapter;
import
android.widget.TextView;
import
android.widget.Toast;
public
class
Text2ServerActivity
extends
Activity {
TextView textViewHead =
null
;
TextView textViewMessage;
Button buttonStart;
Button buttonSend;
EditText editText;
ListView listView;
static
Toast toast =
null
;
PrintWriter out,o1,o2,o3,o4,o5,o6,o7,o8,o9,o10,o11,o12,o13,o14,o15,o16,o17,o18,o19,o20;
PrintWriter ArrayOut[] = {o1,o2,o3,o4,o5,o6,o7,o8,o9,o10,o11,o12,o13,o14,o15,o16,o17,o18,o19,o20};
//直接写(PrintWriter[] ArrayOut)不成功
int
k =
0
;
//记录已连接的客户端数
int
m =
0
;
// 区分显示在服务端的目标对象与body
String ReceiveMessage =
"客户端:\n"
;
String nickName[] = {
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
,
""
};
String from,to,body;
String packet[] = {from,to,body};
SimpleAdapter simpleAdapter;
ArrayList<HashMap<String, String>> listItem;
HashMap<String, String> map;
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.main);
textViewHead = (TextView)findViewById(R.id.textView);
textViewMessage = (TextView)findViewById(R.id.textViewMessage);
buttonSend = (Button)findViewById(R.id.buttonSend);
editText = (EditText)findViewById(R.id.editText);
listView = (ListView)findViewById(R.id.listView);
toast = Toast.makeText(Text2ServerActivity.
this
,
"连接成功"
, Toast.LENGTH_SHORT);
/**********listView数据数组与适配器的定义*************/
listItem =
new
ArrayList<HashMap<String,String>>();
//定义列表数组
map =
new
HashMap<String, String>();
map.put(
"LvMessage"
,
"聊天内容:"
);
listItem.add(map);
simpleAdapter =
new
SimpleAdapter(
this
,listItem,
R.layout.user,
new
String[] {
"LvMessage"
},
new
int
[] {R.id.LvTextViewMessage});
//定义适配器
listView.setAdapter(simpleAdapter);
}
/********发送信息按钮监听器*******/
//这个可以不要
public
void
buttonsend(View v){
HashMap<String, String> map =
new
HashMap<String, String>();
map.put(
"LvMessage"
,
"服务端:"
+editText.getEditableText());
listItem.add(map);
listView.setAdapter(simpleAdapter);
out.println(editText.getEditableText());
//发送出该字符串
out.flush();
System.out.println(
"向客户端发送信息:"
+editText.getEditableText());
}
/****注册接收信息广播方法*******/
public
void
OpenBroadcastReceiver(){
//生成BroadcastReceiver对象
broadcastReceiver Receiver =
new
broadcastReceiver();
//生成过滤器IntentFilter对象
IntentFilter filterMessage =
new
IntentFilter();
//为过滤器添加识别标签
filterMessage.addAction(
"android.intent.action.EDIT"
);
//接收广播状态
Text2ServerActivity.
this
.registerReceiver(Receiver, filterMessage);
System.out.println(
"注册广播完成!"
);
}
/********信息广播接收器类***********/
public
class
broadcastReceiver
extends
BroadcastReceiver {
@Override
public
void
onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
//给列表添加数据
String msg = intent.getStringExtra(
"message"
);
packet[m] = msg;
m++;
if
(msg.equals(
"监听中"
)||msg.equals(
"已连接"
)){
textViewHead.setText(
"服务端: 状态:"
+msg);
System.out.println(
"接收器已接收到连接状态msg并显示在TextView上"
);
m =
0
;
}
if
(m>=
3
){
m =
0
;
String ReceiveMessage =
"From 客户端-"
+packet[
0
]+
"To 客户端-"
+packet[
1
] +
" :"
+packet[
2
];
HashMap<String, String> map =
new
HashMap<String, String>();
map.put(
"LvMessage"
, ReceiveMessage);
listItem.add(map);
listView.setAdapter(simpleAdapter);
System.out.println(
"接收器已接收到消息并显示在ListView上"
);
for
(
int
i=
0
;i<k;i++){
//让目标对象与好友名单列表逐个对比
if
(nickName[i].equals(packet[
1
])){
SendMessage(ArrayOut[i],packet[
0
]+
":"
+packet[
2
]);
break
;
}
}
}
}
}
/********发送信息方法**************/
public
void
SendMessage(PrintWriter target,String msg){
target.println(msg);
target.flush();
}
/****注册接收已连接用户名称广播方法*******/
public
void
ConnectedClientReceiver(){
//生成BroadcastReceiver对象
ConnectedClientbroadcastReceiver Receiver2 =
new
ConnectedClientbroadcastReceiver();
//生成过滤器IntentFilter对象
IntentFilter filterfriends =
new
IntentFilter();
//为过滤器添加识别标签
filterfriends.addAction(
"android.intent.action.INSERT"
);
//接收广播状态
Text2ServerActivity.
this
.registerReceiver(Receiver2, filterfriends);
System.out.println(
"注册广播完成!"
);
}
/********接收已连接用户名称广播接收器类***********/
public
class
ConnectedClientbroadcastReceiver
extends
BroadcastReceiver {
@Override
public
void
onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
String msg = intent.getStringExtra(
"nickname"
);
textViewMessage.setText(textViewMessage.getText()+msg+
"\n"
);
System.out.println(
"向各客户端发送好友列表"
);
}
}
/*****onResume方法:启动监听线程*******/
@Override
protected
void
onResume() {
// TODO Auto-generated method stub
super
.onResume();
new
Thread(){
public
void
run()
{
StartListener();
}
}.start();
System.out.println(
"注册广播"
);
OpenBroadcastReceiver();
ConnectedClientReceiver();
}
/**********向各客户端发送好友列表方法**************/
public
void
SendFriendList(){
//发送已连接用户名单给个客户端线程
for
(
int
m=
0
;m<k;m++){
//m代表客户端序号
if
(m==k-
1
){
//k-1代表新连接的客户端
ArrayOut[m].println(
"&"
);
//&,让客户端识别到是好友名单即将发送的标志
ArrayOut[m].flush();
for
(
int
n=
0
;n<=k-
1
;n++){
//n代表是好友名单序号
ArrayOut[m].println(nickName[n]);
ArrayOut[m].flush();
}
ArrayOut[m].println(
"#"
);
//#,让客户端识别到是好友名单发送完毕的标志
ArrayOut[m].flush();
}
else
{
ArrayOut[m].println(
"&"
);
ArrayOut[m].flush();
ArrayOut[m].println(nickName[k-
1
]);
ArrayOut[m].flush();
ArrayOut[m].println(
"#"
);
ArrayOut[m].flush();
}
}
}
/*********监听连接请求方法 ********/
public
void
StartListener(){
while
(
true
){
try
{
//服务端监听6666端口
ServerSocket s =
new
ServerSocket(
6666
);
System.out.println(
"服务器端------监听中......"
);
Intent intent =
new
Intent();
intent.setAction(intent.ACTION_EDIT);
intent.putExtra(
"message"
,
"监听中"
);
Text2ServerActivity.
this
.sendBroadcast(intent);
System.out.println(
"监听中"
);
Socket socket = s.accept();
System.out.println(
"通道连接成功\n"
+
"socket:"
+ socket);
//获取刚连接客户端的输出流并放在数组上
PrintWriter out =
new
PrintWriter(
new
BufferedWriter(
new
OutputStreamWriter(socket.getOutputStream())),
true
);
ArrayOut[k] = out;
//获取刚连接客户端的名称并放在数组上
BufferedReader br =
new
BufferedReader(
new
InputStreamReader(socket.getInputStream(),
"utf-8"
));
String name =br.readLine();
nickName[k] = name;
//在服务端显示已连接好友
Intent intent1 =
new
Intent();
intent1.setAction(intent.ACTION_INSERT);
//向自身发送传输广播
intent1.putExtra(
"nickname"
,name);
Text2ServerActivity.
this
.sendBroadcast(intent1);
System.out.println(
"好友"
+name+
"已连接上服务端"
);
//在服务端显示连接成功
Intent intent2 =
new
Intent();
Text2ServerActivity.
this
.toast.show();
intent2.setAction(intent.ACTION_EDIT);
//向自身发送传输广播
intent2.putExtra(
"message"
,
"已连接"
);
Text2ServerActivity.
this
.sendBroadcast(intent2);
System.out.println(
"发送完成客户端连接请求广播"
);
k++;
//发送已连接用户名单给各个客户端
SendFriendList();
//启动GetMessage线程
GetMessage gm =
new
GetMessage(socket,
this
);
//生成新的runnable实现类对象
Thread gt =
new
Thread(gm);
//生成新的线程
gt.start();
//启动线程
System.out.println(
"启动getMesage线程"
);
}
catch
(IOException e1) {
e1.printStackTrace();
}
}
}
/************菜单*************/
@Override
public
boolean
onCreateOptionsMenu(Menu menu) {
menu.add(
0
,
0
,
0
,
"清除"
);
menu.add(
0
,
1
,
1
,
"退出"
);
menu.add(
0
,
2
,
2
,
"刷新"
);
//再次发送已连接用户名单给各个客户端
return
true
;
}
@Override
public
boolean
onMenuItemSelected(
int
featureId, MenuItem item) {
if
(item.getItemId() ==
0
){
ArrayList<HashMap<String, String>> listItem1 =
new
ArrayList<HashMap<String,String>>();
/*在数组中存放数据*/
HashMap<String, String> map =
new
HashMap<String, String>();
map.put(
"ItemText"
,
"聊天内容:"
);
listItem.add(map);
SimpleAdapter simpleAdapter1 =
new
SimpleAdapter(
this
,listItem1,
R.layout.user,
new
String[] {
"ItemText"
},
new
int
[] {R.id.LvTextViewMessage} );
listView.setAdapter(simpleAdapter1);
}
if
(item.getItemId() ==
1
){
finish();
}
if
(item.getItemId() ==
2
){
for
(
int
m=
0
;m<k;m++){
//m代表客户端序号
if
(m==k-
1
){
//k-1代表新连接的客户端
ArrayOut[m].println(
"&"
);
//&,让客户端识别到是好友名单即将发送的标志
ArrayOut[m].flush();
for
(
int
n=
0
;n<=k-
1
;n++){
//n代表是好友名单序号
ArrayOut[m].println(nickName[n]);
ArrayOut[m].flush();
}
ArrayOut[m].println(
"#"
);
//#,让客户端识别到是好友名单发送完毕的标志
ArrayOut[m].flush();
}
else
{
ArrayOut[m].println(
"&"
);
ArrayOut[m].flush();
ArrayOut[m].println(nickName[k-
1
]);
ArrayOut[m].flush();
ArrayOut[m].println(
"#"
);
ArrayOut[m].flush();
}
}
}
return
super
.onMenuItemSelected(featureId, item);
}
}
|
好了,就写这么多,希望对各位想做Socket聊天工具的朋友有所帮助!!