在Android中,我們可以通過使用標准的Java接口來完成Android應用程序的聯網操作。但是在實際開發中,可能會需要用到更復雜的聯網操作,為此,Android平台提供了Apache HttpClient接口,為客戶端的HTTP編程提供了高效、便捷、功能豐富的工具包支持。
Android平台在引入Apache HttpClient的同時,還對其進行了一些封裝和擴展,如設置缺省的HTTP超時和緩存大小等。使用Apache HttpClient接口,我們可以創建HttpClient、HttpGet/HttpPost、HttpResponse等對象,設置連接參數,執行HTTP操作,處理服務器返回結果等。
本文將以兩個實例演示在Android開發中如何使用HttpClient接口完成客戶端HTTP編程。其中,一個實例使用GET方式獲取服務器上的圖片進行顯示;一個實例使用POST方式向服務器提交數據,完成登錄功能。
1.常用的接口和類
在講解實例之前,我們有必要先了解一下在HttpClient接口中,為我們提供了哪些常用的接口和類。
1.1 ClientConnectionManager接口
ClientConnectionManager是客戶端連接管理器接口,用於對連接到服務器上的客戶端進行管理,主要提供了以下6個抽象方法:
(1)abstract void closeExpiredConnections();
(2)abstract void closeIdleConnections(long idletime, TimeUnit tunit);
(3)abstract SchemeRegistry getSchemeRegistry();
(4)abstract void releaseConnection(ManagedClientConnection conn, long validDuration, TimeUnit timeUnit);
(5)abstract ClientConnectionRequest requestConnection(HttpRoute route, Object state);
(6)abstract void shutdown();
其中,closeExpiredConnections()方法用於關閉所有過期的連接;closeIdleConnections()方法用於關閉所有空閑的連接;getSchemeRegistry()方法用於獲得注冊方案;releaseConnection()方法用於釋放連接;requestConnection()方法用於請求一個新的連接;shutdown()方法用於關閉管理器並釋放資源。
1.2 DefaultHttpClient
DefaultHttpClient是HttpClient接口的一個直接子類,它是一個默認的HTTP客戶端,通常我們可以使用它來創建一個HTTP連接。在HttpClient接口中提供了多個重載的execute()方法,用來執行HTTP請求。
1.3 HttpRequest接口
HttpGet和HttpPost都是HttpRequest接口的直接子類,分別用於向服務器提交GET請求和POST請求。
1.4 HttpResponse接口
HttpResponse接口提供了HTTP的響應信息,其主要方法如圖1所示。
圖1 HttpResponse接口提供的主要方法
其中,getEntity()方法用於獲取響應的消息實體;getStatusLine()方法用於獲取響應的狀態行,在返回結果StatusLine對象中包含了HTTP響應的狀態碼,可以使用方法getStatusCode()獲得。
2.使用GET方式獲取服務器上的圖片
在該實例中,我們使用了在上一篇博文《Android學習筆記46:使用Post方式提交數據》中搭建好的Web工程作為服務器,並在該工程中添加了一張名為“cat.jpg”的圖片作為我們將要獲取的對象。
使用GET方式獲取服務器上的圖片,可以按照以下4個步驟進行:
(1)創建一個GET方式的HttpRequest請求對象。
(2)創建一個默認的HTTP客戶端,並執行該GET方式的HTTP請求。
(3)獲得服務器的響應碼,據此判斷服務器是否正確響應。
(4)獲得服務器的響應內容(InputStream),轉換成Bitmap圖片。
以上4個步驟的具體實現代碼如下:
1 /* 2 * Function : 發送GET請求 3 * Author : 博客園-依舊淡然 4 */ 5 public static Bitmap sendGetResquest(String path) { 6 Bitmap bitmap = null; 7 HttpGet httpGet = new HttpGet(path); //創建一個GET方式的HttpRequest對象 8 DefaultHttpClient httpClient = new DefaultHttpClient(); //創建一個默認的HTTP客戶端 9 try { 10 HttpResponse httpResponse = httpClient.execute(httpGet); //執行GET方式的HTTP請求 11 int reponseCode = httpResponse.getStatusLine().getStatusCode(); //獲得服務器的響應碼 12 if(reponseCode == HttpStatus.SC_OK) { 13 InputStream inputStream = httpResponse.getEntity().getContent(); //獲得服務器的響應內容 14 bitmap = BitmapFactory.decodeStream(inputStream); 15 inputStream.close(); 16 } 17 } catch (ClientProtocolException e) { 18 e.printStackTrace(); 19 } catch (IOException e) { 20 e.printStackTrace(); 21 } 22 return bitmap; 23 }
最后,我們在Activity中通過一個Button按鈕來向服務器發送GET請求,並調用sendGetResquest()方法將得到的Bitmap對象顯示在ImageView控件中。具體的實現代碼如下:
1 /* 2 * Function : 點擊事件響應 3 * Author : 博客園-依舊淡然 4 */ 5 public void onClick(View view) { 6 switch(view.getId()) { 7 case R.id.button_get: 8 String url = "http://192.168.1.101:8080/myhttp/cat.jpg"; 9 Bitmap bitmap = HttpUtils.sendGetResquest(url); 10 mImageView.setImageBitmap(bitmap); 11 break; 12 } 13 }
運行該工程,點擊“提交GET請求”按鈕后,可以看到如圖2所示的顯示界面,在“提交GET請求”按鈕的下面所顯示的圖片正是我們從服務器上得到的圖片。
圖2 使用GET方式獲取服務器上的圖片
3.使用POST方式向服務器提交數據
在該實例中,我們同樣使用了在上一篇博文《Android學習筆記46:使用Post方式提交數據》中搭建好的Web工程作為服務器。運行Tomcat,在瀏覽器中訪問該Web工程,可以看到如圖3所示的界面。
圖3 Web工程的顯示頁面
該實例要做的就是,使用POST方式向服務器提交用戶名和密碼,模擬登錄過程,並獲得服務器的驗證信息,顯示登錄是否成功。
使用POST方式向服務器提交數據,比GET方式要稍微復雜點,具體可以按照以下5個步驟進行:
(1)對請求體參數(也就是username和password)進行封裝。
(2)創建一個POST方式的HttpRequest對象,並設置POST方式的請求體。
(3)創建一個默認的HTTP客戶端,並執行該POST方式的HTTP請求。
(4)獲得服務器的響應碼,據此判斷服務器是否正確響應。
(5)獲得服務器的響應內容(InputStream),轉換成String字符串進行顯示。
以上5個步驟的具體實現代碼如下:
1 /* 2 * Function : 發送POST請求 3 * Author : 博客園-依舊淡然 4 */ 5 public static String sendPostResquest(String path, Map<String, String> params, String encoding) { 6 List<NameValuePair> list = new ArrayList<NameValuePair>(); //封裝請求體參數 7 if((params != null) && !params.isEmpty()) { 8 for(Map.Entry<String, String> param : params.entrySet()) { 9 list.add(new BasicNameValuePair(param.getKey(), param.getValue())); 10 } 11 } 12 try { 13 UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, encoding); //對請求體參數進行URL編碼 14 HttpPost httpPost = new HttpPost(path); //創建一個POST方式的HttpRequest對象 15 httpPost.setEntity(entity); //設置POST方式的請求體 16 DefaultHttpClient client = new DefaultHttpClient(); 17 HttpResponse httpResponse = client.execute(httpPost); //執行POST請求 18 int reponseCode = httpResponse.getStatusLine().getStatusCode(); //獲得服務器的響應碼 19 if(reponseCode == HttpStatus.SC_OK) { 20 String resultData = EntityUtils.toString(httpResponse.getEntity()); //獲得服務器的響應內容 21 return resultData; 22 } 23 } catch (IOException e) { 24 e.printStackTrace(); 25 } 26 return ""; 27 }
同樣的,我們在Activity中通過一個Button按鈕來向服務器發送POST請求,並調用sendPostResquest()方法將得到的服務器響應結果顯示在TextView控件中。具體的實現代碼如下:
1 /* 2 * Function : 點擊事件響應 3 * Author : 博客園-依舊淡然 4 */ 5 public void onClick(View view) { 6 switch(view.getId()) { 7 case R.id.button_submit: 8 String username = mEditText_userName.getText().toString(); 9 String password = mEditText_password.getText().toString(); 10 Map<String, String> params = new HashMap<String, String>(); 11 params.put("username", username); 12 params.put("password", password); 13 String url = "http://192.168.1.101:8080/myhttp/servlet/LoginAction"; 14 mTextView_result.setText(HttpUtils.sendPostResquest(url, params, "utf-8")); 15 break; 16 } 17 }
運行該工程,在EditText控件中分別輸入用戶名和密碼,點擊“提交數據”按鈕后,可以看到如圖4所示的顯示界面,在“提交數據”按鈕下面的TextView控件中可以看到服務器返回了“Login succeeded!” 的提示信息。