Android Weather Forecast - Google Weather API - Description

Tutorials with advanced 'difficulty' and more Lines of Code.

Android Weather Forecast - Google Weather API - Description

Postby plusminus » Fri Dec 21, 2007 12:34 am

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


What you learn: You will learn how to access the Google Weather API an parse the XML-Result using a SAXParser.

:idea: Designed/Tested with sdk-version: m5-rc14

What this contains:

Difficulty: 3.5 of 5
I did this within 2 hours of coding (half for the xml-layout :roll:). This once again shows the power and flexibility of the Android-Platform :!:

:idea: Questions/Problems: Simply post below...

What it will look like:
Screenshot taken with SDK-version m3:
Image Image


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 :!: + I added comments :!:
Syntax: [ Download ] [ Hide ]
Using xml Syntax Highlighting
  1. <xml_api_reply version="1">
  2.         <weather module_id="0" tab_id="0">
  3.                 <forecast_information>
  4.                         <!-- Some inner tags containing data about the city found, time and unit-stuff -->
  5.                         <city data="Schriesheim, BW"/>
  6.                         <postal_code data="Schriesheim,Germany"/>
  7.                         <latitude_e6 data=""/>
  8.                         <longitude_e6 data=""/>
  9.                         <forecast_date data="2007-12-21"/>
  10.                         <current_date_time data="2007-12-21 19:50:00 +0000"/>
  11.                         <unit_system data="US"/>
  12.                 </forecast_information>
  13.                 <current_conditions>
  14.                         <!-- Some inner tags containing data of current weather -->
  15.                         <condition data="Fog"/>
  16.                         <temp_f data="23"/>
  17.                         <temp_c data="-5"/>
  18.                         <humidity data="Humidity: 93%"/>
  19.                         <icon data="/images/weather/fog.gif"/>
  20.                         <wind_condition data="Wind: N at 1 mph"/>
  21.                 </current_conditions>
  22.                 <forecast_conditions>
  23.                         <!-- Some inner tags containing data about future weather -->
  24.                         <day_of_week data="Today"/>
  25.                         <low data="24"/>
  26.                         <high data="37"/>
  27.                         <icon data="/images/weather/fog.gif"/>
  28.                         <condition data="Fog"/>
  29.                 </forecast_conditions>
  30.                 <forecast_conditions>
  31.                         <!-- Some inner tags containing data about future weather -->
  32.                         <day_of_week data="Sat"/>
  33.                         <low data="24"/>
  34.                         <high data="37"/>
  35.                         <icon data="/images/weather/sunny.gif"/>
  36.                         <condition data="Clear"/>
  37.                 </forecast_conditions>
  38.                 <forecast_conditions>
  39.                         <!-- Another set as above -->
  40.                 </forecast_conditions>
  41.                 <forecast_conditions>
  42.                         <!-- Another set as above -->
  43.                 </forecast_conditions>
  44.         </weather>
  45. </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:
Syntax: [ Download ] [ Hide ]
Using xml Syntax Highlighting
  1. <xml_api_reply version="1">
  2.         <weather module_id="0" tab_id="0">
  3.                 <problem_cause data=""/>
  4.         </weather>
  5. </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:
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. public class WeatherSet {
  2.         // ===========================================================
  3.         // Fields
  4.         // ===========================================================
  5.        
  6.         private WeatherCurrentCondition myCurrentCondition = null;
  7.         private ArrayList<WeatherForecastCondition> myForecastConditions =
  8.                 new ArrayList<WeatherForecastCondition>(4);
  9.  
  10.         // ===========================================================
  11.         // Getter & Setter
  12.         // ===========================================================
  13.  
  14.         // Getter & Setter for fields above...
  15. }
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:
Image
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.
Image

By extending LinearLayout we've got the ability to set the android:orientation-Attribute to ="horizontal" or to ="vertical" :!: You can see that feature in the picture. The lonely "SingleWeatherInfoView" which shows the WeatherCondition of today, was coded with android:orientation="horizontal". You can see that the "inner" Views appear next to each other. The four "SingleWeatherInfoView" were xml-defined with: android:orientation="vertical", you can see that its "inner" Views appear below each other. This once again shows the power of object-orientated programming at its best :)

How to create a custom View :src: Separate/Extended Tutorial.
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:
  1. Call the Google Weather API with what the user typed to the EditText
  2. Create a SAXParser and parse the result of the previous step
  3. Display the parsed data in the five "SingleWeatherInfoView".
And this is the corresponding code:
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.                 Button cmd_submit = (Button)findViewById(R.id.cmd_submit);
  2.                 cmd_submit.setOnClickListener(new OnClickListener(){
  3.                         @Override
  4.                         public void onClick(View arg0) {
  5.                                 URL url;
  6.                                 try {
  7.                                         /* Get what user typed to the EditText. */                                     
  8.                                         String cityParamString =
  9.                                                 ((EditText)findViewById(R.id.edit_input))
  10.                                                         .getText().toString();
  11.                                         String queryString =
  12.                                                 "http://www.google.com/ig/api?weather="
  13.                                                         + cityParamString;
  14.                                         /* Replace blanks with HTML-Equivalent. */
  15.                                         url = new URL(queryString.replace(" ", "%20"));
  16.  
  17.                                         /* Get a SAXParser from the SAXPArserFactory. */
  18.                                         SAXParserFactory spf = SAXParserFactory.newInstance();
  19.                                         SAXParser sp = spf.newSAXParser();
  20.                                        
  21.                                         /* Get the XMLReader of the SAXParser we created. */
  22.                                         XMLReader xr = sp.getXMLReader();
  23.                                        
  24.                                         /* Create a new ContentHandler and apply it to the XML-Reader*/
  25.                                         GoogleWeatherHandler gwh = new GoogleWeatherHandler();
  26.                                         xr.setContentHandler(gwh);
  27.                                        
  28.                                         /* Parse the xml-data our URL-call returned. */
  29.                                         xr.parse(new InputSource(url.openStream()));
  30.  
  31.                                         /* Our Handler now provides the parsed weather-data to us. */
  32.                                         WeatherSet ws = gwh.getWeatherSet();
  33.                                        
  34.                                         /* Update the SingleWeatherInfoView with the parsed data. */
  35.                                         updateWeatherInfoView(R.id.weather_today, ws.getWeatherCurrentCondition());
  36.                                        
  37.                                         updateWeatherInfoView(R.id.weather_1, ws.getWeatherForecastConditions().get(0));
  38.                                         updateWeatherInfoView(R.id.weather_2, ws.getWeatherForecastConditions().get(1));
  39.                                         updateWeatherInfoView(R.id.weather_3, ws.getWeatherForecastConditions().get(2));
  40.                                         updateWeatherInfoView(R.id.weather_4, ws.getWeatherForecastConditions().get(3));
  41.                                        
  42.                                 } catch (Exception e) {
  43.                                         resetWeatherInfoViews();
  44.                                         Log.e(DEBUG_TAG, "WeatherQueryError", e);
  45.                                 }
  46.                         }
  47.                 });
Parsed in 0.038 seconds, using GeSHi 1.0.8.4


:) Thats it. :)
:arrow: Take a look at the Full Source of this Tutorial :larrow:

Regards,
plusminus
Last edited by plusminus on Mon Feb 25, 2008 2:00 pm, edited 2 times in total.
Image
Image | Android Development Community / Tutorials
User avatar
plusminus
Site Admin
Site Admin
 
Posts: 2688
Joined: Wed Nov 14, 2007 8:37 pm
Location: Schriesheim, Germany

Top

Postby wrapware » Thu Jan 17, 2008 8:00 pm

Really nice behavior.
But there is one question:

Is it possible to modify the xml definition by code in the following manner:

Syntax: [ Download ] [ Hide ]
Using xml Syntax Highlighting
  1. <?xml version="1.0" encoding="utf-8"?>
  2.  
  3. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  4.  
  5.         android:orientation="vertical"
  6.  
  7.         android:layout_width="fill_parent"
  8.  
  9.         android:layout_height="fill_parent"
  10.  
  11.         >
  12.  
  13.  
  14.  
  15.  
  16.  
  17.         <view xmlns:android="http://schemas.android.com/apk/res/android"
  18.  
  19.           class="de.xyz.widgets.ImageContainerView"
  20.  
  21.                         id="@+id/image1"
  22.  
  23.                         android:layout_width="fill_parent"
  24.  
  25.                         android:layout_height="wrap_content"
  26.  
  27.           />
  28.  
  29.                        
  30.  
  31. </LinearLayout>
Parsed in 0.002 seconds, using GeSHi 1.0.8.4


and modify the content in the Activity.onCreate method like the following:

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. ImageContainerView oView = (ImageContainerView)findViewById(R.id.image1);
  2.  
  3. // how can I do this ...
  4.  
  5. oView.setContent(new ImageContainerView(BitmapFactory.decodeResource(getResources(), R.drawable.image1)));
Parsed in 0.035 seconds, using GeSHi 1.0.8.4


Is there a way to load the image1 from the Code (in onCreate) into the 'static' XML-Representation, or must I go the long way like SingleWeatherInfoView?

Any help is welcome.
wrapware
Freshman
Freshman
 
Posts: 7
Joined: Thu Jan 17, 2008 7:48 pm
Location: Germany

Postby wrapware » Fri Jan 18, 2008 8:14 am

There is one method availabe, if the view is an ImageView:
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. oView.setImageDrawable(...
Parsed in 0.035 seconds, using GeSHi 1.0.8.4


But I'm using a View as base class, so there is still no way ...
wrapware
Freshman
Freshman
 
Posts: 7
Joined: Thu Jan 17, 2008 7:48 pm
Location: Germany

Forcast for Current Location

Postby GodsMoon » Mon Jan 21, 2008 10:16 pm

Instead of having the user input the name of the City and State is it possible to read the GPS coordinates (assuming the phone has a GPS) and get the weather from the current location?
I've looked around a little but it seems like google does not provide a weather API for GPS coords, its only for a city names.

Will I have to reengineer the program to work with another service or is there a gps coords to city name converter or did I just miss something in the weather api?

any ideas?

Thanks
GodsMoon
Developer
Developer
 
Posts: 26
Joined: Mon Dec 10, 2007 5:13 pm

Re: Forcast for Current Location

Postby plusminus » Mon Jan 21, 2008 11:59 pm

Hello GodsMoon,

also haven't seen a functionality in the Google Weather API to query for GPS.
So you probably have to go a way around using another API, but this will probably suck. :(

There has to be sth. out there that we could use. But I only had time for a superficial google-search. (Exams suck :!: )

Regards,
plusminus
Image
Image | Android Development Community / Tutorials
User avatar
plusminus
Site Admin
Site Admin
 
Posts: 2688
Joined: Wed Nov 14, 2007 8:37 pm
Location: Schriesheim, Germany

Postby cauchy » Tue Jan 22, 2008 9:26 pm

A way for you to convert your GPS coordinates to a City Name could be the following ws PI from geonames.org:

http://ws.geonames.org/findNearbyPlaceN ... 30&lng=5.4

You can easily get the lat and lng parameters from the LocationManager:

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. LocationManager lm = (LocationManager) context
  3.  
  4.                                   .getSystemService( Context.LOCATION_SERVICE);
  5.  
  6.  
  7.  
  8. Location current_location = lm.getCurrentLocation( "gps");
  9.  
  10. final String lat = String.valueOf( current_location.getLatitude());
  11.  
  12. final String lng = String.valueOf( current_location.getLongitude());
  13.  
  14.  
Parsed in 0.035 seconds, using GeSHi 1.0.8.4


Then all you have to do is a request to the URL I gave at the begining of my message replacing the lat and lng by their values, process the result with a bit of SAX parsing and there you go! :-)

This may be a bit overkill but I can't think of nothing simpler for you problem (if anyone has something else, I'm interrested).

Hope this helps!

Olivier.
cauchy
Freshman
Freshman
 
Posts: 4
Joined: Thu Jan 10, 2008 9:44 am
Location: Marseille, France

Top

Postby plusminus » Tue Jan 22, 2008 9:33 pm

Hello cauchy(Oliver),

big thx !!! I'll make a tutorial on parsing the output given by the service you suggested :!: (when I finished Exams).

For those who cannot wait ;) I'd suggest this tutorial: :src: Parsing XML from the Net - Using the SAXParser

Regards,
plusminus
Image
Image | Android Development Community / Tutorials
User avatar
plusminus
Site Admin
Site Admin
 
Posts: 2688
Joined: Wed Nov 14, 2007 8:37 pm
Location: Schriesheim, Germany

what a great find

Postby GodsMoon » Thu Jan 24, 2008 9:04 pm

cauchy,

Thank you so much that is an awesome find.

It will be very useful I'm sure.

Thank you for sharing :D
GodsMoon
Developer
Developer
 
Posts: 26
Joined: Mon Dec 10, 2007 5:13 pm

Postby GodsMoon » Thu Jan 24, 2008 9:50 pm

In the US findNearbyPlaceName is very spotty. If it doesn't find a place "nearby" it returns nothing. The zip code lookup is much better.
for example:
http://ws.geonames.org/findNearbyPostal ... g=-70.1834

I've just been plugging in random values and its seems to return results just about always (not over the ocean of course). It also seems to work in Canda, though I didn't try anywhere else.

If one of the other webservices is better let us know.
GodsMoon
Developer
Developer
 
Posts: 26
Joined: Mon Dec 10, 2007 5:13 pm

Postby cauchy » Thu Jan 24, 2008 11:23 pm

Hi GodsMoon,

Actually there is another really good one they have that gives the full address for a given location.
Unfortunatly it seems to work mainly(if not only) for the US. Anyway, it works fine with the locations provided by the Android Emulator ;-):

http://ws.geonames.org/findNearestAddre ... ng=-122.19

Olivier.
cauchy
Freshman
Freshman
 
Posts: 4
Joined: Thu Jan 10, 2008 9:44 am
Location: Marseille, France

Postby icer » Mon Feb 18, 2008 2:33 pm

Hey, this is a great tutorial. :)

Is there an API documentation for these weather features? Who owns that weather data and can I freely use it on 3rd party apps? Links please.

TIA
icer
icer
Once Poster
Once Poster
 
Posts: 1
Joined: Mon Feb 18, 2008 2:30 pm

Postby plusminus » Mon Feb 18, 2008 5:24 pm

Hello icer,

the weather Data is openly provided by Google and therefore we can us it for free.
I don't know whether there is any document out there describing how to use the API, just use it ;)

Regards,
plusminus
Image
Image | Android Development Community / Tutorials
User avatar
plusminus
Site Admin
Site Admin
 
Posts: 2688
Joined: Wed Nov 14, 2007 8:37 pm
Location: Schriesheim, Germany

will you porting this tutorial to m5-rc14?

Postby to__liuyi » Mon Feb 25, 2008 11:14 am

I really like the weather forcast tutorial, but it can't run on m5-rc14 SDK. Get Nullpoint exception when start. I think the layout has compatibility issue, but I don't know where.

Will you porting to m5-rc14?
to__liuyi
Freshman
Freshman
 
Posts: 4
Joined: Mon Feb 04, 2008 3:47 am

Postby plusminus » Mon Feb 25, 2008 2:03 pm

Just updated it. :)

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

Regards,
plusminus
Image
Image | Android Development Community / Tutorials
User avatar
plusminus
Site Admin
Site Admin
 
Posts: 2688
Joined: Wed Nov 14, 2007 8:37 pm
Location: Schriesheim, Germany

still have problems

Postby to__liuyi » Tue Feb 26, 2008 1:22 am

plusminus, that very kind of you!

but it still choked.

error msg on emulator say:
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. Application Error:
  2.  
  3. org.anddev.android.weatherforecast
  4.  
  5.  
  6.  
  7. An error has occurred in org.anddev.android.weatherforecast. Unable to start activity CompoentInfo{org.anddev.android.weatherforecast/org.anddev.android.weatheroforecast.WeatherForcast}:
  8.  
  9. java.lang.NullPointerException.
Parsed in 0.036 seconds, using GeSHi 1.0.8.4


and here is msg on console:
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. [2008-02-26 08:06:10 - WeatherForecast] ------------------------------
  2.  
  3. [2008-02-26 08:06:10 - WeatherForecast] Android Launch!
  4.  
  5. [2008-02-26 08:06:10 - WeatherForecast] adb is running normally.
  6.  
  7. [2008-02-26 08:06:10 - WeatherForecast] Launching: org.anddev.android.weatherforecast.WeatherForecast
  8.  
  9. [2008-02-26 08:06:10 - WeatherForecast] Automatic Target Mode: launch emulator.
  10.  
  11. [2008-02-26 08:06:10 - WeatherForecast] Launching a new emulator.
  12.  
  13. [2008-02-26 08:06:15 - WeatherForecast] New emulator found: emulator-tcp-5555
  14.  
  15. [2008-02-26 08:07:34 - WeatherForecast] HOME is up on device 'emulator-tcp-5555'
  16.  
  17. [2008-02-26 08:07:34 - WeatherForecast] Pushing WeatherForecast.apk to /data/app on device 'emulator-tcp-5555'
  18.  
  19. [2008-02-26 08:07:35 - WeatherForecast] Starting activity on device: org.anddev.android.weatherforecast.WeatherForecast
  20.  
  21. [2008-02-26 08:07:41 - WeatherForecast] ActivityManager: Starting: Intent { comp={org.anddev.android.weatherforecast/org.anddev.android.weatherforecast.WeatherForecast} }
Parsed in 0.039 seconds, using GeSHi 1.0.8.4



by the way, my Eclipse IDE that the AndroidManifest.xml has valiation errors. activity,action and category element must have property named android:name. I have to modify the file to this:

Syntax: [ Download ] [ Hide ]
Using xml Syntax Highlighting
  1. <?xml version="1.0" encoding="utf-8"?>
  2.  
  3. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  4.  
  5.    package="org.anddev.android.weatherforecast">
  6.  
  7.     <application android:icon="@drawable/icon">
  8.  
  9.         <activity android:name="WeatherForecast" android:label="@string/app_name">
  10.  
  11.             <intent-filter>
  12.  
  13.                 <action android:name="android.intent.action.MAIN" />
  14.  
  15.                 <category android:name="android.intent.category.LAUNCHER" />
  16.  
  17.             </intent-filter>
  18.  
  19.         </activity>
  20.  
  21.     </application>
  22.  
  23. </manifest>
Parsed in 0.003 seconds, using GeSHi 1.0.8.4


Do you think it related with the runtime exception?
to__liuyi
Freshman
Freshman
 
Posts: 4
Joined: Mon Feb 04, 2008 3:47 am

Top
Next

Return to Advanced Tutorials

Who is online

Users browsing this forum: No registered users and 3 guests