Android學習筆記(四五):互連網通訊-HttpClient、XML解析(W3C)

來源:互聯網
上載者:User

前幾日Android發布了4.0 Icecream,昨天上網發現Begining Book中有Edition 3的版本,比對一下,還是有相當的改動,不僅僅增加了tablet的部分,對原有的章節有有一些修訂,前後的調整等等。先按Edtion 2的順序看,相同章節的看Edtion 3,然後回頭看Edition 3的Chapter
24、25(E2的36)、26、27、28、29、44、45、46、47幾個新增章節。同時將模擬器改為Android 2.3的版本,已適應可能新增的改動。

訪問Internet是裝置的一個重要使用者,之前學習過如何嵌入Webkit,此外我們可以通過API來訪問Intenet。Android提供Apache HttpClient庫,基於此,其他協議,可以視為在HTTP封裝的格式,例如XML,JSON等。HTTP Client的詳細資料可在http://hc.apache.org/中擷取。

Android提供三個XML的解析器: 1、傳統的W3C DOM parser(org.w3c.dom); 2、SAX解析器(org.xml.sax); 3、之前Android學習筆記(三八):資源resource(上)中使用XmlPullParser。 另外提供JSON解析器(org.json)。當然也可以使用第三方的解析器。
實現的步驟如下:

  1. 建立HttpClient介面的對象,可以通過DefaultHttpClient來建立。
  2. 請求和HttpRequest相幫定,包括HttpGet,HttpPost,然手執行通過execute()來執行請求。
  3. 可以使用HttpResponsed對象處理返回,帶有response code(例如200,即200 OK),Http頭等,另外可以在execute()中攜帶ResponseHandler作為參數,將在此返回response body,然則此法可行但不推薦,因為通常來講我們應該response code。

下面是一個天氣widget的小例子,採用HttpClient,是以哦那個HttpGet發出對某個URL(google的天氣查詢網路頁面)請求,返回xml格式的天氣資訊,從中分析,並將結果通過WebKit Browser的方式程式,下面是尋找廣州天氣的返回。在例子中,第一學習HttpClient的用法,第二也學習XML的解析,此次採用W3C DOM解析器,通過NodeList和Element來進行分析。


<xml_api_reply version="1"> 
<weather module_id="0" tab_id="0" mobile_row="0" mobile_zipped="1" row="0" section="0"> 
<forecast_information>  <!-- 查詢地點資訊,只給出準備分析的部分 -->
    … … 
    <postal_code data="廣州"/> 
    <forecast_date data="2011-10-27"/> 
</forecast_information>
<current_conditions>  <!-- 給出當前的天氣情況,只顯示準備分析的部分 -->
    <condition data="局部多雲"/> 
    <temp_c data="27"/>
    <humidity data="濕度: 48%"/>
    <icon data="/ig/images/weather/partly_cloudy.gif"/>
    <wind_condition data="風向: 北、風速:2 米/秒"/>
</current_conditions>  
<forecast_conditions>  <!-- 給出當天天氣預報 -->
    <day_of_week data="周四"/>
    <low data="21"/>
    <high data="28"/>
    <icon data="/ig/images/weather/mostly_sunny.gif"/>
    <condition data="以晴為主"/>
</forecast_conditions>
<forecast_conditions> <!-- 給出明天天氣預報 -->
      ... ...
</forecast_conditions>
<forecast_conditions> <!-- 給出後天天氣預報 -->
      … …
</forecast_conditions>
<forecast_conditions> <!-- 給出第三天天氣預報 -->
      … …
</forecast_conditions>
</weather>
</xml_api_reply>

程式碼如下:

(這個介面屬於iGoogle的私人介面,已經被關閉,可以找其他的weather api,例如http://www.wunderground.com/weather/api/。 Wei , 2012.9 )

public class Chapter25Test1 extends Activity{
    private WebView browser = null;  //採用WebView來排版顯示的內容
    private HttpClient client = null;
    private List<Forecast> forecasts = new ArrayList<Forecast>(); 
//採用List來儲存未來幾天的天氣情況
    private CurrentWeather currentCondition = null; 
//儲存即時天氣情況和地點時間
    private String format = "http://www.google.com/ig/api?hl=zh-cn&weather=%1s"; //Google XML天氣資訊的查詢API介面
    
    protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.chapter_25_test1);
        browser = (WebView) findViewById(R.id.c131_webkit);
        //步驟1、建立HttpClient介面的對象,可以通過DefaultHttpClient來建立。
        client = new DefaultHttpClient();
    } 

     protected void onResume() { 
        super.onResume();
        updateForecast("廣州");  //步驟2、向Internet請求廣州的天氣資訊,擷取資訊,並呈現
    } 

    protected void onDestroy() { 
        super.onDestroy();
        //步驟3、釋放HttpClient的資源,此步沒詳細跟蹤,按字面估計如一直串連無回複,則在Activity Destroy的時候,終止串連
        client.getConnectionManager().shutdown();
    } 

    //步驟2、向Internet請求廣州的天氣資訊,擷取資訊,並呈現
    private void updateForecast(String citycode ){
        String url = String.format(format, citycode);
        //步驟2.1、產生HttpGet請求,並通過execute( )向Internet發出,在responseHandler中得到傳回值。
        HttpGet getMethod = new HttpGet(url);
        try{
            ResponseHandler<String> responseHandle = new BasicResponseHandler();
            String responseBody = client.execute(getMethod,responseHandle);
            buildForecasts(responseBody);  //步驟2.2 從返回中擷取天氣資訊
            String page = generatePage();   //步驟2.3 通過HTML在webkit browser中呈現
            browser.loadDataWithBaseURL(null, page, "text/html", "UTF-8", null);
        }catch(Throwable t){ 
            Toast.makeText(this,"Request failed : "+ t.toString(), 5000).show();
        }
    }
    //步驟2.2 從返回中擷取天氣資訊,注意這種帶throws Exception的寫法
    private void buildForecasts(String raw) throws Exception{    
        DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        Document doc = builder.parse(new InputSource(new StringReader(raw)));
        //擷取即時天氣資訊和地點、時間資訊,方式和後面擷取未來天氣預報一樣,較為繁瑣,略過,資訊存放在currentCondition中
         …. …. 

        //對於XML<node_name  node_attribute=attribute_valule> node_vaule </node_name> 
        NodeList furCondition = doc.getElementsByTagName("forecast_conditions");
        //有未來四日天氣預報,分別取出
        for(int i = 0 ; i < furCondition.getLength(); i ++){
            Element e = (Element)furCondition.item(i);
            addWeather(e);
        }
    }
    private void addWeather( Element e){
        Forecast fc = new Forecast(getWeatherAttribute(e,"day_of_week"),
                                                  getWeatherAttribute(e,"low"),
                                                  getWeatherAttribute(e,"high"),
                                                  getWeatherAttribute(e,"icon"),
                                                  getWeatherAttribute(e,"condition"));
        forecasts.add(fc);
    } 
    
    //下面是從每組Element中讀取所需資訊,另外補充的是如果愛用Node,例如e.getFirstClide()擷取,也可以 node.getAttributes().getNamedItem("data").getNodeValue() 來獲得攜帶的屬性值
    private String getWeatherAttribute(Element e, String name){
        NodeList t = e.getElementsByTagName(name);
        Element a = (Element)t.item(0);
        return a.getAttribute("data");
    } 

     //步驟2.3 通過HTML在webkit browser中呈現
    private String generatePage(){
        StringBuilder bufResult  = new StringBuilder("<html><body><table width=\"100%\">");
        bufResult.append("<h2><font color=\"red\">" + currentCondition.getCity() + "</font></h2>\n"); 
        … … //顯示即時資訊
        bufResult.append ("<table><tr><th width=\"25%\">Time</th>"+
        "<th width=\"25%\">溫度</th><th colspan=\"2\" width=\"50%\">天氣情況</th></tr>");
        for(Forecast forecast : forecasts){
            bufResult.append("<tr><td align=\"center\">");
            bufResult.append(forecast.getDate());
            bufResult.append("</td><td align=\"center\">");
            bufResult.append(forecast.getTemperature());
            bufResult.append("</td><td align=\"right\">");
            bufResult.append(forecast.getCondition());
            bufResult.append("</td><td align=\"left\"><img src=\"http://www.google.com/");
            bufResult.append(forecast.getIcon());
            bufResult.append("\"></td></tr>"); 
        }
        bufResult.append("</table></body></html>");
        return bufResult.toString();
    }
    private class Forecast{ 
         …. /* 存放天氣預報資訊,並提供get擷取方法*/ …..
    }
    private class CurrentWeather{ 
       …. /* 存放當前天氣、時間、地點,並提供get擷取方法*/ ….
    }
}

通過經緯度擷取地點

在Google的天氣預報api中,也是可以輸入經緯度,格式為:http://www.google.com/ig/api?hl=zh-cn&weather=,,,23080000,113170000,這是廣州的經緯度。Android可以通過GPS擷取經緯度,然後所謂輸入參數,可以得到當前所在地的天氣。在模擬器中,可以通過預先配置經緯度來進行個類比。先開啟模擬器,然後在Eclipse的菜單Window -> Open Perspective
-> DDMS,進入配置,可在Control Panel中設定所需的經緯度。如右圖所示。

定位服務以後再學習。

需要注意

如果是要使用SSL協議,HttpClient並不支援。主要是因為需要決定如何處理SSL認證,是否接受所有認證,包括私人或者已經到期的正確,或者是否需要提示使用者。

簡單的HttpClient在預設下作為單線程使用。如果需要多線程,可以設定HttpClient支援多線程。

AndroidHttpClient

從Android2.2(API level 8)開始,可以使用AndroidHttpClient類,在android.net.http中,是HttpClient介面的一個實現,就如例子中的DefaultHttpClient。通過這個類,可以進行SSL管理;可通過靜態方法newInstance來直接填寫userAgent(report in your HTTP requests)並擷取AndroidHttpClient的執行個體,可以在HTTP頭能增加date資訊,支援gzip壓縮的內容。

和傳統的DefaultHttpClient不同,AndroidHttpClient不會自動儲存cookies,可通過HttpContext對象來處理。

此外,AndroidHttpClient不允許主線程使用,只能在後台線程運行。這點需要特別注意。

相關連結:我的Andriod開發相關文章

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.