Android SocketService
android中,联网操作有http连接和socket连接两大类。由于项目需要,我们采取的是Socket连接。鉴于平时连接频繁,因此把Socket连接放到Service里,需要从服务器端获取数据时,只要调用Service中相应方法即可。
Service大致结构是:
public class InternetService extends Service implements Runnable { private Socket socket; private BufferedReader reader;// private PrintWriter writer;// private Binder binder; private Thread td;// 线程,获取服务器端发送来的消息 private String workStatus;// 当前工作状况,null表示正在处理,success表示处理成功,failure表示处理失败 private String currAction; //标记当前请求头信息,在获取服务器端反馈的数据后,进行验证,以免出现反馈信息和当前请求不一致问题。比如现在发送第二个请求,但服务器端此时才响应第一个请求 /** * 向服务器发送请求 * * @param action * */ public void sendRequest(String action) { try { workStatus = null; JSONObject json = new JSONObject(); json.put("action", action); currAction=action; sendMessage(json); } catch (Exception ex) { workStatus = Constant.TAG_FAILURE; ex.printStackTrace(); } } /** * 返回当前workStatus的值 * / public StringgetWorkStatus() { return workStatus ; } /** * 处理服务器端反馈的数据 * * @param json * */ private void dealUploadSuperviseTask(JSONObject json) { try{ workStatus=json.getString("result"); }catch(Exception ex) { ex.printStackTrace(); workStatus=Constant.TAG_FAILURE; } } /** * 退出程序时,关闭Socket连接 */ public void closeConnection() { JSONObject json = new JSONObject();// 向服务器端发送断开连接请求 try { json.put("action", "exit"); sendMessage(json);// 向服务器端发送断开连接请求 Log.v("qlq", "the request is " + json.toString()); } catch (Exception ex) { ex.printStackTrace(); } } /** * 连接服务器 */ private void connectService() { try { socket = new Socket(); SocketAddress socAddress = new InetSocketAddress(127.0.0, 8000)); socket.connect(socAddress, 3000); reader = new BufferedReader(new InputStreamReader( socket.getInputStream(), "GBK")); writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter( socket.getOutputStream(), "GBK")), true); } catch (SocketException ex) { Log.v("QLQ", "socketException "); ex.printStackTrace(); workStatus = Constant.TAG_CONNECTFAILURE;// 如果是网络连接出错了,则提示网络连接错误 return; } catch (SocketTimeoutException ex) { ex.printStackTrace(); workStatus = Constant.TAG_CONNECTFAILURE;// 如果是网络连接出错了,则提示网络连接错误 return; } catch (Exception ex) { ex.printStackTrace(); workStatus = Constant.TAG_CONNECTFAILURE;// 如果是网络连接出错了,则提示网络连接错误 return; } } /** * 向服务器发送传入的JSON数据信息 * * @param json */ private void sendMessage(JSONObject json) { if (!isNetworkConnected())// 如果当前网络连接不可用,直接提示网络连接不可用,并退出执行。 { Log.v("QLQ", "workStatus is not connected!111"); workStatus = Constant.TAG_CONNECTFAILURE; return; } if (socket == null)// 如果未连接到服务器,创建连接 connectService(); if (!InternetService.this.td.isAlive())// 如果当前线程没有处于存活状态,重启线程 (td = new Thread(InternetService.this)).start(); if (!socket.isConnected() || (socket.isClosed())) // isConnected()返回的是是否曾经连接过,isClosed()返回是否处于关闭状态,只有当isConnected()返回true,isClosed()返回false的时候,网络处于连接状态 { Log.v("QLQ", "workStatus is not connected!111222"); for (int i = 0; i < 3 && workStatus == null; i++) {// 如果连接处于关闭状态,重试三次,如果连接正常了,跳出循环 socket = null; connectService(); if (socket.isConnected() && (!socket.isClosed())) { Log.v("QLQ", "workStatus is not connected!11333"); break; } } if (!socket.isConnected() || (socket.isClosed()))// 如果此时连接还是不正常,提示错误,并跳出循环 { workStatus = Constant.TAG_CONNECTFAILURE; Log.v("QLQ", "workStatus is not connected!111444"); return; } } if (!socket.isOutputShutdown()) {// 输入输出流是否关闭 try { writer.println(json.toString()); } catch (Exception e) { // TODO Auto-generated catch block Log.v("QLQ", "workStatus is not connected!55555666666"); e.printStackTrace(); workStatus = Constant.TAG_FAILURE; } } else { workStatus = Constant.TAG_CONNECTFAILURE; } } /** * 处理服务器端传来的消息,并通过action头信息判断,传递给相应处理方法 * * @param str */ private void getMessage(String str) { try { JSONObject json = new JSONObject(str); String action = json.getString("action");// 提取JSON的action信息,获取当前JSON响应的是哪个操作。 if(!currAction.equals(action)) return; if (action.equals("getCategory")) { dealUploadSuperviseTask(json); } } catch (Exception ex) { ex.printStackTrace(); workStatus=Constant.TAG_FAILURE; } } public class InterBinder extends Binder { public InternetService getService() { return InternetService.this; } } @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub binder = new InterBinder(); td = new Thread(InternetService.this);// 启动线程 td.start(); return binder; } @Override public void onCreate() { super.onCreate(); // connectService(); } @Override public void onStart(Intent intent, int startId) { super.onStart(intent, startId); } @Override public void onDestroy() { super.onDestroy(); Log.v("QLQ", "Service is on destroy"); } @Override public boolean onUnbind(Intent intent) { Log.v("QLQ", "service on onUnbind"); return super.onUnbind(intent); } /** * 循环,接收从服务器端传来的数据 */ public void run() { try { while (true) { Thread.sleep(500);// 休眠0.5s if (socket != null && !socket.isClosed()) {// 如果socket没有被关闭 if (socket.isConnected()) {// 判断socket是否连接成功 if (!socket.isInputShutdown()) { String content; if ((content = reader.readLine()) != null) { getMessage(content); } } } } } } catch (Exception ex) { try { socket.close(); } catch (Exception e) { e.printStackTrace(); } workStatus = Constant.TAG_CONNECTFAILURE;// 如果出现异常,提示网络连接出现问题。 ex.printStackTrace(); } } }
InternetService innetService ; public ServiceConnection internetServiceConnection = new ServiceConnection() { public void onServiceConnected(ComponentName arg0, IBinder service) { innetService = ((InternetService.InterBinder) service).getService(); } public void onServiceDisconnected(ComponentName arg0) { innetService = null; } };
bindService(new Intent(BasicActivity.this, InternetService.class), internetServiceConnection, Context.BIND_AUTO_CREATE);//BasicActivity是我自己为所有Activity定义的基类,这段代码也是写在BasicActivity里。
unbindService(internetServiceConnection);
而定义currAction,则是为了标识好当前请求内容,由于服务器端反馈的信息上也有action头信息标识当前返回的数据对应哪种请求,所以,在发送请求时设置currAction,接收到服务器端反馈数据后,验证和currAction是否一致,如果不一致的话,就不作处理,表示“未等到希望的数据”,如果一致,才能执行下一步操作。这样可以防止数据匹配错误。
至于定义BasicActivity,则是因为软件中很多页面除了中间显示的内容外,头部按钮栏等都一致,此外还有很多共用的代码等,因此定义一个BasicActivity,作为他们的父类,减少代码量,这也是java多态的一种体现。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。