Android系列之網絡(一)----使用HttpClient發送HTTP請求(通過get方法獲取數據)


【聲明】 

歡迎轉載,但請保留文章原始出處→_→ 

生命壹號:http://www.cnblogs.com/smyhvae/

文章來源:http://www.cnblogs.com/smyhvae/p/4004983.html

 

 

【系列】Android系列之網絡:(持續更新)

Android系列之網絡(一)----使用HttpClient發送HTTP請求(通過get方法獲取數據)

Android系列之網絡(二)----HTTP請求頭與響應頭

Android系列之網絡(三)----使用HttpClient發送HTTP請求(分別通過GET和POST方法發送數據)

Android系列之網絡(四)----SAX方式解析XML數據

 

【正文】 

一、HTTP協議初探:

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

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

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

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

HTTP協議的學習重點:

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

關於http協議的學習,推薦兩個鏈接:

http://www.cnblogs.com/TankXiao/archive/2012/02/13/2342672.html

http://blog.csdn.net/gueter/article/details/1524447

 

二、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代碼,只是通常情況下瀏覽器都會將這些代碼解析成漂亮的網頁后再展示出來。

參考鏈接:

http://www.cnblogs.com/plokmju/p/Android_apacheHttpClient.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM