Android - HTTP 協議訪問網絡

使用 HTTP 協議訪問網絡

果真的說要去深入分析 HTTP 協議,可能需要花費整整一本書的篇幅。這裏我當然不
會這麼幹,因爲畢竟你是跟着我學習 Android 開發的,而不是網站開發。對於 HTTP 協議,
你只需要稍微瞭解一些就足夠了,它的工作原理特別的簡單,就是客戶端向服務器發出一條
HTTP 請求,服務器收到請求之後會返回一些數據給客戶端,然後客戶端再對這些數據進行
解析和處理就可以了。是不是非常簡單?一個瀏覽器的基本工作原理也就是如此了。比如說
上一節中使用到的 WebView 控件,其實也就是我們向百度的服務器發起了一條 HTTP 請求,
接着服務器分析出我們想要訪問的是百度的首頁,於是會把該網頁的 HTML 代碼進行返回,
然後WebView再調用手機瀏覽器的內核對返回的HTML代碼進行解析, 最終將頁面展示出來。


使用 HttpURLConnection

首先需要獲取到 HttpURLConnection 的實例,一般只需 new 出一個 URL 對象,並傳入
目標的網絡地址,然後調用一下 openConnection()方法即可,如下所示:

URL url = new URL("http://www.baidu.com");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();

得到了 HttpURLConnection 的實例之後,我們可以設置一下 HTTP 請求所使用的方法。
常用的方法主要有兩個,GET 和 POST。GET 表示希望從服務器那裏獲取數據,而 POST 則
表示希望提交數據給服務器。寫法如下:

connection.setRequestMethod("GET");

接下來就可以進行一些自由的定製了,比如設置連接超時、讀取超時的毫秒數,以及服
務器希望得到的一些消息頭等。這部分內容根據自己的實際情況進行編寫,示例寫法如下:
connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);

之後再調用 getInputStream()方法就可以獲取到服務器返回的輸入流了, 剩下的任務就是
對輸入流進行讀取,如下所示:

InputStream in = connection.getInputStream();

最後可以調用 disconnect()方法將這個 HTTP 連接關閉掉,如下所示:

connection.disconnect();

實例 : 

public class MainActivity extends Activity implements OnClickListener {
public static final int SHOW_RESPONSE = 0;
private Button sendRequest;
private TextView responseText;
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case SHOW_RESPONSE:
String response = (String) msg.obj;
// 在這裏進行UI操作,將結果顯示到界面上
responseText.setText(response);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sendRequest = (Button) findViewById(R.id.send_request);
responseText = (TextView) findViewById(R.id.response_text);
sendRequest.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.send_request) {
sendRequestWithHttpURLConnection();
}
}
private void sendRequestWithHttpURLConnection() {
// 開啓線程來發起網絡請求
new Thread(new Runnable() {
@Override
public void run() {
HttpURLConnection connection = null;
try {
URL url = new URL("http://www.baidu.com");
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);
InputStream in = connection.getInputStream();
// 下面對獲取到的輸入流進行讀取
BufferedReader reader = new BufferedReader(new
InputStreamReader(in));
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
Message message = new Message();
message.what = SHOW_RESPONSE;
// 將服務器返回的結果存放到Message中
message.obj = response.toString();
handler.sendMessage(message);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
}).start();
}
}
可以看到,我們在 Send Request 按鈕的點擊事件裏調用了 sendRequestWithHttpURL-
Connection()方法, 在這個方法中先是開啓了一個子線程, 然後在子線程裏使用HttpURLConnection
發出一條 HTTP 請求,請求的目標地址就是百度的首頁。接着利用 BufferedReader 對服務器
返回的流進行讀取,並將結果存放到了一個 Message 對象中。這裏爲什麼要使用 Message 對
象呢?當然是因爲子線程中無法對 UI 進行操作了。我們希望可以將服務器返回的內容顯示
到界面上, 所以就創建了一個 Message 對象, 並使用 Handler 將它發送出去。 之後又在 Handler
的 handleMessage()方法中對這條 Message 進行處理,最終取出結果並設置到 TextView 上。
完整的一套流程就是這樣,不過在開始運行之前,仍然別忘了要聲明一下網絡權限。修
改 AndroidManifest.xml 中的代碼,如下所示:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.networktest"
android:versionCode="1"
android:versionName="1.0" >
……
<uses-permission android:name="android.permission.INTERNET" />
……
</manifest>


使用 HttpClient(注 : Android Studio已經不能使用了,因爲Google在Android6.0對這個接口放棄了使用)

HttpClient是 Apache提供的 HTTP網絡訪問接口, 從一開始的時候就被引入到了 Android
API 中。它可以完成和 HttpURLConnection 幾乎一模一樣的效果,但兩者之間的用法卻有較
大的差別,那麼我們自然要看一下 HttpClient 是如何使用的了。
首先你需要知道,HttpClient 是一個接口,因此無法創建它的實例,通常情況下都會創
建一個 DefaultHttpClient 的實例,如下所示:

HttpClient httpClient = new DefaultHttpClient();

接下來如果想要發起一條 GET 請求,就可以創建一個 HttpGet 對象,並傳入目標的網絡
地址,然後調用 HttpClient 的 execute()方法即可:

HttpGet httpGet = new HttpGet("http://www.baidu.com");
httpClient.execute(httpGet);

如果是發起一條 POST 請求會比 GET 稍微複雜一點,我們需要創建一個 HttpPost 對象,
並傳入目標的網絡地址,如下所示:

	HttpPost post = new HttpPost("http://www.baidu.com");
	List<NameValuePair> list = new ArrayList<NameValuePair>();
	list.add(new BasicNameValuePair("username", "admin"));
	list.add(new BasicNameValuePair("password", "123456"));
	UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, "utf-8");
	post.setEntity(entity);

接下來的操作就和 HttpGet 一樣了,調用 HttpClient 的 execute()方法,並將 HttpPost 對
象傳入即可:

httpClient.execute(httpPost);
執行 execute()方法之後會返回一個 HttpResponse對象, 服務器所返回的所有信息就會包
含在這裏面。通常情況下我們都會先取出服務器返回的狀態碼,如果等於 200就說明請求和
響應都成功了,如下所示:
if (httpResponse.getStatusLine().getStatusCode() == 200) {
// 請求和響應都成功了
}
接下來在這個 if 判斷的內部取出服務返回的具體內容,可以調用 getEntity()方法獲取到
一個 HttpEntity 實例, 然後再用 EntityUtils.toString()這個靜態方法將 HttpEntity 轉換成字符串
即可,如下所示:

HttpEntity entity = httpResponse.getEntity();
String response = EntityUtils.toString(entity);

注意如果服務器返回的數據是帶有中文的,直接調用 EntityUtils.toString()方法進行轉換
會有亂碼的情況出現,這個時候只需要在轉換的時候將字符集指定成 utf-8 就可以了,如下
所示:

String response = EntityUtils.toString(entity, "utf-8");
好了,基本的用法就是如此

實例 :

public class MainActivity extends Activity implements OnClickListener {
……
@Override
public void onClick(View v) {
if (v.getId() == R.id.send_request) {
sendRequestWithHttpClient();
}
}
private void sendRequestWithHttpClient() {
new Thread(new Runnable() {
@Override
public void run() {
try {
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet("http://www.baidu.com");
HttpResponse httpResponse = httpClient.execute(httpGet);
if (httpResponse.getStatusLine().getStatusCode() == 200) {
//  請求和響應都成功了
HttpEntity entity = httpResponse.getEntity();
String response = EntityUtils.toString(entity,
"utf-8");
Message message = new Message();
message.what = SHOW_RESPONSE;
//  將服務器返回的結果存放到Message 中
message.obj = response.toString();
handler.sendMessage(message);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
……
}













發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章