歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Android 版本的天氣預報

Android 版本的天氣預報

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