今天主要學習的就是天氣預報,調用google的weather的API接口可以實現未來四天的天氣預報,本程序主要應用的方法是從SAX 解析XML文檔,嗯對了,還有一個第三方的jar包sax2r2.jar,因為,首先,要開發一款天氣預報應用,一定要有一個web服務端來提供數據,這個數據源我們自己肯定是沒辦法弄的,所以就需要一個第三方機構為我們提供天氣數據.這種機構其實有很多,不過大多數都是收費的,當然這些收費的數據源提供的數據會更加豐富詳細.如果不想花錢去購買這些收費的數據服務,我們還有另一種替代方案-就是使用免費的天氣數據,這篇文章了為大家介紹一個Google 提供的天氣API接著看看實現的過程
1.先看看布局,一個編輯框,一個按鈕,一個表格布局
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:Android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical"
- android:background="@drawable/bg">
-
- <TextView
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:text="其輸入你要查詢天氣的城市:" />
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal">
- <EditText
- android:id="@+id/editcity"
- android:layout_width="100dp"
- android:layout_height="wrap_content"
- />
- <Button
- android:id="@+id/buttonsearch"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="查詢"
- />
-
- </LinearLayout>
-
- <TableLayout
- android:id="@+id/weathertable"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:stretchColumns="1"
-
- >
- <!-- stretchColumns="1" TableLayout所有行的第二列為擴展列。
- 也就是說如果每行都有三列的話,剩余的空間由第二列補齊 -->
- </TableLayout>
-
- </LinearLayout>
2.接著看看SAX解析解析的步驟:
- package com.wang.xml;
-
- import java.util.ArrayList;
- import java.util.List;
-
- import org.xml.sax.Attributes;
- import org.xml.sax.SAXException;
- import org.xml.sax.helpers.DefaultHandler;
-
- public class XmlHandler extends DefaultHandler{
-
- private List<weatherSetGet> weatherlist;
- private boolean Forcast;
- private weatherSetGet weathercurrent;
- //聲明列表函數
- public List<weatherSetGet> getWeatherList(){
-
- return weatherlist;
- }
-
- public void setWeatherlist(List<weatherSetGet> weatherlist){
- this.weatherlist=weatherlist;
-
- }
- //構造函數
- public XmlHandler(){
- weatherlist=new ArrayList<weatherSetGet>();
- Forcast=false;
- }
- // 結束解析XML的文檔中的元素
-
- public void endElement(String uri, String localName, String qName)
- throws SAXException {
- //
- String tagname =localName.length()!=0?localName:qName;
- //轉換這個字符串以較低的情況下,使用規則的用戶的默認語言環境。
- tagname=tagname.toLowerCase();
- // 如果標記的名字是forecast_conditions則結束解析
- if (tagname.equals("forecast_conditions")) {
- //預測為假
- Forcast =false;
- //添加指定的對象在這個列表中
- weatherlist.add(weathercurrent);
- }
- }
- // 開始解析XML的文檔中的元素
-
- public void startElement(String uri, String localName, String qName,
- Attributes attributes) throws SAXException {
-
- String tagname=localName.length()!=0?localName:qName;
- tagname=tagname.toLowerCase();
- // 如果標記的名字是forecast_conditions開始解析
-
- if (tagname.equals("forecast_conditions")) {
- Forcast=true;
-
- weathercurrent=new weatherSetGet();
-
- }
- if (Forcast) {
- if (tagname.equals("day_of_week")) {
- //設置值為得到的解析數據的值
- weathercurrent.setDay(attributes.getValue("data"));
-
- } else if( tagname.equals("low")) {
- weathercurrent.setLow(attributes.getValue("data"));
- } else if( tagname.equals("high")) {
- weathercurrent.setHigh(attributes.getValue("data"));
- } else if( tagname.equals("icon")) {
- weathercurrent.setImage(attributes.getValue("data"));
- } else if( tagname.equals("condition")) {
- weathercurrent.setCondition(attributes.getValue("data"));
- }
- }
-
- }
-
- }
3.SAX解析XML的set與個方法如下:
- package com.wang.xml;
-
- public class weatherSetGet {
- private String day;
- private String low;
- private String high;
- private String image;
- private String condition;
- //創建get和set的對象函數
- public String getDay() {
- return day;
- }
- public void setDay(String day) {
- this.day = day;
- }
- public String getLow() {
- return low;
- }
- public void setLow(String low) {
- this.low = low;
- }
- public String getHigh() {
- return high;
- }
- public void setHigh(String high) {
- this.high = high;
- }
- public String getImage() {
- return image;
- }
- public void setImage(String image) {
- this.image = image;
- }
- public String getCondition() {
- return condition;
- }
- public void setCondition(String condition) {
- this.condition = condition;
- }
-
-
- }
4.看看一看主活動的內容
- package com.wang;
-
-
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.net.URL;
- import java.net.URLEncoder;
- import java.util.List;
- import java.util.Timer;
- import java.util.TimerTask;
-
-
- import javax.xml.parsers.SAXParser;
- import javax.xml.parsers.SAXParserFactory;
-
-
- import org.xml.sax.InputSource;
- import org.xml.sax.XMLReader;
-
-
- import com.wang.xml.XmlHandler;
- import com.wang.xml.weatherSetGet;
-
-
- import android.R.color;
- import android.R.layout;
- import android.app.Activity;
- import android.app.AlertDialog;
- import android.app.Dialog;
- import android.graphics.Color;
- import android.graphics.drawable.Drawable;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.Message;
- import android.util.Log;
- import android.view.Gravity;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.view.ViewGroup.LayoutParams;
- import android.widget.Button;
- import android.widget.EditText;
- import android.widget.ImageView;
- import android.widget.TableLayout;
- import android.widget.TableRow;
- import android.widget.TextView;
-
-
- public class WeatherTestDemoActivity extends Activity {
-
- private EditText edcity;
- private Button searchBtn;
- private Handler weatherHandler;
- private Dialog dialog;
- private Timer time;
-
-
-
-
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- time =new Timer();
- edcity=(EditText)findViewById(R.id.editcity);
- searchBtn=(Button)findViewById(R.id.buttonsearch);
- // 進度對話框,等待資源的下載。。
- dialog=new AlertDialog.Builder(this)
- .setTitle("讀取數據中.....").setMessage("請稍等,正在加載數據...").create();
- //這個處理程序的默認構造函數associates的隊列為當前線程。如果不是這一個,這個處理程序不能接收消息。
- weatherHandler =new Handler(){
-
-
- @Override
- public void handleMessage(Message msg) {
- // 等到從編輯框裡輸入的城市名稱,並賦值個cityname
- final String cityname=edcity.getText().toString();
- // 調用seachcityweather進行天氣查詢
- seachcityweather(cityname);
- //隱藏進度對話框
- dialog.hide();
-
-
-
- }
-
-
-
-
- };
- //為按鈕添加點擊事件
- searchBtn.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- //顯示進度對話框
- dialog.show();
- //對單個的計劃任務執行指定的延時之後。
- time.schedule(new TimerTask() {
-
- @Override
- public void run() {
- /***
- *定義了一個消息,其中包含一個描述和任意的數據對象,
- *可以發送給一個處理程序。
- *這個對象包含兩個額外的int字段和一個額外的對象字段
- *,允許您不分配在許多情況下。 雖然構造函數的信息是公共的,
- *最好的辦法就是其中的一個叫Message.obtain()
- *或Handler.obtainMessage()方法,
- *它將把他們從池中回收的對象。
- * ****/
- //聲明一個消息對象
- Message msg=new Message();
- //設置消息目標為weatherHandler
- msg.setTarget(weatherHandler);
- msg.sendToTarget();
-
- }
- }, 100);
-
- }
- });
-
- }
-
-
-
-
-
-
-
-
- protected void seachcityweather(String cityname) {
- //SAX解析,SAXParserFactory可以使應用程序配置並獲取一個基於SAX的解析器解析來的XML文檔
- SAXParserFactory factory=SAXParserFactory.newInstance();
- try {
- /**SAXParser
- * 這類包裝解析器接口,這個接口是由XMLReader取代。
- * 為便於過渡,這類繼續支持相同的名稱和接口以及支持新方法。
- * 這個類的實例可以獲得newSAXParser()方法。
- * 一旦獲取該類的實例,XML可以解析來自各種輸入源。
- * 這些輸入來源是InputStreams、文件、url和SAX InputSources
- **/
- //實力化SAXParser 得到xml解析的對象getXMLReader
- SAXParser sp=factory.newSAXParser();
- XMLReader reader=sp.getXMLReader();
- //調用XmlHandler 生成一個對象
- XmlHandler handler=new XmlHandler();
- /**讓應用程序可以注冊一個事件處理程序的內容。
- * 如果應用程序不注冊一個內容處理程序,
- * 所有內容事件報道的SAX解析器會悄悄地忽略。
- * 應用程序可以注冊一個新的或不同的處理程序在中間的一個解析,
- * SAX解析器必須立即開始使用新的處理程序。***/
- reader.setContentHandler(handler);
- //得到解析的天氣的資源+你所需要解析的城市
- URL url=new URL("http://www.google.com/ig/api?hl=zh-cn&weather=" + URLEncoder.encode(cityname));
- /****
- * 讀取數據從源輸入流���換成字符通過提供的字符轉換器。
- * 默認的編碼是取自“文件。編碼”的系統屬性。
- * InputStreamReader包含一個緩沖區讀取的字節數從源流並將其轉化成字符需要。
- * 緩沖區的大小是8 K
- */
- //打開輸入流
- InputStream inputStream=url.openStream();
- //轉換成國家標准擴展碼GBK
- InputStreamReader inputStreamReader=new InputStreamReader(inputStream,"GBK");
- /**** InputSource
- * 這個類允許SAX應用程序封裝輸入源的信息在一個單獨的對象,
- * 這可能包括一個公共標識符、系統標識符,字節流(可能有一個指定的編碼),和轉義字符或字符流。
- *
- **/
- //聲明一個對象
- InputSource source=new InputSource(inputStreamReader);
- /******
- * 應用程序可以使用這個方法來指導讀者開始的XML解析一個XML文檔
- * 從任何有效的輸入源(一個字符流,字節流,或一個URI)。
- * 應用程序可能無法調用該方法雖然解析過程中
- * (他們應該創建一個新的XMLReader相反嵌套的每個XML文檔)。
- * 一旦一個解析完成,應用程序可以重用相同的XMLReader對象,
- * 可能使用不同的輸入源
- * XMLReader的配置對象(如處理器綁定和價值觀的確立對功能的標志和屬性)是未受完成解析,
- * 除非那方面的定義顯式地指定配置的其他行為*******/
- reader.parse(source);
- //得到天氣列表
- List<weatherSetGet> weatherlist=handler.getWeatherList();
- //實力化表格布局
- TableLayout tableLayout=(TableLayout)findViewById(R.id.weathertable);
- //刪除viewGroup中的子視圖
- tableLayout.removeAllViews();
-
- for (weatherSetGet weather:weatherlist) {
-
- TableRow row=new TableRow(this);
- //設置布局參數與此相關的視圖。
- //這些供應參數到父的這個視圖指定應該如何安排。
- row.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));
- //垂直居中
- row.setGravity(Gravity.CENTER_VERTICAL);
-
- ImageView imageView=new ImageView(this);
- //下載圖片並繪制
- imageView.setImageDrawable(loadImage(weather.getImage()));
- ///z最小高度
- imageView.setMinimumHeight(50);
- row.addView(imageView);
-
-
- TextView day=new TextView(this);
- // 文本內容和顏色
- day.setText(weather.getDay());
- day.setTextColor(Color.RED);
- day.setGravity(Gravity.CENTER_HORIZONTAL);
- //添加視
- row.addView(day);
-
- TextView tv=new TextView(this);
- tv.setText(weather.getLow()+"℃ - "+weather.getHigh()+"℃ ");
- tv.setTextColor(Color.RED);
- //添加視圖
- row.addView(tv);
-
- TextView condition=new TextView(this);
- //水平居中
- condition.setGravity(Gravity.CENTER_HORIZONTAL);
- //添加視圖
- row.addView(condition);
-
- tableLayout.addView(row);
-
-
-
-
- }
-
- } catch (Exception e) {
- // 解析錯誤時候彈出對話框
- new AlertDialog.Builder(this)
- .setTitle("解析出錯啦!!!")
- .setMessage("獲取天氣數據失!!!請重試!!!")
- .setNegativeButton("確定", null).show();
-
-
- }
- }
-
-
-
-
- //加載天氣圖片資源
-
-
- private Drawable loadImage(String image) {
- try {
- //從輸入流InputStream繪圖並得到返回其內容的資源是指由該URL。
- //默認情況下,返回一個InputStream,或null如果內容類型的響應是未知的
- return Drawable.createFromStream((InputStream)new URL("http://www.google.com/"+image).getContent(), "測試...");
-
- } catch (Exception e) {
- Log.e("exception", e.getMessage());
- }
-
-
- return null;
- }
- }
5.親!最後別忘了添加聯網的權限哦!!
- <!-- 添加聯網的權限 -->
- ;uses-permission android:name="android.permission.INTERNET"/>
6.關於如何導入第三方jar包請看
android 中@override和如何導入第三方jar包(見 http://www.linuxidc.com/Linux/2012-08/67213.htm )這個裡面有關於解決導入第三方jar包的問題,不過裡面是導入的高德地圖的jar包,其實sax2r2.jar的jar包導入過程和高德地圖的方法過程一樣,因為都是第三方jar包
7,運行效果入下:
8.如果想下載源碼請點擊下面的網址:
免費下載地址在 http://linux.linuxidc.com/
用戶名與密碼都是www.linuxidc.com
具體下載目錄在 /2012年資料/8月/3日/Android 版本的天氣預報/