Android Weather Forecast - Google Weather API - Description
Take a look at the Full Source of this Tutorial


What you learn: You will learn how to access the Google Weather API an parse the XML-Result using a SAXParser.
What this contains:
- Access the Google Weather API
- Load data from the web :src: Separate/Extended Tutorial
- Parse XML Files (Streams) using the SAXParser :src: Separate/Extended Tutorial
- Create a Custom View (extends LinearLayout) :src: Separate/Extended Tutorial
- ...
Difficulty: 3.5 of 5
I did this within 2 hours of coding (half for the xml-layout
What it will look like:
Screenshot taken with SDK-version m3:


Description:
0.) In this tutorial we are going to use the Google (iGoogle) Weather API. We will simply call an URL with the following style:
// Style:
http://www.google.com/ig/api?weather=QUERY
// Working Examples ( Note: that " "(space) has to be replaced with its html-expression "%20"
// Your browser manages that conversion automatically )
http://www.google.com/ig/api?weather=Sc ... im,Germany
http://www.google.com/ig/api?weather=New%20York,%20USA
The response is always like the following (when the city could be found):
Note: Originally the xml-code responded comes without LineFeeds
Using xml Syntax Highlighting
- <xml_api_reply version="1">
- <weather module_id="0" tab_id="0">
- <forecast_information>
- <!-- Some inner tags containing data about the city found, time and unit-stuff -->
- <city data="Schriesheim, BW"/>
- <postal_code data="Schriesheim,Germany"/>
- <latitude_e6 data=""/>
- <longitude_e6 data=""/>
- <forecast_date data="2007-12-21"/>
- <current_date_time data="2007-12-21 19:50:00 +0000"/>
- <unit_system data="US"/>
- </forecast_information>
- <current_conditions>
- <!-- Some inner tags containing data of current weather -->
- <condition data="Fog"/>
- <temp_f data="23"/>
- <temp_c data="-5"/>
- <humidity data="Humidity: 93%"/>
- <icon data="/images/weather/fog.gif"/>
- <wind_condition data="Wind: N at 1 mph"/>
- </current_conditions>
- <forecast_conditions>
- <!-- Some inner tags containing data about future weather -->
- <day_of_week data="Today"/>
- <low data="24"/>
- <high data="37"/>
- <icon data="/images/weather/fog.gif"/>
- <condition data="Fog"/>
- </forecast_conditions>
- <forecast_conditions>
- <!-- Some inner tags containing data about future weather -->
- <day_of_week data="Sat"/>
- <low data="24"/>
- <high data="37"/>
- <icon data="/images/weather/sunny.gif"/>
- <condition data="Clear"/>
- </forecast_conditions>
- <forecast_conditions>
- <!-- Another set as above -->
- </forecast_conditions>
- <forecast_conditions>
- <!-- Another set as above -->
- </forecast_conditions>
- </weather>
- </xml_api_reply>
Parsed in 0.007 seconds, using GeSHi 1.0.8.4
If we call the Google Weather API with an not existing town, like:
http://www.google.com/ig/api?weather=FantasyTown,Disneyland
The "error" xml-return-code for such a bad query is like:
Using xml Syntax Highlighting
- <xml_api_reply version="1">
- <weather module_id="0" tab_id="0">
- <problem_cause data=""/>
- </weather>
- </xml_api_reply>
Parsed in 0.001 seconds, using GeSHi 1.0.8.4
1.) So as we need to extract the information out of the XML-code returned, we have to choose a XML-parser. I decided to use an SAX-Parser (Wiki-Info). SAX stands for Simple API for XML, so it is perfect for us

So the parsing-part follows that Tutorial (one line above). It will parse the XML-Data returned by the Weather API and in the end it "presents" the following Object to us:
Using java Syntax Highlighting
- public class WeatherSet {
- // ===========================================================
- // Fields
- // ===========================================================
- private WeatherCurrentCondition myCurrentCondition = null;
- private ArrayList<WeatherForecastCondition> myForecastConditions =
- new ArrayList<WeatherForecastCondition>(4);
- // ===========================================================
- // Getter & Setter
- // ===========================================================
- // Getter & Setter for fields above...
- }
Parsed in 0.032 seconds, using GeSHi 1.0.8.4
It simply contains two sub-objects: WeatherCurrentCondition which contains the parsed data from the xml-tag <current_conditions> and a list of WeatherForecastInfoSet which contains the parsed data from all the xml-tags <forecast_conditions>.
The parsing part is finished now (see the full source for the actual code).
2.) Lets take a look at the Layout. The layout is a bit more complex as what has been done previously.
This it how it is cascaded:

I'm using so much TableLayouts, because they can easily stretch its child-Views.
The small entities with the Image and the Temperature-TextView are a customized View ("SingleWeatherInfoView"), which extends LinearLayout.

By extending LinearLayout we've got the ability to set the android:orientation-Attribute to ="horizontal" or to ="vertical"

How to create a custom View :src: Separate/Extended Tutorial.
The layout part is finished now (see the full source for the actual code).
The layout part is finished now (see the full source for the actual code).
3.) So 90% of the work is done now. The last thing we have to do is to put all the parts together.
We apply an OnClickListener to the Submit-Button, which will do the following, when clicked:
- Call the Google Weather API with what the user typed to the EditText
- Create a SAXParser and parse the result of the previous step
- Display the parsed data in the five "SingleWeatherInfoView".
Using java Syntax Highlighting
- Button cmd_submit = (Button)findViewById(R.id.cmd_submit);
- cmd_submit.setOnClickListener(new OnClickListener(){
- @Override
- public void onClick(View arg0) {
- URL url;
- try {
- /* Get what user typed to the EditText. */
- String cityParamString =
- ((EditText)findViewById(R.id.edit_input))
- .getText().toString();
- String queryString =
- "http://www.google.com/ig/api?weather="
- + cityParamString;
- /* Replace blanks with HTML-Equivalent. */
- url = new URL(queryString.replace(" ", "%20"));
- /* Get a SAXParser from the SAXPArserFactory. */
- SAXParserFactory spf = SAXParserFactory.newInstance();
- SAXParser sp = spf.newSAXParser();
- /* Get the XMLReader of the SAXParser we created. */
- XMLReader xr = sp.getXMLReader();
- /* Create a new ContentHandler and apply it to the XML-Reader*/
- GoogleWeatherHandler gwh = new GoogleWeatherHandler();
- xr.setContentHandler(gwh);
- /* Parse the xml-data our URL-call returned. */
- xr.parse(new InputSource(url.openStream()));
- /* Our Handler now provides the parsed weather-data to us. */
- WeatherSet ws = gwh.getWeatherSet();
- /* Update the SingleWeatherInfoView with the parsed data. */
- updateWeatherInfoView(R.id.weather_today, ws.getWeatherCurrentCondition());
- updateWeatherInfoView(R.id.weather_1, ws.getWeatherForecastConditions().get(0));
- updateWeatherInfoView(R.id.weather_2, ws.getWeatherForecastConditions().get(1));
- updateWeatherInfoView(R.id.weather_3, ws.getWeatherForecastConditions().get(2));
- updateWeatherInfoView(R.id.weather_4, ws.getWeatherForecastConditions().get(3));
- } catch (Exception e) {
- resetWeatherInfoViews();
- Log.e(DEBUG_TAG, "WeatherQueryError", e);
- }
- }
- });
Parsed in 0.038 seconds, using GeSHi 1.0.8.4
Regards,
plusminus






I'd suggest this tutorial: 
The text-colors are pretty shitty now. All grey and with the background I used (see the screenshot) just badly visible.