1. 程式人生 > >Android系列之網路(一)----使用HttpClient傳送HTTP請求(通過get方法獲取資料)

Android系列之網路(一)----使用HttpClient傳送HTTP請求(通過get方法獲取資料)

轉載地址:http://www.cnblogs.com/smyhvae/p/4004983.html

 這個關於http的內容寫的比較好

一、HTTP協議初探:

HTTP(Hypertext Transfer Protocol)中文 “超文字傳輸協議”,是一種為分散式,合作式,多媒體資訊系統服務,面向應用層的協議,是Internet上目前使用最廣泛的應用層協議,它基於傳輸層的TCP協議進行通訊,HTTP協議是通用的、無狀態的協議。

這幾個名詞有一種通俗的解釋:

  • 通訊協議:雙方對話的標準
  • 通用的:用了都說好,誰用誰知道
  • 無狀態的:翻臉不認人
  • 超文字:除了文字,還可以是音訊、視訊

HTTP協議與Android開發之間的關係:

HTTP協議的學習重點:

  • Http協議基礎概念、
  • 請求響應模型、
  • 提交請求的不同方法、
  • 響應狀態判斷、
  • 獲取響應以及解析響應、
  • 資料下載的實現方法、
  • 資料上傳的實現方法、
  • 請求頭詳細內容、
  • 響應頭詳細內容等

關於http協議的學習,推薦兩個連結:

二、http協議概念: 1、http協議定義: WWW是以Internet作為傳輸媒介的一個應用系統,WWW網上基本的傳輸單位是Web網頁。WWW的工作是基於客戶機/伺服器計算模型,由Web瀏覽器和Web伺服器構成,兩者之間採用超文字傳輸協議HTTP進行通訊。 HTTP協議時基於TCP/IP協議之上的協議,是Web瀏覽器和Web伺服器之間的應用層的協議,是通用的、無狀態的面向物件的協議。 如果要實現網路互聯我們要思考兩個需要解決的技術問題:
  • 第一:瀏覽器和伺服器是通過什麼來連線的。
  • 第二:這種連線方式是怎麼實現的。
通過Internet去傳送到伺服器當中,而Internet內部可以通過三種方式來實現傳送資訊和資料:
  • 第一種:HTTP協議,也是在工作中最常用的,是建立在TCP/IP基礎上實現的。
  • 第二種:FTP協議
  • 第三種:TCP/IP協議,它也是最底層的協議,其它的方式必須是要通過它,但是要想實現這種協議必須要實現socket程式設計,這種方法是用來上傳一些比較大的檔案,視訊,進行斷點續傳的操作。
2、客戶端連線伺服器實現內部的原理如下: 分析上圖,步驟如下:
  • 第一步:在瀏覽器客戶端中得到使用者輸入的內容。 
  • 第二步:瀏覽器得到這個網址之後,內部會將這個域名傳送到DNS上,進行域名解析。得到它的IP之後就會連結到指定的伺服器上,假如伺服器的地址是:221.104.13.32:80,從瀏覽器到伺服器埠它使用到最底層的TCP/IP協議。 
  • 第三步:實現TCP/IP協議用Socket來完成,使用了Socket的套接字。 
  • 第四步:伺服器端的80埠監聽客戶端的連結,這樣客戶端到伺服器就連結上了。
  • 伺服器接收到這些內容之後,並按照這些請求的路徑找到對應的頁面,進一步找到對應的網頁內容,返回給客戶端。
通俗一點講,使用者在瀏覽器輸入網址,通過http協議發出去,網址經過DNS域名解析,解析成指定的ip地址,並在80埠上監聽使用者的請求。伺服器監聽到請求之後,會以三種方式返回給客戶端:HTML、XML、JASON。 HTTP返回請求資料的三種方式:
  • 1、以HTML程式碼內容返回。 
  • 2、以XML字串的形式返回,在以後的android開發中這種形式返回資料比較多。 
  • 3、以JSON物件形式返回,在網路流量上考慮JSON要比XML方式要好一些,便於解析。
在Android當中,一般使用xml和Json資料解析。

三、使用HTTP協議訪問網路:

Android中的WebView控制元件已經在後臺幫我們處理好了傳送HTTP請求、接收服務響應、解析返回資料,以及最終的頁面展示這幾步工作,不過由於它封裝得太好了,反而不能直觀地看出HTTP協議是如何工作的。因此接下來我們通過手動傳送HTTP請求的方式,來更加深入的瞭解這一過程。

在Android上傳送HTTP請求的方式一般有兩種:HttpURLConnectionHttpCient。我們先來學習HttpCient。

四、HttpCient:

HttpClient是Apache開源組織提供的HTTP網路訪問介面(一個開源的專案),從名字上就可以看出,它是一個簡單的HTTP客戶端(並不是瀏覽器),可以傳送HTTP請求,接受HTTP響應。但是不會快取伺服器的響應,不能執行HTTP頁面中籤入嵌入的JS程式碼,自然也不會對頁面內容進行任何解析、處理,這些都是需要開發人員來完成的。

現在Android已經成功集成了HttpClient,所以開發人員在Android專案中可以直接使用HttpClient來想Web站點提交請求以及接受響應,如果使用其他的Java專案,需要引入進相應的Jar包。HttpClient可以在官網上下載。官網連結:http://hc.apache.org/downloads.cgi

HttpClient其實是一個interface型別,HttpClient封裝了物件需要執行的Http請求、身份驗證、連線管理和其它特性。既然HttpClient是一個介面,因此無法建立它的例項。從文件上看,HttpClient有三個已知的實現類分別是:AbstractHttpClient, AndroidHttpClient, DefaultHttpClient,會發現有一個專門為Android應用準備的實現類AndroidHttpClient,當然使用常規的DefaultHttpClient也可以實現功能。

從兩個類包所有在位置就可以看出區別,AndroidHttpClient定義在android.net.http.AndroidHttpClient包下,屬於Android原生的http訪問,而DefaultHttpClient定義在org.apache.http.impl.client.DefaultHttpClient包下,屬於對apche專案的支援。而AndroidHttpClient沒有公開的建構函式,只能通過靜態方法newInstance()方法來獲得AndroidHttpClient物件。

簡單來說,用HttpClient傳送請求、接收響應都很簡單,只需要五大步驟即可:(要牢記)

  • 建立代表客戶端的HttpClient物件。
  • 建立代表請求的物件,如果需要傳送GET請求,則建立HttpGet物件,如果需要傳送POST請求,則建立HttpPost物件。注:對於傳送請求的引數,GET和POST使用的方式不同,GET方式可以使用拼接字串的方式,把引數拼接在URL結尾;POST方式需要使用setEntity(HttpEntity entity)方法來設定請求引數。
  • 呼叫HttpClient物件的execute(HttpUriRequest request)傳送請求,執行該方法後將獲得伺服器返回的HttpResponse物件。伺服器發還給我們的資料就在這個HttpResponse相應當中。呼叫HttpResponse的對應方法獲取伺服器的響應頭、響應內容等。
  • 檢查相應狀態是否正常。伺服器發給客戶端的相應,有一個相應碼:相應碼為200,正常;相應碼為404,客戶端錯誤;相應碼為505,伺服器端錯誤。
  • 獲得相應物件當中的資料

五、DefaultHttpClient:

根據上面的五大步驟,我們就拿DefaultHttpClient舉例來訪問網路。注意這裡有一條原則:在主執行緒中不能訪問網路(在android4.0之後的加入的概念)。

【例項】點選按鈕,獲取百度首頁的文字內容

新建工程檔案m04_http01。完整版程式碼如下:

首先是佈局檔案,雖然比較簡單,但還是貼上吧。

activity_main.xml程式碼如下:

複製程式碼
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <Button
        android:id="@+id/button1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Send Request" />

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <TextView
            android:id="@+id/TextView1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/hello_world" />
    </ScrollView>

</LinearLayout>
複製程式碼

佈局檔案中,我們用一個ScrollView來包裹TextView。藉助ScrollView控制元件的話,就可以允許我們一滾動的形式檢視螢幕外i的那部分內容

MainActivity.java的程式碼如下:(註釋比較詳細)

複製程式碼
 1 package com.example.m04_http01;
 2 
 3 import org.apache.http.HttpEntity;
 4 import org.apache.http.HttpResponse;
 5 import org.apache.http.client.HttpClient;
 6 import org.apache.http.client.methods.HttpGet;
 7 import org.apache.http.impl.client.DefaultHttpClient;
 8 import org.apache.http.util.EntityUtils;
 9 import android.app.Activity;
10 import android.os.Bundle;
11 import android.os.Handler;
12 import android.os.Message;
13 import android.view.View;
14 import android.view.View.OnClickListener;
15 import android.widget.Button;
16 import android.widget.TextView;
17 
18 public class MainActivity extends Activity {
19 
20     public static final int SHOW_RESPONSE = 0;
21     
22     private Button button_sendRequest;
23     private TextView textView_response;
24     
25     //新建Handler的物件,在這裡接收Message,然後更新TextView控制元件的內容
26     private Handler handler = new Handler() {
27 
28         @Override
29         public void handleMessage(Message msg) {
30             super.handleMessage(msg);
31             switch (msg.what) {
32             case SHOW_RESPONSE:
33                 String response = (String) msg.obj;
34                 textView_response.setText(response);
35                 break;
36 
37             default:
38                 break;
39             }            
40         }
41 
42     };
43     
44     @Override
45     protected void onCreate(Bundle savedInstanceState) {
46         super.onCreate(savedInstanceState);
47         setContentView(R.layout.activity_main);
48         textView_response = (TextView)findViewById(R.id.TextView1);
49         button_sendRequest = (Button)findViewById(R.id.button1);
50         
51         button_sendRequest.setOnClickListener(new OnClickListener() {
52             
53             //點選按鈕時,執行sendRequestWithHttpClient()方法裡面的執行緒
54             @Override
55             public void onClick(View v) {
56                 // TODO Auto-generated method stub
57                 sendRequestWithHttpClient();
58             }
59         });
60     }
61 
62     //方法:傳送網路請求,獲取百度首頁的資料。在裡面開啟執行緒
63     private void sendRequestWithHttpClient() {
64         new Thread(new Runnable() {
65             
66             @Override
67             public void run() {
68                 //用HttpClient傳送請求,分為五步
69                 //第一步:建立HttpClient物件
70                 HttpClient httpCient = new DefaultHttpClient();
71                 //第二步:建立代表請求的物件,引數是訪問的伺服器地址
72                 HttpGet httpGet = new HttpGet("http://www.baidu.com");
73                 
74                 try {
75                     //第三步:執行請求,獲取伺服器發還的相應物件
76                     HttpResponse httpResponse = httpCient.execute(httpGet);
77                     //第四步:檢查相應的狀態是否正常:檢查狀態碼的值是200表示正常
78                     if (httpResponse.getStatusLine().getStatusCode() == 200) {
79                         //第五步:從相應物件當中取出資料,放到entity當中
80                         HttpEntity entity = httpResponse.getEntity();
81                         String response = EntityUtils.toString(entity,"utf-8");//將entity當中的資料轉換為字串
82                         
83                         //在子執行緒中將Message物件發出去
84                         Message message = new Message();
85                         message.what = SHOW_RESPONSE;
86                         message.obj = response.toString();
87                         handler.sendMessage(message);
88                     }
89                     
90                 } catch (Exception e) {
91                     // TODO Auto-generated catch block
92                     e.printStackTrace();
93                 }
94                 
95             }
96         }).start();//這個start()方法不要忘記了        
97         
98     }    
99 }
複製程式碼

大致流程如下:

這裡,我們添加了一個sendRequestWithHttpClient()方法(第63行),並在點選事件中去呼叫這個方法。在這個方法中,先開啟了一個子執行緒。

69至81行:在子執行緒中使用HttpClient發出一條HTTP請求,請求的目標地址是百度的首頁。

83至87行:為了能讓結果在介面上顯示出來,將伺服器返回的資料放到了Message物件中,並用Handler將Message發出去。

需要注意的是:

第80行的entity就是伺服器發還給客戶端的資料。

最後要記得在清單檔案中宣告訪問網路的許可權:

複製程式碼
<uses-sdk

android:minSdkVersion="8"

android:targetSdkVersion="16" />

<uses-permission android:name="android.permission.INTERNET"/>
複製程式碼

程式執行後,點選按鈕,顯示結果如下:

伺服器返回給我們的就是這種HTML程式碼,只是通常情況下瀏覽器都會將這些程式碼解析成漂亮的網頁後再展示出來。

參考連結: