plusminus Site Admin

Joined: 14 Nov 2007 Posts: 2067 Location: Germany
|
Posted: Mon Dec 24, 2007 3:24 pm Post subject: Android Weather Forecast - Google Weather API - FULL SOURCE |
|
|
Android Weather Forecast - Google Weather API
Hop to the actual Tutorial-Part
The Full Source
To download the whole project, scroll to the attachments in the end of this post.
Designed/Tested with sdk-version: m5-rc14
Lets get it on :
The package-structure:

"/AndroidManifest.xml"
| XML: | <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.anddev.android.weatherforecast">
<application android:icon="@drawable/icon">
<activity android:name=".WeatherForecast" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest> |
"/res/layout/main.xml"
| XML: | <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/weather_background"
>
<TableLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:stretchColumns="0"
>
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Usage like: 'City, Country'"
android:gravity="left"
/>
<CheckBox android:id="@+id/chk_usecelsius"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Use °C (not °F)"
android:gravity="right"
/>
</TableRow>
</TableLayout>
<TableLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:stretchColumns="0"
>
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<EditText android:id="@+id/edit_input"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Schriesheim, Germany"
android:singleLine="true"
/>
<Button android:id="@+id/cmd_submit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="OK"
/>
</TableRow>
</TableLayout>
<org.anddev.android.weatherforecast.views.SingleWeatherInfoView
android:id="@+id/weather_today"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:paddingTop="15px"
/>
<TableLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:stretchColumns="0,1,2,3"
android:paddingTop="15px"
>
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<org.anddev.android.weatherforecast.views.SingleWeatherInfoView
android:id="@+id/weather_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
/>
<org.anddev.android.weatherforecast.views.SingleWeatherInfoView
android:id="@+id/weather_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
/>
<org.anddev.android.weatherforecast.views.SingleWeatherInfoView
android:id="@+id/weather_3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
/>
<org.anddev.android.weatherforecast.views.SingleWeatherInfoView
android:id="@+id/weather_4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
/>
</TableRow>
</TableLayout>
</LinearLayout> |
"/src/your_package_structure/WeatherForecast.java"
| Java: | package org.anddev.android.weatherforecast;
import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.anddev.android.weatherforecast.views.SingleWeatherInfoView;
import org.anddev.android.weatherforecast.weather.GoogleWeatherHandler;
import org.anddev.android.weatherforecast.weather.WeatherCurrentCondition;
import org.anddev.android.weatherforecast.weather.WeatherForecastCondition;
import org.anddev.android.weatherforecast.weather.WeatherSet;
import org.anddev.android.weatherforecast.weather.WeatherUtils;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
public class WeatherForecast extends Activity {
private final String DEBUG_TAG = "WeatherForcaster";
private CheckBox chk_usecelsius = null;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
this.chk_usecelsius = (CheckBox) findViewById(R.id.chk_usecelsius);
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);
}
}
});
}
private void updateWeatherInfoView(int aResourceID,
WeatherForecastCondition aWFIS) throws MalformedURLException {
/* Construct the Image-URL. */
URL imgURL = new URL("http://www.google.com" + aWFIS.getIconURL());
((SingleWeatherInfoView) findViewById(aResourceID)).setRemoteImage(imgURL);
int tempMin = aWFIS.getTempMinCelsius();
int tempMax = aWFIS.getTempMaxCelsius();
/* Convert from Celsius to Fahrenheit if necessary. */
if (this.chk_usecelsius.isChecked()) {
((SingleWeatherInfoView) findViewById(aResourceID))
.setTempCelciusMinMax(tempMin, tempMax);
} else {
tempMin = WeatherUtils.celsiusToFahrenheit(tempMin);
tempMax = WeatherUtils.celsiusToFahrenheit(tempMax);
((SingleWeatherInfoView) findViewById(aResourceID))
.setTempFahrenheitMinMax(tempMin, tempMax);
}
}
private void updateWeatherInfoView(int aResourceID,
WeatherCurrentCondition aWCIS) throws MalformedURLException {
/* Construct the Image-URL. */
URL imgURL = new URL("http://www.google.com" + aWCIS.getIconURL());
((SingleWeatherInfoView) findViewById(aResourceID)).setRemoteImage(imgURL);
/* Convert from Celsius to Fahrenheit if necessary. */
if (this.chk_usecelsius.isChecked()){
((SingleWeatherInfoView) findViewById(aResourceID))
.setTempCelcius(aWCIS.getTempCelcius());
}else{
((SingleWeatherInfoView) findViewById(aResourceID))
.setTempFahrenheit(aWCIS.getTempFahrenheit());
}
}
private void resetWeatherInfoViews() {
((SingleWeatherInfoView)findViewById(R.id.weather_today)).reset();
((SingleWeatherInfoView)findViewById(R.id.weather_1)).reset();
((SingleWeatherInfoView)findViewById(R.id.weather_2)).reset();
((SingleWeatherInfoView)findViewById(R.id.weather_3)).reset();
((SingleWeatherInfoView)findViewById(R.id.weather_4)).reset();
}
} |
"/src/your_package_structure/views/SingleWeatherInfoView.java"
| Java: | package org.anddev.android.weatherforecast.views;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Map;
import org.anddev.android.weatherforecast.R;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
/**
* The View capable of showing a WeatehrIcon + a Temperature-TextView.
*/
public class SingleWeatherInfoView extends LinearLayout {
// ===========================================================
// Fields
// ===========================================================
private ImageView myWeatherImageView = null;
private TextView myTempTextView = null;
// ===========================================================
// Constructors
// ===========================================================
public SingleWeatherInfoView(Context context) {
super(context);
}
public SingleWeatherInfoView(Context context, AttributeSet attrs,
Map inflateParams) {
super(context, attrs, inflateParams);
/* Setup the ImageView that will show weather-icon. */
this.myWeatherImageView = new ImageView(context);
this.myWeatherImageView.setImageDrawable(getResources().getDrawable(
R.drawable.dunno));
/* Setup the textView that will show the temperature. */
this.myTempTextView = new TextView(context);
this.myTempTextView.setText("? °C");
this.myTempTextView.setTextSize(16);
this.myTempTextView.setTypeface(Typeface
.create("Tahoma", Typeface.BOLD));
/* Add child views to this object. */
this.addView(this.myWeatherImageView, new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
this.addView(this.myTempTextView, new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
}
// ===========================================================
// Getter & Setter
// ===========================================================
public void reset() {
this.myWeatherImageView.setImageDrawable(getResources().getDrawable(
R.drawable.dunno));
this.myTempTextView.setText("? °C");
}
/** Sets the Child-ImageView of this to the URL passed. */
public void setRemoteImage(URL aURL) {
try {
URLConnection conn = aURL.openConnection();
conn.connect();
InputStream is = conn.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
Bitmap bm = BitmapFactory.decodeStream(bis);
bis.close();
is.close();
this.myWeatherImageView.setImageBitmap(bm);
} catch (IOException e) {
/* Reset to 'Dunno' on any error. */
this.myWeatherImageView.setImageDrawable(getResources()
.getDrawable(R.drawable.dunno));
}
}
public void setTempCelcius(int aTemp) {
this.myTempTextView.setText("" + aTemp + " °C");
}
public void setTempFahrenheit(int aTemp) {
this.myTempTextView.setText("" + aTemp + " °F");
}
public void setTempFahrenheitMinMax(int aMinTemp, int aMaxTemp) {
this.myTempTextView.setText("" + aMinTemp + "/" + aMaxTemp + " °F");
}
public void setTempCelciusMinMax(int aMinTemp, int aMaxTemp) {
this.myTempTextView.setText("" + aMinTemp + "/" + aMaxTemp + " °C");
}
public void setTempString(String aTempString) {
this.myTempTextView.setText(aTempString);
}
} |
"/src/your_package_structure/weather/GoogleWeatherHandler.java"
| Java: | package org.anddev.android.weatherforecast.weather;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* SAXHandler capable of extracting information out of the xml-data returned by
* the Google Weather API.
*/
public class GoogleWeatherHandler extends DefaultHandler {
// ===========================================================
// Fields
// ===========================================================
private WeatherSet myWeatherSet = null;
private boolean in_forecast_information = false;
private boolean in_current_conditions = false;
private boolean in_forecast_conditions = false;
private boolean usingSITemperature = false; // false means Fahrenheit
// ===========================================================
// Constructors
// ===========================================================
// ===========================================================
// Getter & Setter
// ===========================================================
public WeatherSet getWeatherSet() {
return this.myWeatherSet;
}
// ===========================================================
// Methods
// ===========================================================
@Override
public void startDocument() throws SAXException {
this.myWeatherSet = new WeatherSet();
}
@Override
public void endDocument() throws SAXException {
// Nothing
}
@Override
public void startElement(String namespaceURI, String localName,
String qName, Attributes atts) throws SAXException {
// 'Outer' Tags
if (localName.equals("forecast_information")) {
this.in_forecast_information = true;
} else if (localName.equals("current_conditions")) {
this.myWeatherSet
.setWeatherCurrentCondition(new WeatherCurrentCondition());
this.in_current_conditions = true;
} else if (localName.equals("forecast_conditions")) {
this.myWeatherSet.getWeatherForecastConditions().add(
new WeatherForecastCondition());
this.in_forecast_conditions = true;
} else {
String dataAttribute = atts.getValue("data");
// 'Inner' Tags of "<forecast_information>"
if (localName.equals("city")) {
} else if (localName.equals("postal_code")) {
} else if (localName.equals("latitude_e6")) {
/* One could use this to convert city-name to Lat/Long. */
} else if (localName.equals("longitude_e6")) {
/* One could use this to convert city-name to Lat/Long. */
} else if (localName.equals("forecast_date")) {
} else if (localName.equals("current_date_time")) {
} else if (localName.equals("unit_system")) {
if (dataAttribute.equals("SI"))
this.usingSITemperature = true;
}
// SHARED(!) 'Inner' Tags within "<current_conditions>" AND
// "<forecast_conditions>"
else if (localName.equals("day_of_week")) {
if (this.in_current_conditions) {
this.myWeatherSet.getWeatherCurrentCondition()
.setDayofWeek(dataAttribute);
} else if (this.in_forecast_conditions) {
this.myWeatherSet.getLastWeatherForecastCondition()
.setDayofWeek(dataAttribute);
}
} else if (localName.equals("icon")) {
if (this.in_current_conditions) {
this.myWeatherSet.getWeatherCurrentCondition().setIconURL(
dataAttribute);
} else if (this.in_forecast_conditions) {
this.myWeatherSet.getLastWeatherForecastCondition()
.setIconURL(dataAttribute);
}
} else if (localName.equals("condition")) {
if (this.in_current_conditions) {
this.myWeatherSet.getWeatherCurrentCondition()
.setCondition(dataAttribute);
} else if (this.in_forecast_conditions) {
this.myWeatherSet.getLastWeatherForecastCondition()
.setCondition(dataAttribute);
}
}
// 'Inner' Tags within "<current_conditions>"
else if (localName.equals("temp_f")) {
this.myWeatherSet.getWeatherCurrentCondition()
.setTempFahrenheit(Integer.parseInt(dataAttribute));
} else if (localName.equals("temp_c")) {
this.myWeatherSet.getWeatherCurrentCondition().setTempCelcius(
Integer.parseInt(dataAttribute));
} else if (localName.equals("humidity")) {
this.myWeatherSet.getWeatherCurrentCondition().setHumidity(
dataAttribute);
} else if (localName.equals("wind_condition")) {
this.myWeatherSet.getWeatherCurrentCondition()
.setWindCondition(dataAttribute);
}
// 'Inner' Tags within "<forecast_conditions>"
else if (localName.equals("low")) {
int temp = Integer.parseInt(dataAttribute);
if (this.usingSITemperature) {
this.myWeatherSet.getLastWeatherForecastCondition()
.setTempMinCelsius(temp);
} else {
this.myWeatherSet.getLastWeatherForecastCondition()
.setTempMinCelsius(
WeatherUtils.fahrenheitToCelsius(temp));
}
} else if (localName.equals("high")) {
int temp = Integer.parseInt(dataAttribute);
if (this.usingSITemperature) {
this.myWeatherSet.getLastWeatherForecastCondition()
.setTempMaxCelsius(temp);
} else {
this.myWeatherSet.getLastWeatherForecastCondition()
.setTempMaxCelsius(
WeatherUtils.fahrenheitToCelsius(temp));
}
}
}
}
@Override
public void endElement(String namespaceURI, String localName, String qName)
throws SAXException {
if (localName.equals("forecast_information")) {
this.in_forecast_information = false;
} else if (localName.equals("current_conditions")) {
this.in_current_conditions = false;
} else if (localName.equals("forecast_conditions")) {
this.in_forecast_conditions = false;
}
}
@Override
public void characters(char ch[], int start, int length) {
/*
* Would be called on the following structure: <element>characters</element>
*/
}
} |
"/src/your_package_structure/weather/WeatherCurrentCondition.java"
| Java: | package org.anddev.android.weatherforecast.weather;
/**
* Holds the information between the <current_conditions>-tag of what the Google
* Weather API returned.
*/
public class WeatherCurrentCondition {
// ===========================================================
// Fields
// ===========================================================
private String dayofWeek = null;
private Integer tempCelcius = null;
private Integer tempFahrenheit = null;
private String iconURL = null;
private String condition = null;
private String windCondition = null;
private String humidity = null;
// ===========================================================
// Constructors
// ===========================================================
public WeatherCurrentCondition() {
}
// ===========================================================
// Getter & Setter
// ===========================================================
public String getDayofWeek() {
return this.dayofWeek;
}
public void setDayofWeek(String dayofWeek) {
this.dayofWeek = dayofWeek;
}
public Integer getTempCelcius() {
return this.tempCelcius;
}
public void setTempCelcius(Integer temp) {
this.tempCelcius = temp;
}
public Integer getTempFahrenheit() {
return this.tempFahrenheit;
}
public void setTempFahrenheit(Integer temp) {
this.tempFahrenheit = temp;
}
public String getIconURL() {
return this.iconURL;
}
public void setIconURL(String iconURL) {
this.iconURL = iconURL;
}
public String getCondition() {
return this.condition;
}
public void setCondition(String condition) {
this.condition = condition;
}
public String getWindCondition() {
return this.windCondition;
}
public void setWindCondition(String windCondition) {
this.windCondition = windCondition;
}
public String getHumidity() {
return this.humidity;
}
public void setHumidity(String humidity) {
this.humidity = humidity;
}
} |
"/src/your_package_structure/weather/WeatherForecastCondition.java"
| Java: | package org.anddev.android.weatherforecast.weather;
/**
* Holds the information between the <forecast_conditions>-tag of what the
* Google Weather API returned.
*/
public class WeatherForecastCondition {
// ===========================================================
// Fields
// ===========================================================
private String dayofWeek = null;
private Integer tempMin = null;
private Integer tempMax = null;
private String iconURL = null;
private String condition = null;
// ===========================================================
// Constructors
// ===========================================================
public WeatherForecastCondition() {
}
// ===========================================================
// Getter & Setter
// ===========================================================
public String getDayofWeek() {
return dayofWeek;
}
public void setDayofWeek(String dayofWeek) {
this.dayofWeek = dayofWeek;
}
public Integer getTempMinCelsius() {
return tempMin;
}
public void setTempMinCelsius(Integer tempMin) {
this.tempMin = tempMin;
}
public Integer getTempMaxCelsius() {
return tempMax;
}
public void setTempMaxCelsius(Integer tempMax) {
this.tempMax = tempMax;
}
public String getIconURL() {
return iconURL;
}
public void setIconURL(String iconURL) {
this.iconURL = iconURL;
}
public String getCondition() {
return condition;
}
public void setCondition(String condition) {
this.condition = condition;
&nb |
| |