Android Service+Socket 联网交互
?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();
??? ??? }
??? }
}
在前臺頁面上,由于前臺和后臺要進行數據交互,因此需要使用bindService方法綁定服務。
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;
??? ??? }
??? };
然后在onCreate里,執行
bindService(new Intent(BasicActivity.this, InternetService.class),
??? ??? ??? ??? internetServiceConnection, Context.BIND_AUTO_CREATE);//BasicActivity是我自己為所有Activity定義的基類,這段代碼也是寫在BasicActivity里。
由于服務綁定后必須要解除,因此在onDestroy中應加上代碼
unbindService(internetServiceConnection);
之所以定義workStatus,是為了讓前臺知道當前聯網操作是否成功。
而定義currAction,則是為了標識好當前請求內容,由于服務器端反饋的信息上也有action頭信息標識當前返回的數據對應哪種請求,所以,在發送請求時設置currAction,接收到服務器端反饋數據后,驗證和currAction是否一致,如果不一致的話,就不作處理,表示“未等到希望的數據”,如果一致,才能執行下一步操作。這樣可以防止數據匹配錯誤。
至于定義BasicActivity,則是因為軟件中很多頁面除了中間顯示的內容外,頭部按鈕欄等都一致,此外還有很多共用的代碼等,因此定義一個BasicActivity,作為他們的父類,減少代碼量,這也是java多態的一種體現。
?
?
http://www.cnblogs.com/ruiati/p/3491136.html
總結
以上是生活随笔為你收集整理的Android Service+Socket 联网交互的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 安卓开发之android使用webvie
- 下一篇: js文件代码未加载或者没有js效果