Android應用經常會和服務器端交互,這就需要手機客戶端發送網絡請求。
1.網絡請求方式
最基本的方法有4種,分別是GET,POST,PUT,DELETE。常用的兩種網絡請求方式是POST,GET。下面我們要先知道 POST與GET請求方式的區別
⑴ 根據HTTP規範,GET用於信息獲取,POST表示可能修改變服務器上的資源的請求。是向服務器傳送數據。
⑵ GET請求的數據會附在URL之後(就是把數據放置在HTTP協議頭中),以?分割URL和傳輸數據,參數之間以&相連,值和表單內的各個字段一一對應。如:login.action?name=hyddd&password=idontknow&verify=%E4%BD%A0%E5%A5%BD。如果數據是英文字母/數字,原樣發送,如果是空格,轉換爲+,如果是中文/其他字符,則直接把字符串用BASE64加密,得出如:%E4%BD%A0%E5%A5%BD,其中%XX中的XX爲該符號以16進製表示的ASCII。在URL中是可以看到的。而POST把提交的數據則放置在是HTTP包的包體中。用戶是看不到這個過程的。
⑶ GET方式提交的數據最多隻能是1024字節,理論上POST沒有限制,可傳較大量的數據。IIS4中最大爲80KB,IIS5中爲100KB?
這句話很多地方是這樣寫的,但是有些人認爲這種說法是錯誤的。他們是這樣說的:
①.首先是"GET方式提交的數據最多隻能是1024字節",因爲GET是通過URL提交數據,那麼GET可提交的數據量就跟URL的長度有直接關係了。而實際上,URL不存在參數上限的問題,HTTP協議規範沒有對URL長度進行限制。這個限制是特定的瀏覽器及服務器對它的限制。IE對URL長度的限制是2083字節(2K+35)。對於其他瀏覽器,如Netscape、FireFox等,理論上沒有長度限制,其限制取決於操作系統的支持。(注意這是限制是整個URL長度,而不僅僅是你的參數值數據長度。)
②.理論上講,POST是沒有大小限制的,HTTP協議規範也沒有進行大小限制,說“POST數據量存在80K/100K的大小限制”是不準確的,POST數據是沒有限制的,起限制作用的是服務器的處理程序的處理能力。對於ASP程序,Request對象處理每個表單域時存在100K的數據長度限制。但如果使用Request.BinaryRead則沒有這個限制。由這個延伸出去,對於IIS 6.0,微軟出於安全考慮,加大了限制。I
IS 6.0之前沒有這些限制。我們還需要注意:
1).IIS 6.0默認ASP POST數據量最大爲200KB,每個表單域限制是100KB。
2).IIS 6.0默認上傳文件的最大大小是4MB。
3).IIS 6.0默認最大請求頭是16KB。
所以上面的80K,100K可能只是默認值而已(注:關於IIS4和IIS5的參數,我還沒有確認),但肯定是可以自己設置的。由於每個版本的IIS對這些參數的默認值都不一樣,具體請參考相關的IIS配置文檔。
⑷GET安全性較低低,但是執行效率卻比POST方法好。比如:通過GET提交數據,用戶名和密碼將明文出現在URL上。POST安全性較高。
2.網絡請求接口
⑴ HttpURLConnection接口
HttpURLConnection是繼承於URLConnection類,二者都是抽象類。其對象主要通過URL的openConnection方法獲得。
創建方法如下代碼所示:
URL url = new URL("http://www.51cto.com/index.jsp?par=123456");
HttpURLConnection urlConn=(HttpURLConnection)url.openConnection();
通過以下方法可以對請求的屬性進行一些設置,如下所示
//設置輸入和輸出流
urlConn.setDoOutput(true);
urlConn.setDoInput(true);
//設置請求方式爲POST
urlConn.setRequestMethod("POST");
//POST請求不能使用緩存
urlConn.setUseCaches(false);
//關閉連接
urlConn.disConnection();
HttpURLConnection默認使用GET方式,例如下面代碼所示:
//以Get方式上傳參數
public class Activity03 extends Activity
{
private final String DEBUG_TAG = "Activity03";
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.http);
TextView mTextView = (TextView)this.findViewById(R.id.TextView_HTTP);
//http地址"?par=abcdefg"是我們上傳的參數
String httpUrl = "http://192.168.1.110:8080/httpget.jsp?par=abcdefg";
//獲得的數據
String resultData = "";
URL url = null;
try
{
//構造一個URL對象
url = new URL(httpUrl);
}
catch (MalformedURLException e)
{
Log.e(DEBUG_TAG, "MalformedURLException");
}
if (url != null)
{
try
{
// 使用HttpURLConnection打開連接
HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
//得到讀取的內容(流)
InputStreamReader in = new InputStreamReader(urlConn.getInputStream());
// 爲輸出創建BufferedReader
BufferedReader buffer = new BufferedReader(in);
String inputLine = null;
//使用循環來讀取獲得的數據
while (((inputLine = buffer.readLine()) != null))
{
//我們在每一行後面加上一個"\n"來換行
resultData += inputLine + "\n";
}
//關閉InputStreamReader
in.close();
//關閉http連接
urlConn.disconnect();
//設置顯示取得的內容
if ( resultData != null )
{
mTextView.setText(resultData);
}
else
{
mTextView.setText("讀取的內容爲NULL");
}
}
catch (IOException e)
{
Log.e(DEBUG_TAG, "IOException");
}
}
else
{
Log.e(DEBUG_TAG, "Url NULL");
}
}
如果需要使用POST方式,則需要setRequestMethod設置。代碼如下:
//以post方式上傳參數
public class Activity04 extends Activity
{
private final String DEBUG_TAG = "Activity04";
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.http);
TextView mTextView = (TextView)this.findViewById(R.id.TextView_HTTP);
//http地址"?par=abcdefg"是我們上傳的參數
String httpUrl = "http://192.168.1.110:8080/httpget.jsp";
//獲得的數據
String resultData = "";
URL url = null;
try
{
//構造一個URL對象
url = new URL(httpUrl);
}
catch (MalformedURLException e)
{
Log.e(DEBUG_TAG, "MalformedURLException");
}
if (url != null)
{
try
{
// 使用HttpURLConnection打開連接
HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
//因爲這個是post請求,設立需要設置爲true
urlConn.setDoOutput(true);
urlConn.setDoInput(true);
// 設置以POST方式
urlConn.setRequestMethod("POST");
// Post 請求不能使用緩存
urlConn.setUseCaches(false);
urlConn.setInstanceFollowRedirects(true);
// 配置本次連接的Content-type,配置爲application/x-www-form-urlencoded的
urlConn.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
// 連接,從postUrl.openConnection()至此的配置必須要在connect之前完成,
// 要注意的是connection.getOutputStream會隱含的進行connect。
urlConn.connect();
//DataOutputStream流
DataOutputStream out = new DataOutputStream(urlConn.getOutputStream());
//要上傳的參數
String content = "par=" + URLEncoder.encode("ABCDEFG", "gb2312");
//將要上傳的內容寫入流中
out.writeBytes(content);
//刷新、關閉
out.flush();
out.close();
//獲取數據
BufferedReader reader = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));
String inputLine = null;
//使用循環來讀取獲得的數據
while (((inputLine = reader.readLine()) != null))
{
//我們在每一行後面加上一個"\n"來換行
resultData += inputLine + "\n";
}
reader.close();
//關閉http連接
urlConn.disconnect();
//設置顯示取得的內容
if ( resultData != null )
{
mTextView.setText(resultData);
}
else
{
mTextView.setText("讀取的內容爲NULL");
}
}
catch (IOException e)
{
Log.e(DEBUG_TAG, "IOException");
}
}
else
{
Log.e(DEBUG_TAG, "Url NULL");
}
}
}
⑵
HttpClient
Apache HttpClient 是一個開源項目,彌補了 java.net.* 靈活性不足的缺點,爲客戶端的HTTP編程提供高效、最新、功能豐富的工具包支持。
Android 平臺引入了 Apache HttpClient 的同時還提供了對它的一些封裝和擴展,例如設置缺省的HTTP超時和緩存大小等。
使用這部分接口的基本操作與 java.net.* 基本類似,主要包括: 創建 HttpClient 以及 GetMethod / PostMethod, HttpRequest 等對象,設置連接參數,執行HTTP操作,處理服務器返回結果。
//創建HttpClient
//這裏使用DefaultHttpClient表示默認屬性
HttpClient httpclient = new DefaultHttpClient();
Get方法的操作代碼示例如下所示:public class Activity02 extends Activity
{
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.http);
TextView mTextView = (TextView) this.findViewById(R.id.TextView_HTTP);
// http地址
String httpUrl = "http://192.168.1.110:8080/httpget.jsp?par=HttpClient_android_Get";
//HttpGet連接對象
HttpGet httpRequest = new HttpGet(httpUrl);
try
{
//取得HttpClient對象
HttpClient httpclient = new DefaultHttpClient();
//請求HttpClient,取得HttpResponse
HttpResponse httpResponse = httpclient.execute(httpRequest);
//請求成功
if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK)
{
//取得返回的字符串
String strResult = EntityUtils.toString(httpResponse.getEntity());
mTextView.setText(strResult);
}
else
{
mTextView.setText("請求錯誤!");
}
}
catch (ClientProtocolException e)
{
mTextView.setText(e.getMessage().toString());
}
catch (IOException e)
{
mTextView.setText(e.getMessage().toString());
}
catch (Exception e)
{
mTextView.setText(e.getMessage().toString());
}
}
}
使用POST方法進行參數傳遞時,需要使用NameValuePair來保存要傳遞的參數,另外,還需要設置所使用的字符集。代碼如下所示:
public class Activity03 extends Activity
{
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.http);
TextView mTextView = (TextView) this.findViewById(R.id.TextView_HTTP);
// http地址
String httpUrl = "http://192.168.1.110:8080/httpget.jsp";
//HttpPost連接對象
HttpPost httpRequest = new HttpPost(httpUrl);
//使用NameValuePair來保存要傳遞的Post參數
List<NameValuePair> params = new ArrayList<NameValuePair>();
//添加要傳遞的參數
params.add(new BasicNameValuePair("par", "HttpClient_android_Post"));
try
{
//設置字符集
HttpEntity httpentity = new UrlEncodedFormEntity(params, "gb2312");
//請求httpRequest
httpRequest.setEntity(httpentity);
//取得默認的HttpClient
HttpClient httpclient = new DefaultHttpClient();
//取得HttpResponse
HttpResponse httpResponse = httpclient.execute(httpRequest);
//HttpStatus.SC_OK表示連接成功
if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK)
{
//取得返回的字符串
String strResult = EntityUtils.toString(httpResponse.getEntity());
mTextView.setText(strResult);
}
else
{
mTextView.setText("請求錯誤!");
}
}
catch (ClientProtocolException e)
{
mTextView.setText(e.getMessage().toString());
}
catch (IOException e)
{
mTextView.setText(e.getMessage().toString());
}
catch (Exception e)
{
mTextView.setText(e.getMessage().toString());
}
}
}
HttpClient實際上是對Java提供方法的一些封裝,在HttpURLConnection中的輸入輸出流操作,在這個接口中被統一封裝成了HttpPost(HttpGet)和HttpResponse,這樣,就減少了操作的繁瑣性。
另外,在使用POST方式進行傳輸時,需要進行字符編碼。