Friday, March 23, 2012

Get weather info from Yahoo! Weather RSS Feed

The Yahoo! Weather RSS feed enables you to get up-to-date weather information, http://developer.yahoo.com/weather/.

The Weather RSS feed request follows simple HTTP GET syntax: start with a base URL and then add parameters and values after a question mark (?).

ex: Weather RSS feed for New York
http://weather.yahooapis.com/forecastrss?w=2459115

where 2459115 is WOEID for New York. You can find the code for any location from http://weather.yahoo.com/.

The another exercise show how to Search WOEID from http://query.yahooapis.com/.

The returned XML will like it:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<rss version="2.0" xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#">
 <channel>

<title>Yahoo! Weather - New York, NY</title>
<link>http://us.rd.yahoo.com/dailynews/rss/weather/New_York__NY/*http://weather.yahoo.com/forecast/USNY0996_f.html</link>
<description>Yahoo! Weather for New York, NY</description>
<language>en-us</language>
<lastBuildDate>Fri, 23 Mar 2012 8:49 pm EDT</lastBuildDate>
<ttl>60</ttl>
<yweather:location city="New York" region="NY"   country="United States"/>
<yweather:units temperature="F" distance="mi" pressure="in" speed="mph"/>
<yweather:wind chill="60"   direction="0"   speed="0" />
<yweather:atmosphere humidity="49"  visibility="10"  pressure="30.08"  rising="0" />
<yweather:astronomy sunrise="6:52 am"   sunset="7:10 pm"/>
<image>
<title>Yahoo! Weather</title>
<width>142</width>
<height>18</height>
<link>http://weather.yahoo.com</link>
<url>http://l.yimg.com/a/i/brand/purplelogo//uh/us/news-wea.gif</url>
</image>
<item>
<title>Conditions for New York, NY at 8:49 pm EDT</title>
<geo:lat>40.71</geo:lat>
<geo:long>-74.01</geo:long>
<link>http://us.rd.yahoo.com/dailynews/rss/weather/New_York__NY/*http://weather.yahoo.com/forecast/USNY0996_f.html</link>
<pubDate>Fri, 23 Mar 2012 8:49 pm EDT</pubDate>
<yweather:condition  text="Fair"  code="33"  temp="60"  date="Fri, 23 Mar 2012 8:49 pm EDT" />
<description><![CDATA[
<img src="http://l.yimg.com/a/i/us/we/52/33.gif"/><br />
<b>Current Conditions:</b><br />
Fair, 60 F<BR />
<BR /><b>Forecast:</b><BR />
Fri - Mostly Cloudy. High: 72 Low: 52<br />
Sat - PM Showers. High: 61 Low: 49<br />
<br />
<a href="http://us.rd.yahoo.com/dailynews/rss/weather/New_York__NY/*http://weather.yahoo.com/forecast/USNY0996_f.html">Full Forecast at Yahoo! Weather</a><BR/><BR/>
(provided by <a href="http://www.weather.com" >The Weather Channel</a>)<br/>
]]></description>
<yweather:forecast day="Fri" date="23 Mar 2012" low="52" high="72" text="Mostly Cloudy" code="27" />
<yweather:forecast day="Sat" date="24 Mar 2012" low="49" high="61" text="PM Showers" code="39" />
<guid isPermaLink="false">USNY0996_2012_03_24_7_00_EDT</guid>
</item>
</channel>
</rss>
<!-- api1.weather.sg1.yahoo.com compressed/chunked Fri Mar 23 18:50:03 PDT 2012 -->


Yahoo! Weather RSS Feed

It's a example to get Get weather info from Yahoo! Weather RSS Feed. Query Yahoo using HttpGet, then parse the returned XML using DOM. Please note that I only parse the returned RSS partially for demonstration, NOT ALL.

Get weather info from Yahoo! Weather RSS Feed

package com.exercise.AndroidYahooWeatherDOM;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;

public class AndroidYahooWeatherDOMActivity extends Activity {

TextView weather;

class MyWeather{
String description;
String city;
String region;
String country;

String windChill;
String windDirection;
String windSpeed;

String sunrise;
String sunset;

String conditiontext;
String conditiondate;

public String toString(){

 return "\n- " + description + " -\n\n"
  + "city: " + city + "\n"
  + "region: " + region + "\n"
  + "country: " + country + "\n\n"

  + "Wind\n"
  + "chill: " + windChill + "\n"
  + "direction: " + windDirection + "\n"
  + "speed: " + windSpeed + "\n\n"

  + "Sunrise: " + sunrise + "\n"
  + "Sunset: " + sunset + "\n\n"

  + "Condition: " + conditiontext + "\n"
  + conditiondate +"\n";
 
}
}

 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.main);
     weather = (TextView)findViewById(R.id.weather);
  
  
     String weatherString = QueryYahooWeather();
     Document weatherDoc = convertStringToDocument(weatherString);

     MyWeather weatherResult = parseWeather(weatherDoc);
     weather.setText(weatherResult.toString());
 }

 private MyWeather parseWeather(Document srcDoc){

  MyWeather myWeather = new MyWeather();

  //<description>Yahoo! Weather for New York, NY</description>
  myWeather.description = srcDoc.getElementsByTagName("description")
    .item(0)
    .getTextContent();

  //<yweather:location city="New York" region="NY" country="United States"/>
  Node locationNode = srcDoc.getElementsByTagName("yweather:location").item(0);
  myWeather.city = locationNode.getAttributes()
  .getNamedItem("city")
  .getNodeValue()
  .toString();
myWeather.region = locationNode.getAttributes()
  .getNamedItem("region")
  .getNodeValue()
  .toString();
myWeather.country = locationNode.getAttributes()
  .getNamedItem("country")
  .getNodeValue()
  .toString();

//<yweather:wind chill="60" direction="0" speed="0"/>
Node windNode = srcDoc.getElementsByTagName("yweather:wind").item(0);
myWeather.windChill = windNode.getAttributes()
  .getNamedItem("chill")
  .getNodeValue()
  .toString();
myWeather.windDirection = windNode.getAttributes()
  .getNamedItem("direction")
  .getNodeValue()
  .toString();
myWeather.windSpeed = windNode.getAttributes()
  .getNamedItem("speed")
  .getNodeValue()
  .toString();

//<yweather:astronomy sunrise="6:52 am" sunset="7:10 pm"/>
Node astronomyNode = srcDoc.getElementsByTagName("yweather:astronomy").item(0);
myWeather.sunrise = astronomyNode.getAttributes()
  .getNamedItem("sunrise")
  .getNodeValue()
  .toString();
myWeather.sunset = astronomyNode.getAttributes()
  .getNamedItem("sunset")
  .getNodeValue()
  .toString();

//<yweather:condition text="Fair" code="33" temp="60" date="Fri, 23 Mar 2012 8:49 pm EDT"/>
Node conditionNode = srcDoc.getElementsByTagName("yweather:condition").item(0);
myWeather.conditiontext = conditionNode.getAttributes()
  .getNamedItem("text")
  .getNodeValue()
  .toString();
myWeather.conditiondate = conditionNode.getAttributes()
  .getNamedItem("date")
  .getNodeValue()
  .toString();

  return myWeather;
 }

 private Document convertStringToDocument(String src){
  Document dest = null;

  DocumentBuilderFactory dbFactory =
    DocumentBuilderFactory.newInstance();
  DocumentBuilder parser;

  try {
   parser = dbFactory.newDocumentBuilder();
 dest = parser.parse(new ByteArrayInputStream(src.getBytes()));
} catch (ParserConfigurationException e1) {
 e1.printStackTrace();
 Toast.makeText(AndroidYahooWeatherDOMActivity.this,
     e1.toString(), Toast.LENGTH_LONG).show();
} catch (SAXException e) {
 e.printStackTrace();
 Toast.makeText(AndroidYahooWeatherDOMActivity.this,
     e.toString(), Toast.LENGTH_LONG).show();
} catch (IOException e) {
 e.printStackTrace();
 Toast.makeText(AndroidYahooWeatherDOMActivity.this,
     e.toString(), Toast.LENGTH_LONG).show();
}

  return dest;
 }

 private String QueryYahooWeather(){

  String qResult = "";
  String queryString = "http://weather.yahooapis.com/forecastrss?w=2459115";

  HttpClient httpClient = new DefaultHttpClient();
     HttpGet httpGet = new HttpGet(queryString);
  
     try {
      HttpEntity httpEntity = httpClient.execute(httpGet).getEntity();
    
      if (httpEntity != null){
       InputStream inputStream = httpEntity.getContent();
       Reader in = new InputStreamReader(inputStream);
       BufferedReader bufferedreader = new BufferedReader(in);
       StringBuilder stringBuilder = new StringBuilder();
     
       String stringReadLine = null;

       while ((stringReadLine = bufferedreader.readLine()) != null) {
        stringBuilder.append(stringReadLine + "\n");
       }
     
       qResult = stringBuilder.toString();
      }

} catch (ClientProtocolException e) {
 e.printStackTrace();
 Toast.makeText(AndroidYahooWeatherDOMActivity.this,
     e.toString(), Toast.LENGTH_LONG).show();
} catch (IOException e) {
 e.printStackTrace();
 Toast.makeText(AndroidYahooWeatherDOMActivity.this,
     e.toString(), Toast.LENGTH_LONG).show();
}

     return qResult;
 }
}


main.xml
<?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" >

 <TextView
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:text="@string/hello" />
 <ScrollView
     android:layout_width="fill_parent"
     android:layout_height="fill_parent">
     <TextView
         android:id="@+id/weather"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content" />
 </ScrollView>

</LinearLayout>


You have to modify AndroidManifest.xml to grand permission of "android.permission.INTERNET"

Download the files.

Next:
- Get description from Yahoo! Weather RSS feed, and display in WebView.
- Search WOEID from http://query.yahooapis.com/.
- Search WOEID and query Yahoo Weather
- Get Google Weather

Updated version:
- Get weather info from Yahoo! Weather RSS Feed in background thread

15 comments:

  1. nice tutorial helped me a lot but i have some errors and some questions,
    i want to make a simple app except that i want to show the weather condition, temperature, and maybe an image of the current weather.

    i keep getting the error
    "srcDoc cannot be resolved"

    i am very new to android, can you please help me out?

    ReplyDelete
  2. and i want to show the image that is shown of the current weather, how can i extract it from the xml should i just put it in the src of the image as a link or is there any other way :$

    again thank you in advance

    ReplyDelete
  3. hello Drilon Zenku,

    it's a easy way to display the CDATA of description, in WebView.

    Please read Get description from Yahoo! Weather RSS feed, and display in WebView..

    ReplyDelete
  4. Please, can you tell me how to get file xml from Yahoo! Weather RSS Feed like in your tutorial?

    ReplyDelete
  5. DO NOT truset eclipse niehter adp.

    it suddenlt worked perfectly after two days trying with it.


    Thank you.

    ReplyDelete
  6. How to parse both yweather:forecast? I'm only can get the last value

    ReplyDelete
  7. I'm trying to run this example but im getting android.os.NetworkOnMainThreadException how do you work around this?

    ReplyDelete
  8. hello Telles Nobrega,

    Yes, it's a outdate example. Start from API level 11, you cannot access Network in main thread.

    Please read Get weather info from Yahoo! Weather RSS Feed in background thread.

    ReplyDelete
  9. This code works well but my problem is, I want to get the weather update of my current city (whatever it is), not the weather forecast of NY.. What should I do for that?

    ReplyDelete
  10. Is it possible to get hourly forecast from yahoo weather?

    ReplyDelete
  11. I think Yahoo no this information provided.

    check it here: http://developer.yahoo.com/weather/

    ReplyDelete
  12. Hi
    this was very good to get started.
    Thanks :)
    However you parse the Inputstream into a string and then put the string back into a byte array input stream. This adds complexity and memory footprint
    you can simply do something like this:
    (I changed to URLConnection, it works aswell with the HTTPClient you used)



    private Document QueryYahooWeather(){
    String queryString = "http://weather.yahooapis.com/forecastrss?w=2459115";
    URL url;
    try {
    url = new URL(queryString);
    } catch (MalformedURLException e) {
    Log.e(TAG, "Malformed url " + queryString);
    return null;
    }

    try {
    URLConnection urlConnection = url.openConnection();
    urlConnection.connect();
    InputStream inputStream = urlConnection.getInputStream();

    DocumentBuilderFactory dbFactory =
    DocumentBuilderFactory.newInstance();
    DocumentBuilder parser;


    parser = dbFactory.newDocumentBuilder();
    return parser.parse(inputStream);

    } catch (Exception e) {
    Log.e(TAG, "Error parsing weather " + e);
    return null;
    }
    }

    ReplyDelete
  13. hello domenukk,

    thanks for your comment:)

    ReplyDelete