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

【聲明】 html

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

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

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

 

 

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

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

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

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

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

 

【正文】 app

1、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

 

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

 

3、使用HTTP協議訪問網絡:

Android中的WebView控件已經在後臺幫咱們處理好了發送HTTP請求、接收服務響應、解析返回數據,以及最終的頁面展現這幾步工做,不過因爲它封裝得太好了,反而不能直觀地看出HTTP協議是如何工做的。所以接下來咱們經過手動發送HTTP請求的方式,來更加深刻的瞭解這一過程。

在Android上發送HTTP請求的方式通常有兩種:HttpURLConnectionHttpCient。咱們先來學習HttpCient。

 

4、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,服務器端錯誤。
  • 得到相應對象當中的數據

 

5、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

相關文章
相關標籤/搜索