歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Android 版本的天氣預報

今天主要學習的就是天氣預報,調用google的weather的API接口可以實現未來四天的天氣預報,本程序主要應用的方法是從SAX 解析XML文檔,嗯對了,還有一個第三方的jar包sax2r2.jar,因為,首先,要開發一款天氣預報應用,一定要有一個web服務端來提供數據,這個數據源我們自己肯定是沒辦法弄的,所以就需要一個第三方機構為我們提供天氣數據.這種機構其實有很多,不過大多數都是收費的,當然這些收費的數據源提供的數據會更加豐富詳細.如果不想花錢去購買這些收費的數據服務,我們還有另一種替代方案-就是使用免費的天氣數據,這篇文章了為大家介紹一個Google 提供的天氣API接著看看實現的過程

1.先看看布局,一個編輯框,一個按鈕,一個表格布局

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:Android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:orientation="vertical"   
  6.     android:background="@drawable/bg">  
  7.   
  8.     <TextView  
  9.         android:layout_width="fill_parent"  
  10.         android:layout_height="wrap_content"  
  11.         android:text="其輸入你要查詢天氣的城市:" />  
  12.     <LinearLayout   
  13.     android:layout_width="fill_parent"  
  14.     android:layout_height="wrap_content"  
  15.     android:orientation="horizontal">  
  16.     <EditText  
  17.         android:id="@+id/editcity"  
  18.         android:layout_width="100dp"  
  19.         android:layout_height="wrap_content"  
  20.          />  
  21.     <Button    
  22.         android:id="@+id/buttonsearch"  
  23.         android:layout_width="wrap_content"  
  24.         android:layout_height="wrap_content"  
  25.         android:text="查詢"  
  26.         />  
  27.           
  28. </LinearLayout>  
  29.   
  30. <TableLayout   
  31.     android:id="@+id/weathertable"  
  32.     android:layout_width="fill_parent"  
  33.     android:layout_height="fill_parent"  
  34.     android:stretchColumns="1"  
  35.       
  36.     >  
  37.     <!-- stretchColumns="1" TableLayout所有行的第二列為擴展列。   
  38. 也就是說如果每行都有三列的話,剩余的空間由第二列補齊  -->  
  39. </TableLayout>  
  40.   
  41. </LinearLayout>  
2.接著看看SAX解析解析的步驟:
  1. package com.wang.xml;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. import org.xml.sax.Attributes;  
  7. import org.xml.sax.SAXException;  
  8. import org.xml.sax.helpers.DefaultHandler;  
  9.   
  10. public class XmlHandler extends DefaultHandler{  
  11.   
  12.     private List<weatherSetGet> weatherlist;  
  13.     private boolean Forcast;  
  14.     private weatherSetGet weathercurrent;  
  15.     //聲明列表函數   
  16.     public List<weatherSetGet> getWeatherList(){  
  17.           
  18.         return weatherlist;  
  19.     }  
  20.       
  21.     public void setWeatherlist(List<weatherSetGet> weatherlist){  
  22.         this.weatherlist=weatherlist;  
  23.           
  24.     }  
  25.     //構造函數   
  26.     public XmlHandler(){  
  27.         weatherlist=new ArrayList<weatherSetGet>();  
  28.         Forcast=false;  
  29.     }  
  30.     // 結束解析XML的文檔中的元素   
  31.   
  32.     public void endElement(String uri, String localName, String qName)  
  33.             throws SAXException {  
  34.         //    
  35.         String tagname =localName.length()!=0?localName:qName;  
  36.         //轉換這個字符串以較低的情況下,使用規則的用戶的默認語言環境。   
  37.         tagname=tagname.toLowerCase();  
  38.         // 如果標記的名字是forecast_conditions則結束解析   
  39.         if (tagname.equals("forecast_conditions")) {  
  40.             //預測為假   
  41.             Forcast =false;  
  42.             //添加指定的對象在這個列表中   
  43.             weatherlist.add(weathercurrent);  
  44.         }  
  45.     }  
  46.     // 開始解析XML的文檔中的元素   
  47.   
  48.     public void startElement(String uri, String localName, String qName,  
  49.             Attributes attributes) throws SAXException {  
  50.   
  51.         String tagname=localName.length()!=0?localName:qName;  
  52.         tagname=tagname.toLowerCase();  
  53.         // 如果標記的名字是forecast_conditions開始解析   
  54.   
  55.         if (tagname.equals("forecast_conditions")) {  
  56.            Forcast=true;  
  57.              
  58.            weathercurrent=new weatherSetGet();  
  59.               
  60.         }  
  61.         if (Forcast) {  
  62.             if (tagname.equals("day_of_week")) {  
  63.                 //設置值為得到的解析數據的值   
  64.                 weathercurrent.setDay(attributes.getValue("data"));  
  65.                   
  66.             } else  if( tagname.equals("low")) {  
  67.                 weathercurrent.setLow(attributes.getValue("data"));  
  68.             } else  if( tagname.equals("high")) {  
  69.                 weathercurrent.setHigh(attributes.getValue("data"));  
  70.             } else  if( tagname.equals("icon")) {  
  71.                 weathercurrent.setImage(attributes.getValue("data"));  
  72.             } else  if( tagname.equals("condition")) {  
  73.                 weathercurrent.setCondition(attributes.getValue("data"));  
  74.             }  
  75.         }  
  76.           
  77.     }  
  78.       
  79. }  
3.SAX解析XML的set與個方法如下:
  1. package com.wang.xml;  
  2.   
  3. public class weatherSetGet {  
  4.     private String day;  
  5.     private String low;  
  6.     private String high;  
  7.     private String image;  
  8.     private String condition;  
  9.     //創建get和set的對象函數   
  10.     public String getDay() {  
  11.         return day;  
  12.     }  
  13.     public void setDay(String day) {  
  14.         this.day = day;  
  15.     }  
  16.     public String getLow() {  
  17.         return low;  
  18.     }  
  19.     public void setLow(String low) {  
  20.         this.low = low;  
  21.     }  
  22.     public String getHigh() {  
  23.         return high;  
  24.     }  
  25.     public void setHigh(String high) {  
  26.         this.high = high;  
  27.     }  
  28.     public String getImage() {  
  29.         return image;  
  30.     }  
  31.     public void setImage(String image) {  
  32.         this.image = image;  
  33.     }  
  34.     public String getCondition() {  
  35.         return condition;  
  36.     }  
  37.     public void setCondition(String condition) {  
  38.         this.condition = condition;  
  39.     }  
  40.       
  41.   
  42. }  
4.看看一看主活動的內容
  1. package com.wang;  
  2.   
  3.   
  4. import java.io.InputStream;  
  5. import java.io.InputStreamReader;  
  6. import java.net.URL;  
  7. import java.net.URLEncoder;  
  8. import java.util.List;  
  9. import java.util.Timer;  
  10. import java.util.TimerTask;  
  11.   
  12.   
  13. import javax.xml.parsers.SAXParser;  
  14. import javax.xml.parsers.SAXParserFactory;  
  15.   
  16.   
  17. import org.xml.sax.InputSource;  
  18. import org.xml.sax.XMLReader;  
  19.   
  20.   
  21. import com.wang.xml.XmlHandler;  
  22. import com.wang.xml.weatherSetGet;  
  23.   
  24.   
  25. import android.R.color;  
  26. import android.R.layout;  
  27. import android.app.Activity;  
  28. import android.app.AlertDialog;  
  29. import android.app.Dialog;  
  30. import android.graphics.Color;  
  31. import android.graphics.drawable.Drawable;  
  32. import android.os.Bundle;  
  33. import android.os.Handler;  
  34. import android.os.Message;  
  35. import android.util.Log;  
  36. import android.view.Gravity;  
  37. import android.view.View;  
  38. import android.view.View.OnClickListener;  
  39. import android.view.ViewGroup.LayoutParams;  
  40. import android.widget.Button;  
  41. import android.widget.EditText;  
  42. import android.widget.ImageView;  
  43. import android.widget.TableLayout;  
  44. import android.widget.TableRow;  
  45. import android.widget.TextView;  
  46.   
  47.   
  48. public class WeatherTestDemoActivity extends Activity {  
  49.      
  50.     private EditText edcity;  
  51.     private Button searchBtn;  
  52.     private Handler weatherHandler;  
  53.     private Dialog dialog;  
  54.     private Timer time;  
  55.       
  56.       
  57.       
  58.       
  59.     public void onCreate(Bundle savedInstanceState) {  
  60.         super.onCreate(savedInstanceState);  
  61.         setContentView(R.layout.main);  
  62.         time =new Timer();  
  63.         edcity=(EditText)findViewById(R.id.editcity);  
  64.         searchBtn=(Button)findViewById(R.id.buttonsearch);  
  65.         // 進度對話框,等待資源的下載。。   
  66.         dialog=new AlertDialog.Builder(this)  
  67.         .setTitle("讀取數據中.....").setMessage("請稍等,正在加載數據...").create();  
  68.         //這個處理程序的默認構造函數associates的隊列為當前線程。如果不是這一個,這個處理程序不能接收消息。   
  69.         weatherHandler =new Handler(){  
  70.   
  71.   
  72.             @Override  
  73.             public void handleMessage(Message msg) {  
  74.           // 等到從編輯框裡輸入的城市名稱,並賦值個cityname   
  75.                 final String cityname=edcity.getText().toString();  
  76.            // 調用seachcityweather進行天氣查詢         
  77.                 seachcityweather(cityname);  
  78.                 //隱藏進度對話框   
  79.                dialog.hide();  
  80.                  
  81.               
  82.               
  83.             }  
  84.               
  85.               
  86.               
  87.               
  88.         };  
  89.        //為按鈕添加點擊事件   
  90.        searchBtn.setOnClickListener(new OnClickListener() {  
  91.           
  92.         @Override  
  93.         public void onClick(View v) {  
  94.             //顯示進度對話框   
  95.             dialog.show();  
  96.             //對單個的計劃任務執行指定的延時之後。   
  97.             time.schedule(new TimerTask() {  
  98.                   
  99.                 @Override  
  100.                 public void run() {  
  101.                     /*** 
  102.                      *定義了一個消息,其中包含一個描述和任意的數據對象, 
  103.                      *可以發送給一個處理程序。 
  104.                      *這個對象包含兩個額外的int字段和一個額外的對象字段 
  105.                      *,允許您不分配在許多情況下。  雖然構造函數的信息是公共的, 
  106.                      *最好的辦法就是其中的一個叫Message.obtain() 
  107.                      *或Handler.obtainMessage()方法, 
  108.                      *它將把他們從池中回收的對象。 
  109.                      * ****/  
  110.                     //聲明一個消息對象   
  111.                     Message msg=new Message();  
  112.                     //設置消息目標為weatherHandler   
  113.                     msg.setTarget(weatherHandler);  
  114.                     msg.sendToTarget();  
  115.                       
  116.                 }  
  117.             }, 100);  
  118.               
  119.         }  
  120.     });  
  121.           
  122.     }  
  123.   
  124.   
  125.   
  126.   
  127.   
  128.   
  129.   
  130.   
  131.     protected void seachcityweather(String cityname) {  
  132.     //SAX解析,SAXParserFactory可以使應用程序配置並獲取一個基於SAX的解析器解析來的XML文檔   
  133.         SAXParserFactory factory=SAXParserFactory.newInstance();  
  134.         try {  
  135.             /**SAXParser 
  136.              * 這類包裝解析器接口,這個接口是由XMLReader取代。 
  137.              * 為便於過渡,這類繼續支持相同的名稱和接口以及支持新方法。 
  138.              * 這個類的實例可以獲得newSAXParser()方法。 
  139.              * 一旦獲取該類的實例,XML可以解析來自各種輸入源。 
  140.              * 這些輸入來源是InputStreams、文件、url和SAX InputSources 
  141.              **/  
  142.              //實力化SAXParser 得到xml解析的對象getXMLReader   
  143.             SAXParser sp=factory.newSAXParser();  
  144.             XMLReader reader=sp.getXMLReader();  
  145.             //調用XmlHandler 生成一個對象   
  146.             XmlHandler handler=new XmlHandler();  
  147.             /**讓應用程序可以注冊一個事件處理程序的內容。   
  148.              * 如果應用程序不注冊一個內容處理程序, 
  149.              * 所有內容事件報道的SAX解析器會悄悄地忽略。   
  150.              * 應用程序可以注冊一個新的或不同的處理程序在中間的一個解析, 
  151.              * SAX解析器必須立即開始使用新的處理程序。***/  
  152.             reader.setContentHandler(handler);  
  153.             //得到解析的天氣的資源+你所需要解析的城市   
  154.             URL url=new URL("http://www.google.com/ig/api?hl=zh-cn&weather=" + URLEncoder.encode(cityname));  
  155.             /**** 
  156.              * 讀取數據從源輸入流���換成字符通過提供的字符轉換器。 
  157.              * 默認的編碼是取自“文件。編碼”的系統屬性。 
  158.              * InputStreamReader包含一個緩沖區讀取的字節數從源流並將其轉化成字符需要。 
  159.              * 緩沖區的大小是8 K 
  160.              */  
  161.             //打開輸入流   
  162.             InputStream inputStream=url.openStream();  
  163.             //轉換成國家標准擴展碼GBK   
  164.             InputStreamReader inputStreamReader=new InputStreamReader(inputStream,"GBK");  
  165.             /****   InputSource 
  166.              * 這個類允許SAX應用程序封裝輸入源的信息在一個單獨的對象, 
  167.              * 這可能包括一個公共標識符、系統標識符,字節流(可能有一個指定的編碼),和轉義字符或字符流。 
  168.              * 
  169.              **/  
  170.             //聲明一個對象   
  171.             InputSource source=new InputSource(inputStreamReader);  
  172.             /****** 
  173.              * 應用程序可以使用這個方法來指導讀者開始的XML解析一個XML文檔 
  174.              * 從任何有效的輸入源(一個字符流,字節流,或一個URI)。   
  175.              * 應用程序可能無法調用該方法雖然解析過程中 
  176.              * (他們應該創建一個新的XMLReader相反嵌套的每個XML文檔)。 
  177.              * 一旦一個解析完成,應用程序可以重用相同的XMLReader對象, 
  178.              * 可能使用不同的輸入源 
  179.              * XMLReader的配置對象(如處理器綁定和價值觀的確立對功能的標志和屬性)是未受完成解析, 
  180.              * 除非那方面的定義顯式地指定配置的其他行為*******/  
  181.             reader.parse(source);  
  182.             //得到天氣列表   
  183.             List<weatherSetGet> weatherlist=handler.getWeatherList();  
  184.             //實力化表格布局   
  185.             TableLayout tableLayout=(TableLayout)findViewById(R.id.weathertable);  
  186.             //刪除viewGroup中的子視圖   
  187.             tableLayout.removeAllViews();  
  188.               
  189.             for (weatherSetGet weather:weatherlist) {  
  190.                   
  191.                 TableRow  row=new TableRow(this);  
  192.                 //設置布局參數與此相關的視圖。   
  193.                 //這些供應參數到父的這個視圖指定應該如何安排。   
  194.                 row.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));  
  195.                 //垂直居中   
  196.                 row.setGravity(Gravity.CENTER_VERTICAL);  
  197.                   
  198.                 ImageView imageView=new ImageView(this);  
  199.                 //下載圖片並繪制   
  200.                 imageView.setImageDrawable(loadImage(weather.getImage()));  
  201.                 ///z最小高度   
  202.                 imageView.setMinimumHeight(50);  
  203.                 row.addView(imageView);  
  204.                   
  205.                   
  206.                 TextView day=new TextView(this);  
  207.                 // 文本內容和顏色   
  208.                 day.setText(weather.getDay());  
  209.                 day.setTextColor(Color.RED);  
  210.                 day.setGravity(Gravity.CENTER_HORIZONTAL);  
  211.                 //添加視   
  212.                 row.addView(day);  
  213.                   
  214.                 TextView tv=new TextView(this);  
  215.                 tv.setText(weather.getLow()+"℃ -  "+weather.getHigh()+"℃ ");  
  216.                 tv.setTextColor(Color.RED);  
  217.               //添加視圖   
  218.                 row.addView(tv);  
  219.                   
  220.                 TextView condition=new TextView(this);  
  221.                //水平居中   
  222.                 condition.setGravity(Gravity.CENTER_HORIZONTAL);  
  223.                 //添加視圖   
  224.                 row.addView(condition);  
  225.                   
  226.                 tableLayout.addView(row);  
  227.                   
  228.                   
  229.                   
  230.                   
  231.             }  
  232.               
  233.         } catch (Exception e) {  
  234. // 解析錯誤時候彈出對話框   
  235.             new AlertDialog.Builder(this)  
  236.             .setTitle("解析出錯啦!!!")  
  237.             .setMessage("獲取天氣數據失!!!請重試!!!")  
  238.         .setNegativeButton("確定"null).show();  
  239.               
  240.           
  241.         }  
  242.     }  
  243.   
  244.   
  245.   
  246.   
  247. //加載天氣圖片資源   
  248.   
  249.   
  250.     private Drawable loadImage(String image) {  
  251.     try {  
  252.         //從輸入流InputStream繪圖並得到返回其內容的資源是指由該URL。   
  253.         //默認情況下,返回一個InputStream,或null如果內容類型的響應是未知的   
  254.         return Drawable.createFromStream((InputStream)new URL("http://www.google.com/"+image).getContent(), "測試...");  
  255.           
  256.     } catch (Exception e) {  
  257.         Log.e("exception", e.getMessage());  
  258.     }  
  259.           
  260.           
  261.         return null;  
  262.     }  
  263. }  
5.親!最後別忘了添加聯網的權限哦!!
  1. <!-- 添加聯網的權限 -->  
  2. ;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 版本的天氣預報/

Copyright © Linux教程網 All Rights Reserved