1.使用HttpURLConnection
在Android上發送HTTP請求的方式一般有兩種,HttpURLConnection和HttpClient,先學習一下HttpURLConnection的用法。
首先需要獲取到HttpURLConnection的實例,一般只需new出一個URL對象,並傳入目標的網絡地址,然後調用一下openConnection()方法即可,如下所示:
URL url = new URL("http://www.baidu.com");
HttpURLConnection connection=(HttpURLConnection) url.openConnection();
得到了HttpURLConnection的實例之後,設置一下HTTP請求所使用的方法。常用的兩個方法爲get和post。get表示希望從服務器那裏獲取數據,而post則表示希望提交數據給服務器。寫法如下:
connection.setRequestMethod("GET");
此外就是設置連接超時,讀取超時的毫秒數,以及服務器希望得到的一些消息頭等。
connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);
之後就是在調用getInputStream()方法就可以獲取到服務器返回的輸入流了,剩下的任務就是對輸入流進行讀取,如下所示:
InputStream in = connection.getInputStream();
最後調用disconnect()方法將這個HTTP連接關閉掉,如下所示:
connection.disconnect();
新建一個Network項目,首先修改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/btnSendRequest"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="sendRequest"
android:text="Send Request" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="@+id/tvRespones"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextView" />
</ScrollView>
</LinearLayout>
這裏我們用了一個新的控件ScrollView,借用ScrollView控件的話就可以允許我們以滾動的形式查看屏幕外的那部分內容。另外,佈局中還放置了一個Button和一個TextView
Button用於發送HTTP請求,TextView用於將服務器返回的數據顯示出來。
接着修改MainActivity中的代碼,如下所示:
package com.example.nettest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends Activity {
private TextView tvResponse;
public static final int SHOW_RESPONSE=1;
private Handler handler=new Handler(){
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case SHOW_RESPONSE:
String content=(String) msg.obj;
tvResponse.setText(content);
break;
default:
break;
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvResponse=(TextView) findViewById(R.id.tvRespones);
}
public void sendRequest(View view){
sendRequestWithHttpUrlConnection();
}
private void sendRequestWithHttpUrlConnection() {
new Thread(){
public void run() {
HttpURLConnection httpURLConnection=null;
try {//獲取HttpURLConnection的實例,new出對象,傳入目標的網絡地址,調用OpenConnection方法
URL url=new URL("http://www.baidu.com");
httpURLConnection=(HttpURLConnection) url.openConnection();
httpURLConnection.setRequestMethod("GET");//get請求,從服務器那裏獲取數據
httpURLConnection.setConnectTimeout(6000);//設置連接超時
InputStream is=httpURLConnection.getInputStream();//獲取服務器返回的輸入流
//下面是對獲取到的輸入流進行讀取
BufferedReader br=new BufferedReader(new InputStreamReader(is));
String s;
StringBuilder sb=new StringBuilder();
while((s=br.readLine())!=null){
sb.append(s);
}
Message message=new Message();
message.what=SHOW_RESPONSE;
//將服務器返回的結果存放到Message中
message.obj=sb.toString();
handler.sendMessage(message);
System.out.println("getContent="+sb.toString());
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
httpURLConnection.disconnect();//關閉Http連接
}
};
}.start();
}
}
可以看到,我們在Send Requset按鈕的點擊事件中調用了sendRequestWithHttpURLConnection()方法,在這個方法中先是開啓了子線程,然後在子線程中使用HttpURL-
Connection發出一條HTTP請求,請求的目標地址就是百度的首頁;接着利用BufferedReader對服務器返回的流進行讀取,並將結果存放到Message對象中。
完整的一套流程就是這樣,在運行程序之前,不要忘了聲明一下網絡權限,修改AndroidMainifest.xml中的代碼,如下所示:
<uses-permission android:name="android.permission.INTERNET"/>
程序運行結果如下所示:
2.使用HttpClient
HttpClient是Apache提供的HTTP網絡訪問接口,從一開始的時候就被引用到了Android API中。它可以完成和HttpURLConnection幾乎一模一樣的效果,但兩者之間的用法卻
有很大的差別。
首先我們要知道,HttpClient是一個接口,因此無法創建它的實例,這裏我們創建一個DefaultHttpClient的實例,如下所示:
HttpClient httpClient = new DefaultHttpClient();
接下來如果想要發起一條get請求,就可以創建一個HttpGet對象,並傳入目標的網絡地址,然後調用HttpClient的execute()方法即可:
HttpGet httpGet= new HttpGet("http://www.baidu.com");
httpClient.execute(httpGet);
如果是發起一條POST請求會比get稍微複雜一些,我們要創建一個HttpPost對象,並傳入目標的網絡地址,如下所示:
HttpPost httpPost = new HttpPost("http://www.baidu.com");
然後通過一個NameValuePair集合來存放待提交的參數,並將這個參數集合傳入到一個UrlEncodedEntity中,然後調用HttpPost的setEntity()方法將構建好的UrlEncodedEntity傳入,如下所示:
List<NameValuePair> params =new ArrayList<NameValuePair>();
params.add(newBasicNameValuePair("username", "admin"));
params.add(newBasicNameValuePair("password", "123456"));
UrlEncodedFormEntity entity = newUrlEncodedFormEntity(params, "utf-8");
httpPost.setEntity(entity);
然後調用HttpClient的execute()方法,並將HttpPost對象傳入:httpClient.execute(httpPost);
執行execute()方法之後會返回一個HttpResponse對象,服務器所返回的所有信息就會包含在這裏面。通常情況下我們都會先取出服務器返回的狀態碼,如果等於200就說明請求和響應都成功了,如下所示:
if (httpResponse.getStatusLine().getStatusCode()== 200) {
//請求和響應都成功了
}
接下來在這個if判斷的內部取出服務返回的具體內容,可以調用getEntity()方法獲取到一個HttpEntity實例,然後再用EntityUtils.toString()這個靜態方法將HttpEntity轉換成字符串即可,如下所示:
HttpEntity entity =httpResponse.getEntity();
String response = EntityUtils.toString(entity);
如果服務器返回的數據是帶有中文的,直接調用EntityUtils.toString()方法進行轉換會有亂碼的情況出現,這個時候只需要在轉換的時候將字符集指定成utf-8就可以了,如下所示:
String response =EntityUtils.toString(entity, "utf-8");
由於佈局不用改動,直接修改MainActivity中的代碼,如下所示:public class MainActivity extends Activity implements OnClickListener {
……
@Override
public void onClick(View v) {
if (v.getId() == R.id.send_request) {
sendRequestWithHttpClient();
}
}
private void sendRequestWithHttpClient() {
new Thread(new Runnable() {
@Override
public void run() {
try {
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet("http://www.baidu.com");
HttpResponse httpResponse = httpClient.execute(httpGet);
if (httpResponse.getStatusLine().getStatusCode() == 200) {
// 請求和響應都成功了
HttpEntity entity = httpResponse.getEntity();
String response = EntityUtils.toString(entity, "utf-8");
Message message = new Message();
message.what = SHOW_RESPONSE;
// 將服務器返回的結果存放到Message中
message.obj = response.toString();
handler.sendMessage(message);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
……
}
這裏我們只是添加了一個sendRequestWithHttpClient()方法,並在Send Request按鈕的點擊事件裏去調用這個方法。在這個方法中同樣還是先開啓了一個子線程,然後在子線程裏使用HttpClient發出一條HTTP請求,請求的目標地址還是百度的首頁,HttpClient的用法也正如前面所介紹的一樣。然後爲了能讓結果在界面上顯示出來,這裏仍然是將服務器返回的數據存放到了Message對象中,並用Handler將Message發送出去。
僅僅只是改了這麼多代碼,現在我們可以重新運行一下程序了。點擊Send Request按鈕後,你會看到和上一小節中同樣的運行結果,由此證明,使用HttpClient來發送HTTP請求的功能也已經成功實現了。