初学Android Socket 部分代码参考于网络,结合项目测试后修改总结,在此记录。
1 /**
2 * <p>
3 * socket连接服务
4 */
5 public class SocketService extends Service {
6
7 private static final String TAG = "SocketService";
8
9 /*socket*/
10 private Socket socket;
11 /*连接线程*/
12 private Thread connectThread;
13 private Timer timer = new Timer();
14
15
16 /* 读写输入流*/
17 private InputStream inputStream;
18 private DataInputStream dis;
19
20 /*读接收数据线程*/
21 private Thread readThread;
22 /*接收数据长度*/
23 private int rcvLength;
24 /*接收数据*/
25 private String rcvMsg;
26 /* 读取保存进数组*/
27 byte buff[] = new byte[1024 * 1024 * 2];
28
29 private OutputStream outputStream;
30
31
32 private SocketBinder sockerBinder = new SocketBinder();
33 private String ip;//IP地址,这里最好单独建立一个存放数据类,用来存放网络通讯使用到的数据
34 private String port;//端口号
35 private TimerTask task;
36
37 /*默认重连*/
38 private boolean isReConnect = true;
39
40
41 /* 线程状态,安全结束线程*/
42 private boolean threadStatus = false;
43
44 private Handler handler = new Handler(Looper.getMainLooper());
45
46
47 @Override
48 public IBinder onBind(Intent intent) {
49 return sockerBinder;
50 }
51
52
53 public class SocketBinder extends Binder {//通过ServiceConnection获取,后面会讲解
54 /*返回SocketService 在需要的地方可以通过ServiceConnection获取到SocketService */
55 public SocketService getService() {
56 return SocketService.this;
57 }
58 }
59
60 @Override
61 public void onCreate() {
62 super.onCreate();
63 }
64
65
66 @Override
67 public int onStartCommand(Intent intent, int flags, int startId) {
68
69 /*拿到传递过来的ip和端口号*/
70 ip = Constants.INTENT_IP;
71 port = Constants.INTENT_PORT;
72
73 Log.e(TAG, "000" + DeviceUuidFactory.getUuid());
74
75 /*初始化socket*/
76 initSocket();
77
78 return super.onStartCommand(intent, flags, startId);
79 }
80
81
82 /*初始化socket*/
83 private void initSocket() {
84
85 if (socket == null && connectThread == null) {
86
87 //启动读取数据
88 connectThread = new Thread(new Runnable() {
89 @Override
90 public void run() {
91 socket = new Socket();
92 try {
93 /*超时时间为20秒*/
94 socket.connect(new InetSocketAddress(ip, Integer.valueOf(port)), 20000);
95 /*连接成功的话 发送心跳包*/
96 if (socket.isConnected()) {
97
98 inputStream = socket.getInputStream();
99 dis = new DataInputStream(inputStream);
100
101 if (inputStream != null) {
102 /* 开启读写线程 */
103 threadStatus = true;
104 readThread = new ReadThread();
105 readThread.start();
106 }
107
108 /*因为Toast是要运行在主线程的 这里是子线程 所以需要到主线程哪里去显示toast*/
109 // toastMsg("socket已连接111111111");
110
111 /*发送心跳数据*/
112 sendBeatData();
113 }
114
115 } catch (IOException e) {
116 e.printStackTrace();
117 if (e instanceof SocketTimeoutException) {
118 toastMsg("连接超时,正在重连");
119 releaseSocket();
120 } else if (e instanceof NoRouteToHostException) {
121 toastMsg("该地址不存在,请检查");
122 stopSelf();
123 } else if (e instanceof ConnectException) {
124 toastMsg("连接异常或被拒绝,请检查");
125 stopSelf();
126 }
127 }
128 }
129 });
130 /*启动连接线程*/
131 connectThread.start();
132 }
133 }
134
135 /*因为Toast是要运行在主线程的 所以需要到主线程哪里去显示toast*/
136 private void toastMsg(final String msg) {
137
138 handler.post(new Runnable() {
139 @Override
140 public void run() {
141 Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
142 }
143 });
144 }
145
146
147 /**
148 * @param order
149 * @param msg//测试时使用
150 */
151 /*发送数据*/
152 public void sendOrder(final String order, final String msg) {
153 if (socket != null && socket.isConnected()) {
154 /*发送指令*/
155 new Thread(new Runnable() {
156 @Override
157 public void run() {
158 try {
159 Log.e("准备回复消息:", msg);
160 outputStream = socket.getOutputStream();
161 if (outputStream != null) {
162 outputStream.write(order.getBytes("gbk"));
163 outputStream.flush();
164 Log.e("消息发送成功:", order);
165 }
166 } catch (IOException e) {
167 e.printStackTrace();
168 //releaseSocket();
169 Log.e("消息回复异常", msg);
170 }
171 }
172 }).start();
173 } else {
174 Log.e(TAG, "socket连接错误,请重试");
175 releaseSocket();
176 }
177 }
178
179
180 /**
181 * 发送连接状态消息
182 *
183 * @param constants
184 */
185 private void sendEventMsg(String constants) {
186 EventMsg msg = new EventMsg();
187 msg.setTag(constants);
188 EventBus.getDefault().post(msg);
189 }
190
191 /**
192 * 发送连接状态消息
193 *
194 * @param constants
195 */
196 private void sendEventMsg(String constants, String rcvMsg) {
197 EventMsg msg = new EventMsg();//EventMsg的使用自行百度
198 msg.setTag(constants);
199 msg.setMsg(rcvMsg);
200 EventBus.getDefault().post(msg);
201 }
202
203
204 /**
205 * 接收数据
206 */
207 private class ReadThread extends Thread {
208 @TargetApi(Build.VERSION_CODES.KITKAT)
209 @Override
210 public void run() {
211 super.run();
212 //判断进程是否在运行,更安全的结束进程
213 try {
214 while (!socket.isClosed() && threadStatus && ((rcvLength = dis.read(buff)) != -1)) {
215
216 Log.e(TAG, "buff:" + buff);
217
218 if (rcvLength > 0) {
219 rcvMsg = new String(buff, 0, rcvLength, "GBK");
220 toastMsg("收到服务器消息");
221 //接收到数据
222 handleData(rcvMsg);//处理数据并回复服务器
223 }
224 }
225 } catch (Exception e) {
226 toastMsg("接收总控数据异常");
227 }
228
229 }
230 }
231
232
233 /*定时发送数据*/
234 private void sendBeatData() {
235 if (timer == null) {
236 timer = new Timer();
237 }
238
239 if (task == null) {
240 task = new TimerTask() {
241 @Override
242 public void run() {
243 try {
244 outputStream = socket.getOutputStream();
245 /*这里的编码方式根据需求去改*/
246 outputStream.write("这是一条心跳数据".getBytes("gbk"));
247 outputStream.flush();
248 /*发送连接成功的消息*/
249 //这里可以建立一条消息发送到Activity处理界面相关
250 } catch (Exception e) {
251 /*发送失败说明socket断开了或者出现了其他错误*/
252 toastMsg("连接断开,正在重连");
253 /*发送连接失败的消息*/
254 sendEventMsg(Constants.CONNET_FAIL, "");
255 /*重连*/
256 releaseSocket();
257 e.printStackTrace();
258 }
259 }
260 };
261 }
262
263 timer.schedule(task, 0, 60000);//心跳每隔60000毫秒发送一次,60s
264 }
265
266
267 /*释放资源*/
268 private void releaseSocket() {
269
270 if (task != null) {
271 task.cancel();
272 task = null;
273 }
274 if (timer != null) {
275 timer.purge();
276 timer.cancel();
277 timer = null;
278 }
279
280 if (outputStream != null) {
281 try {
282 outputStream.close();
283
284 } catch (IOException e) {
285 e.printStackTrace();
286 }
287 outputStream = null;
288 }
289
290 if (socket != null) {
291 try {
292 socket.close();
293
294 } catch (IOException e) {
295 }
296 socket = null;
297 }
298
299 if (connectThread != null) {
300 connectThread = null;
301 }
302
303 if (readThread != null) {
304 readThread = null;
305 }
306
307 /*重新初始化socket*/
308 if (isReConnect) {
309 initSocket();
310 }
311
312 }
313
314
315 /**
316 * 服务器消息回复
317 *
318 * @param msg
319 * @param
320 */
321 @TargetApi(Build.VERSION_CODES.KITKAT)
322 public void handleData(String msg) throws IOException {
323 sendOrder("确认收到消息", msg);
324 }
325
326
327 @Override
328 public void onDestroy() {
329 super.onDestroy();
330 Log.i("SocketService", "onDestroy");
331 isReConnect = false;
332 threadStatus = false;
333 releaseSocket();
334 }
335 }
IBinder 使用方法
1 ServiceConnection serviceConnection = new ServiceConnection() {
2 @Override
3 public void onServiceConnected(ComponentName name, IBinder service) {
4 SocketService.SocketBinder socketBinder = (SocketService.SocketBinder) service;
5 socketBinder.getService().
6 }
7
8 @Override
9 public void onServiceDisconnected(ComponentName name) {
10
11 }
12 };