1. 程式人生 > >面試篇--android下網路通訊機制(三種網路通訊方式)

面試篇--android下網路通訊機制(三種網路通訊方式)

HttpClient

HttpClient是Apache對java中的HttpURLClient介面的封裝,主要引用org.apache.http.**。Google在2.3版本之前推薦使用HttpClient,因為這個封裝包安全性高,bug較少。

使用方法:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpEntity;
import
org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.NameValuePair; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; import
org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; public class HttpClientUtils { private static HttpClient httpClient; private static HttpClientUtils instance = null; public static synchronized
HttpClientUtils getInstance() { if (instance == null) { instance = new HttpClientUtils(); } return instance; } private HttpClientUtils() { // 學習volley請求佇列,HttpClient使用單例模式 if (httpClient == null) { httpClient = new DefaultHttpClient(); } } /** * 以get方式傳送請求,訪問介面 * @param uri連結地址 * @return 響應資料 */ private static String doHttpGet(String uri) { BufferedReader reader = null; StringBuffer sb = null; String result = ""; HttpGet request = new HttpGet(uri); try { // 傳送請求,得到響應 HttpResponse response = httpClient.execute(request); // 請求成功,statuscode返回200 if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); sb = new StringBuffer(); String line = ""; while ((line = reader.readLine()) != null) { sb.append(line); } } } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (null != reader) { reader.close(); reader = null; } } catch (IOException e) { e.printStackTrace(); } } if (null != sb) { result = sb.toString(); } return result; } /** * 以post方式傳送請求,訪問介面 * @param uri連結地址 * @return 響應資料 */ private static String doHttpPost(String uri) { BufferedReader reader = null; StringBuffer sb = null; String result = ""; HttpPost request = new HttpPost(uri); // 儲存要傳遞的引數 List<NameValuePair> params = new ArrayList<NameValuePair>(); // 新增引數 params.add(new BasicNameValuePair("parameter", "以Post方式傳送請求")); try { // 設定字符集 HttpEntity entity = new UrlEncodedFormEntity(params, "utf-8"); // 請求物件 request.setEntity(entity); // 傳送請求 HttpResponse response = httpClient.execute(request); // 請求成功 if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { System.out.println("post success"); reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); sb = new StringBuffer(); String line = ""; while ((line = reader.readLine()) != null) { sb.append(line); } } } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { // 關閉流 if (null != reader) { reader.close(); reader = null; } } catch (IOException e) { e.printStackTrace(); } } if (null != sb) { result = sb.toString(); } return result; } }

HttpURLConnection

HttpURLConnection在java.NET下,繼承自URLConnection類,相對於HttpClient具有擴充套件性高、靈活性高,更輕量級的優點,所以Google在2.3版本之後推薦大家使用HttpURLConnection來操作網路請求。

使用方法:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;


public class HttpURLConnectUtils {

    private static HttpURLConnectUtils instance = null;

    public static synchronized HttpURLConnectUtils getInstance() {
        if (instance == null) {
            instance = new HttpURLConnectUtils();
        }
        return instance;
    }

    private HttpURLConnectUtils() {
    }

    // post
    public String dohttppost(String mUrl) throws IOException {

        URL url = new URL(mUrl);
        HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();//初始化建立HttpURLConnection例項
        httpURLConnection.setConnectTimeout(5000);//推薦設定網路延時
        httpURLConnection.setDoOutput(true);
        httpURLConnection.setDoInput(true);
        httpURLConnection.setUseCaches(false);
        httpURLConnection.setRequestProperty("Content-type", "application/x-java-serialized-object");
        httpURLConnection.setRequestMethod("POST");
        //設定引數
        OutputStream outputStream = httpURLConnection.getOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
        String params = new String();//這裡簡單設定引數
        params = "name=" + URLEncoder.encode("高冉", "GBK");
        objectOutputStream.writeBytes(params);
        objectOutputStream.flush();
        objectOutputStream.close();
        //接收返回值
        //String msg = httpURLConnection.getResponseMessage();// 接收簡單string
        InputStreamReader inputStreamReader = new InputStreamReader(httpURLConnection.getInputStream());
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
        StringBuilder builder = new StringBuilder();
        for (String s = bufferedReader.readLine(); s != null; s = bufferedReader.readLine()) {
            builder.append(s);
        }
        return builder.toString();
    }

    // get
    public String dohttpget(String mUrl) throws IOException {
        URL url = new URL(mUrl);
        HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
        httpURLConnection.setConnectTimeout(5000);//推薦設定網路延時
        httpURLConnection.setRequestMethod("GET");
        httpURLConnection.connect();

        // String msg = httpURLConnection.getResponseMessage();

        InputStreamReader inputStreamReader = new InputStreamReader(httpURLConnection.getInputStream());
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
        StringBuilder builder = new StringBuilder();
        for (String s = bufferedReader.readLine(); s != null; s = bufferedReader.readLine()) {
            builder.append(s);
        }

        return builder.toString();
    }
}

還需要注意一些細節:

1、post與get區別在於post將引數置於請求資料中,get則跟在url連結後面。
2、大檔案下載操作要置於sd卡中,不要放在手機記憶體中操作,而且需要邊讀邊寫,不要使用Buffered做快取。


三、我們看一個簡單的socket程式設計,實現伺服器回發客戶端資訊。

下面用個例子來說明:

A、客戶端:

新建Android專案工程:SocketForAndroid(這個隨意起名字了吧,我是以這個建立的!)

下面是main_activity.xml的程式碼:

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <?xml version="1.0"encoding="utf-8"?> android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello"/> <EditText android:id="@+id/message" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/hint"/> <Button android:id="@+id/send" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/send"/> </LinearLayout>

MainActivity.java的程式碼入下:

?
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 package com.yaowen.socketforandroid; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import android.widget.EditText; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.Socket; public class MainActivity extendsAppCompatActivity { privateEditText message; privateButton send; @Override protectedvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //初始化兩個UI控制元件 message = (EditText) findViewById(R.id.message); send = (Button) findViewById(R.id.send); //設定傳送按鈕的點選事件響應 send.setOnClickListener(newView.OnClickListener() { @Override publicvoid onClick(View v) { Socket socket =null; //獲取message輸入框裡的輸入的內容 String msg = message.getText().toString() +"\r\n"; try{ //這裡必須是192.168.3.200,不可以是localhost或者127.0.0.1 socket =new Socket("192.168.3.200",18888); PrintWriter out =new PrintWriter( newBufferedWriter( newOutputStreamWriter( socket.getOutputStream() ) ),true); //傳送訊息 out.println(msg); //接收資料 BufferedReader in =new BufferedReader( newInputStreamReader( socket.getInputStream() ) ); //讀取接收的資料 String msg_in = in.readLine(); if(null != msg_in) { message.setText(msg_in); System.out.println(msg_in); }else { message.setText("接收的資料有誤!"); } //關閉各種流 out.close(); in.close(); }catch (IOException e) { e.printStackTrace(); }finally { try{ if(null != socket) { //socket不為空時,最後記得要把socket關閉 socket.close(); } }catch (IOException e) { e.printStackTrace(); } } } }); } }

最後別忘記新增訪問網路許可權:

<uses-permission android:name="android.permission.INTERNET" />

B、服務端:

?
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 package service; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; public class ServerAndroid implementsRunnable { @Override publicvoid run() { Socket socket =null; try{ ServerSocket server =new ServerSocket(18888); // 迴圈監聽客戶端連結請求 while(true) { System.out.println("start..."); // 接收請求 socket = server.accept(); System.out.println("accept..."); // 接收客戶端訊息 BufferedReader in =new BufferedReader(newInputStreamReader(socket.getInputStream())); String message = in.readLine(); System.out.println(message); // 傳送訊息,向客戶端 PrintWriter out =new PrintWriter(newBufferedWriter(newOutputStreamWriter(socket.getOutputStream())), true); out.println("Server:"+ message); // 關閉流 in.close(); out.close(); } }catch (IOException e) { e.printStackTrace(); }finally { if(null != socket) { try{ socket.close(); }catch (IOException e) { e.printStackTrace(); } } } } // 啟動伺服器 publicstatic void main(String[] args) { Thread server =new Thread(newServerAndroid()); server.start(); } }

C、啟動伺服器,控制檯會打印出“start...”字串!

D、執行Android專案檔案,如下圖:



在輸入框裡輸入如下字串,點發送按鈕:



伺服器收到客戶端發來的訊息並列印到控制檯: