Android基礎之十七使用網路技術

來源:互聯網
上載者:User

標籤:

Android基礎之十七使用網路技術

本章主要會講述如何在手機端使用HTTP協議和伺服器端進行網路互動,並對伺服器返回的資料進行解析,這也是Android中最常使用到的網路技術了,下面就讓我們一起來學習一下吧。

1 WebView的用法

藉助它我們就可以在自己的應用程式裡嵌入一個瀏覽器,從而非常輕鬆地展示各種各樣的網頁

WebView的用法也是相當簡單,下面我們就通過一個例子來學習一下吧。建立一個WebViewTest項目,然後修改activity_main.xml中的代碼,如下所示

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent" >    <WebView        android:id="@+id/web_view"        android:layout_width="match_parent"        android:layout_height="match_parent" /></LinearLayout>

可以看到,我們在布局檔案中使用到了一個新的控制項,WebView。這個控制項當然也就是用來顯示網頁的了,這裡的寫法很簡單,給它設定了一個id,並讓它充滿整個螢幕。

然後修改MainActivity中的代碼,如下所示:

package com.example.webview;import android.os.Bundle;import android.app.Activity;import android.view.Menu;import android.webkit.WebView;import android.webkit.WebViewClient;public class MainActivity extends Activity {private WebView webview;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);webview=(WebView) findViewById(R.id.web_view);webview.getSettings().setJavaScriptEnabled(true);webview.setWebViewClient(new WebViewClient() {@Overridepublic boolean shouldOverrideUrlLoading(WebView view, String url) {    view.loadUrl(url); // 根據傳入的參數再去載入新的網頁return true; // 表示當前WebView可以處理開啟新網頁的請求,不用藉助系統瀏覽器}});webview.loadUrl("http://www.baidu.com");}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);return true;}}

MainActivity中的代碼也很短,首先使用findViewById()方法擷取到了WebView的執行個體,然後調用WebView的getSettings()方法可以去設定一些瀏覽器的屬性,這裡我們並不去設定過多的屬性,只是調用了setJavaScriptEnabled()方法來讓WebView支援JavaScript指令碼。

接下來是非常重要的一個部分,我們調用了WebView的setWebViewClient()方法,並傳入了WebViewClient的匿名類作為參數,然後重寫了shouldOverrideUrlLoading()方法。這就表明當需要從一個網頁跳轉到另一個網頁時,我們希望目標網頁仍然在當前WebView中顯示,而不是開啟系統瀏覽器。


最後一步就非常簡單了,調用WebView的loadUrl()方法,並將網址傳入


另外還需要注意,由於本程式使用到了網路功能,而訪問網路是需要聲明許可權的,因此我們還得修改AndroidManifest.xml檔案,並加入許可權聲明,如下所示:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.example.webviewtest"    android:versionCode="1"    android:versionName="1.0" >    ……    <uses-permission android:name="android.permission.INTERNET" />    ……</manifest>

2 使用HTTP協議訪問網路

它的工作原理特別的簡單,就是用戶端向伺服器發出一條HTTP請求,伺服器收到請求之後會返回一些資料給用戶端,然後用戶端再對這些資料進行解析和處理就可以了。

2.1 使用HttpURLConnection

在Android上發送HTTP請求的方式一般有兩種,HttpURLConnectionHttpClient,本小節我們先來學習一下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();

下面就讓我們通過一個具體的例子來真正體驗一下HttpURLConnection的用法。建立一個NetworkTest項目,首先修改activity_main.xml中的代碼,如下所示:


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <Button        android:id="@+id/send_request"        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/response"            android:layout_width="match_parent"            android:layout_height="wrap_content" />    </ScrollView></LinearLayout>

注意這裡我們使用了一個新的控制項,ScrollView,它是用來做什麼的呢?由於手機螢幕的空間一般都比較小,有些時候過多的內容一屏是顯示不下的,藉助ScrollView控制項的話就可以允許我們以滾動的形式查看螢幕外的那部分內容。另外,布局中還放置了一個Button和一個TextView,Button用於發送HTTP請求,TextView用於將伺服器返回的資料顯示出來。

接著修改MainActivity中的代碼,如下所示:

public class MainActivity extends Activity implements OnClickListener {public static final int SHOW_RESPONSE = 0;private Button sendRequest;private TextView responseText;private Handler handler = new Handler() {public void handleMessage(Message msg) {switch (msg.what) {case SHOW_RESPONSE:String response = (String) msg.obj;// 在這裡進行UI操作,將結果顯示到介面上responseText.setText(response);}}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);sendRequest = (Button) findViewById(R.id.send_request);responseText = (TextView) findViewById(R.id.response_text);sendRequest.setOnClickListener(this);}@Overridepublic void onClick(View v) {if (v.getId() == R.id.send_request) {sendRequestWithHttpURLConnection();}}private void sendRequestWithHttpURLConnection() {// 開啟線程來發起網路請求new Thread(new Runnable() {@Overridepublic void run() {HttpURLConnection connection = null;try {URL url = new URL("http://www.baidu.com");connection = (HttpURLConnection) url.openConnection();connection.setRequestMethod("GET");connection.setConnectTimeout(8000);connection.setReadTimeout(8000);InputStream in = connection.getInputStream();// 下面對擷取到的輸入資料流進行讀取BufferedReader reader = new BufferedReader(new InputStreamReader(in));StringBuilder response = new StringBuilder();String line;while ((line = reader.readLine()) != null) {response.append(line);}Message message = new Message();message.what = SHOW_RESPONSE;// 將伺服器返回的結果存放到Message中message.obj = response.toString();handler.sendMessage(message);} catch (Exception e) {e.printStackTrace();} finally {if (connection != null) {connection.disconnect();}}}}).start();}}

以看到,我們在Send Request按鈕的點擊事件裡調用了sendRequestWithHttpURL- Connection()方法,在這個方法中先是開啟了一個子線程,然後在子線程裡使用HttpURLConnection發出一條HTTP請求,請求的目標地址就是百度的首頁。接著利用BufferedReader對伺服器返回的流進行讀取,並將結果存放到了一個Message對象中。這裡為什麼要使用Message對象呢?當然是因為子線程中無法對UI進行操作了。我們希望可以將伺服器返回的內容顯示到介面上,所以就建立了一個Message對象,並使用Handler將它發送出去。之後又在Handler的handleMessage()方法中對這條Message進行處理,最終取出結果並設定到TextView上。

過在開始運行之前,仍然別忘了要聲明一下網路許可權。修改AndroidManifest.xml中的代碼


<manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.example.networktest"    android:versionCode="1"    android:versionName="1.0" >    ……    <uses-permission android:name="android.permission.INTERNET" />    ……</manifest>

好了,現在運行一下程式,並點擊Send Request按鈕,結果2所示。


這是返回的 htmL格式,另外如果也可以以json資料的格式返回。

那麼如果是想要提交資料給伺服器應該怎麼辦呢?其實也不複雜,只需要將HTTP請求的方法改成POST,並在擷取輸入資料流之前把要提交的資料寫出即可。注意每條資料都要以鍵值對的形式存在,資料與資料之間用&符號隔開,比如說我們想要向伺服器提交使用者名稱和密碼,就可以這樣寫:

connection.setRequestMethod("POST");

DataOutputStream out = new DataOutputStream(connection.getOutputStream());

out.writeBytes("username=admin&password=123456");

2.2 使用HttpClient

HttpClient是Apache提供的HTTP網路提供者,從一開始的時候就被引入到了Android API中。它可以完成和HttpURLConnection幾乎一模一樣的效果,但兩者之間的用法卻有較大的差別,那麼我們自然要看一下HttpClient是如何使用的了。

首先你需要知道,HttpClient是一個介面,因此無法建立它的執行個體,通常情況下都會建立一個DefaultHttpClient的執行個體,如下所示:

HttpClient httpClient = new DefaultHttpClient();

接下來如果想要發起一條GET請求,就可以建立一個HttpGet對象,並傳入目標的網路地址,然後調用HttpClient的execute()方法即可:

HttpGet httpGet = new HttpGet("http://www.baidu.com");

httpClient.execute(httpGet);

 並傳入目標的網路地址,如下所示:

HttpPost httpPost = new HttpPost("http://www.baidu.com");

然後通過一個NameValuePair集合來存放待提交的參數,並將這個參數集合傳入到一個UrlEncodedFormEntity中,然後調用HttpPost的setEntity()方法將構建好的UrlEncodedFormEntity傳入,如下所示:

List<NameValuePair> params = new ArrayList<NameValuePair>();

params.add(new BasicNameValuePair("username", "admin"));

params.add(new BasicNameValuePair("password", "123456"));

UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, "utf-8");

httpPost.setEntity(entity);

接下來的操作就和HttpGet一樣了,調用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");

好了,基本的用法就是如此,接下來就讓我們把NetworkTest這個項目改用HttpClient的方式再實現一遍吧。

由於布局部分完全不用改動,所以現在直接修改MainActivity中的代碼,如下所示

public class MainActivity extends Activity implements OnClickListener {……@Overridepublic void onClick(View v) {if (v.getId() == R.id.send_request) {sendRequestWithHttpClient();}}private void sendRequestWithHttpClient() {new Thread(new Runnable() {@Overridepublic 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();}……}






Android基礎之十七使用網路技術

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.