Weather Forecaster App Java Language Android App Goal: Create an app to display
ID: 665690 • Letter: W
Question
Weather Forecaster App
Java Language Android App
Goal: Create an app to display a weather forecast for the user’s current location
Create the app titled Weather Forecaster
The first screen will have a textbox for the user to enter a zip code and a button to submit
When the user enters the zip code and clicks the button, the app will navigate to the weather forecast screen.
The weather forecast screen will show the current weather for the user’s location in a label
Input validation for the zip code (only valid zip codes should be accepted)
Display a listview/tableview of the forecast for the next 7 days
Display images for the forecast (eg: clouds for cloudy weather, a sun for clear weather)
Get the weather using an async task
Use the user’s current location from the device GPS (for this functionality, the app does not need the zip code entry in the first screen)
Cache the data for offline use so the user can see the forecast even in airplane mode
Some publicly available weather APIs (any API is acceptable):
http://openweathermap.org/api
https://developer.yahoo.com/weather/
http://graphical.weather.gov/xml/
Explanation / Answer
Package com.demo.weatherapp;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.survivingwithandroid.weatherapp.model.Location;
import com.survivingwithandroid.weatherapp.model.Weather;
public class JSONWeatherParser {
public static Weather getWeather(String data) throws JSONException {
Weather weather = new Weather();
// We create out JSONObject from the data
JSONObject jObj = new JSONObject(data);
// We start extracting the info
Location loc = new Location();
JSONObject coordObj = getObject("coord", jObj);
loc.setLatitude(getFloat("lat", coordObj));
loc.setLongitude(getFloat("lon", coordObj));
JSONObject sysObj = getObject("sys", jObj);
loc.setCountry(getString("country", sysObj));
loc.setSunrise(getInt("sunrise", sysObj));
loc.setSunset(getInt("sunset", sysObj));
loc.setCity(getString("name", jObj));
weather.location = loc;
// We get weather info (This is an array)
JSONArray jArr = jObj.getJSONArray("weather");
// We use only the first value
JSONObject JSONWeather = jArr.getJSONObject(0);
weather.currentCondition.setWeatherId(getInt("id", JSONWeather));
weather.currentCondition.setDescr(getString("description", JSONWeather));
weather.currentCondition.setCondition(getString("main", JSONWeather));
weather.currentCondition.setIcon(getString("icon", JSONWeather));
JSONObject mainObj = getObject("main", jObj);
weather.currentCondition.setHumidity(getInt("humidity", mainObj));
weather.currentCondition.setPressure(getInt("pressure", mainObj));
weather.temperature.setMaxTemp(getFloat("temp_max", mainObj));
weather.temperature.setMinTemp(getFloat("temp_min", mainObj));
weather.temperature.setTemp(getFloat("temp", mainObj));
// Wind
JSONObject wObj = getObject("wind", jObj);
weather.wind.setSpeed(getFloat("speed", wObj));
weather.wind.setDeg(getFloat("deg", wObj));
// Clouds
JSONObject cObj = getObject("clouds", jObj);
weather.clouds.setPerc(getInt("all", cObj));
// We download the icon to show
return weather;
}
private static JSONObject getObject(String tagName, JSONObject jObj) throws JSONException {
JSONObject subObj = jObj.getJSONObject(tagName);
return subObj;
}
private static String getString(String tagName, JSONObject jObj) throws JSONException {
return jObj.getString(tagName);
}
private static float getFloat(String tagName, JSONObject jObj) throws JSONException {
return (float) jObj.getDouble(tagName);
}
private static int getInt(String tagName, JSONObject jObj) throws JSONException {
return jObj.getInt(tagName);
}
}
Package com.demo.weatherapp;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.survivingwithandroid.weatherapp.model.Location;
import com.survivingwithandroid.weatherapp.model.Weather;
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.Menu;
import android.widget.ImageView;
import android.widget.TextView;
public class MainActivity extends Activity {
private TextView cityText;
private TextView condDescr;
private TextView temp;
private TextView press;
private TextView windSpeed;
private TextView windDeg;
private TextView hum;
private ImageView imgView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String city = "London,UK";
cityText = (TextView) findViewById(R.id.cityText);
condDescr = (TextView) findViewById(R.id.condDescr);
temp = (TextView) findViewById(R.id.temp);
hum = (TextView) findViewById(R.id.hum);
press = (TextView) findViewById(R.id.press);
windSpeed = (TextView) findViewById(R.id.windSpeed);
windDeg = (TextView) findViewById(R.id.windDeg);
imgView = (ImageView) findViewById(R.id.condIcon);
JSONWeatherTask task = new JSONWeatherTask();
task.execute(new String[]{city});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
private class JSONWeatherTask extends AsyncTask<String, Void, Weather> {
@Override
protected Weather doInBackground(String... params) {
Weather weather = new Weather();
String data = ( (new WeatherHttpClient()).getWeatherData(params[0]));
try {
weather = JSONWeatherParser.getWeather(data);
// Let's retrieve the icon
weather.iconData = ( (new WeatherHttpClient()).getImage(weather.currentCondition.getIcon()));
} catch (JSONException e) {
e.printStackTrace();
}
return weather;
}
@Override
protected void onPostExecute(Weather weather) {
super.onPostExecute(weather);
if (weather.iconData != null && weather.iconData.length > 0) {
Bitmap img = BitmapFactory.decodeByteArray(weather.iconData, 0, weather.iconData.length);
imgView.setImageBitmap(img);
}
cityText.setText(weather.location.getCity() + "," + weather.location.getCountry());
condDescr.setText(weather.currentCondition.getCondition() + "(" + weather.currentCondition.getDescr() + ")");
temp.setText("" + Math.round((weather.temperature.getTemp() - 273.15)) + "C");
hum.setText("" + weather.currentCondition.getHumidity() + "%");
press.setText("" + weather.currentCondition.getPressure() + " hPa");
windSpeed.setText("" + weather.wind.getSpeed() + " mps");
windDeg.setText("" + weather.wind.getDeg() + "");
}
}
}
Package com.demo.weatherapp;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class WeatherHttpClient {
private static String BASE_URL = "http://api.openweathermap.org/data/2.5/weather?q=";
private static String IMG_URL = "http://openweathermap.org/img/w/";
public String getWeatherData(String location) {
HttpURLConnection con = null ;
InputStream is = null;
try {
con = (HttpURLConnection) ( new URL(BASE_URL + location)).openConnection();
con.setRequestMethod("GET");
con.setDoInput(true);
con.setDoOutput(true);
con.connect();
// Let's read the response
StringBuffer buffer = new StringBuffer();
is = con.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line = null;
while ( (line = br.readLine()) != null )
buffer.append(line + " ");
is.close();
con.disconnect();
return buffer.toString();
}
catch(Throwable t) {
t.printStackTrace();
}
finally {
try { is.close(); } catch(Throwable t) {}
try { con.disconnect(); } catch(Throwable t) {}
}
return null;
}
public byte[] getImage(String code) {
HttpURLConnection con = null ;
InputStream is = null;
try {
con = (HttpURLConnection) ( new URL(IMG_URL + code)).openConnection();
con.setRequestMethod("GET");
con.setDoInput(true);
con.setDoOutput(true);
con.connect();
// Let's read the response
is = con.getInputStream();
byte[] buffer = new byte[1024];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while ( is.read(buffer) != -1)
baos.write(buffer);
return baos.toByteArray();
}
catch(Throwable t) {
t.printStackTrace();
}
finally {
try { is.close(); } catch(Throwable t) {}
try { con.disconnect(); } catch(Throwable t) {}
}
return null;
}
}
Res folder:
Activitymain.xm
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<TextView
android:id="@+id/cityText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true" />
<ImageView
android:id="@+id/condIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@id/cityText" />
<TextView
android:id="@+id/condDescr"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/condIcon"
android:layout_alignLeft="@id/condIcon"
/>
<TextView
android:id="@+id/temp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="12dp"
android:layout_alignBaseline="@id/condDescr"
android:layout_toRightOf="@id/condDescr"/>
<TextView
android:id="@+id/pressLab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@id/condDescr"
android:text="Pressure"
android:layout_marginTop="15dp" />
<TextView
android:id="@+id/press"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@id/pressLab"
android:layout_toRightOf="@id/pressLab"
/>
<TextView
android:id="@+id/humLab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@id/pressLab"
android:text="Humidity" />
<TextView
android:id="@+id/hum"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@id/humLab"
android:layout_toRightOf="@id/humLab"
android:layout_marginLeft="4dp"
/>
<TextView
android:id="@+id/windLab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@id/humLab"
android:text="Wind" />
<TextView
android:id="@+id/windSpeed"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@id/windLab"
android:layout_toRightOf="@id/windLab"
android:layout_marginLeft="4dp"
/>
<TextView
android:id="@+id/windDeg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@id/windLab"
android:layout_toRightOf="@id/windSpeed"
android:layout_marginLeft="4dp"
/>
</RelativeLayout>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package=" com.demo.weatherapp "
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.demo.weatherapp.MainActivity"
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>
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.