Android系列之網路(一)----使用HttpClient發送HTTP請求,androidhttpclient
【聲明】
歡迎轉載,但請保留文章原始出處→_→
生命壹號:http://www.cnblogs.com/smyhvae/
文章來源:http://www.cnblogs.com/smyhvae/p/4004983.html
連絡方式:smyhvae@163.com
一、HTTP協議初探:
HTTP(Hypertext Transfer Protocol)中文 “超文字傳輸通訊協定 (HTTP)”,是一種為分布式,合作式,多媒體資訊系統服務,面嚮應用層的協議,是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協議訪問網路:
Android中的WebView控制項已經在後台幫我們處理好了發送HTTP請求、接收服務響應、解析返回資料,以及最終的頁面展示這幾步工作,不過由於它封裝得太好了,反而不能直觀地看出HTTP協議是如何工作的。因此接下來我們通過手動發送HTTP請求的方式,來更加深入的瞭解這一過程。
在Android上發送HTTP請求的方式一般有兩種:HttpURLConnection和HttpCient。我們先來學習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 @Override29 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 @Override45 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 @Override55 public void onClick(View v) {56 // TODO Auto-generated method stub57 sendRequestWithHttpClient();58 }59 });60 }61 62 //方法:發送網路請求,擷取百度首頁的資料。在裡面開啟線程63 private void sendRequestWithHttpClient() {64 new Thread(new Runnable() {65 66 @Override67 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 block92 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-sdkandroid:minSdkVersion="8"android:targetSdkVersion="16" /><uses-permission android:name="android.permission.INTERNET"/>
程式運行後,點擊按鈕,顯示結果如下:
伺服器返回給我們的就是這種HTML代碼,只是通常情況下瀏覽器都會將這些代碼解析成漂亮的網頁後再展示出來。
參考連結:
http://www.cnblogs.com/plokmju/p/Android_apacheHttpClient.html
android 使用HttpClient訪問網路 伺服器端與用戶端互動問題
解答:初步判斷,json解析有問題。一般情況下,解析json必須要明確json字串的內容。通俗地來講,就是說你要知道整個json字串的結構組成,有幾個大括弧{},包括嵌套的大括弧{},有幾個中括弧[],包括嵌套的[]。然後由外及內,最外層肯定是大括弧{},就是一個json對象,也就是JsonObject,接著再在這一層,看看有沒有中括弧[],有的話就是json數組,也就是JsonArray,當前層的欄位值可以根據當前層的json對象和欄位名擷取。如此,往內再走下一層json對象,也就是說查看第二個大括弧{},依此類推。
大家看看這是什情況,使用httpclient發送http,經常連線逾時
如果是公網的,逾時很正常,處理一下就好了。