Tutorial details

Android: Build real weather app: JSON, HTTP and Openweathermap | App Code for Sale | Preview

Android: Build real weather app: JSON, HTTP and Openweathermap | Android Tutorial

How to create a weather app that gives current weather information

Overview PAGE TOP

In this post I want to describe how to create a weather app that gives current weather information. This app will use JSON, HTTP connection and AsyncTask to get this information.. As weather provider I will use OpenWeatherMap a free weather service that provides some interesting API really easy to use.I will guide you through the steps necessary to build up a working app. For more information about API, you can visit the OpenWeatherMap web site. I will show to you the final result so you can have an idea about what we will do in this post.

bacha.JPG

Current weather info – HTTP Request and JSON Response

OpenWeatherMap offers several API to use to get weather information. We want to use the one that gives us the current weather info. The URL to call to get this info is:

1   http://api.openweathermap.org/data/2.5/weather?q=city,country

Let’s suppose we want to know the weather in Rome, IT. Using our browser we can have:

tqqq.JPG

As we can see we have JSON response. Formatting the response we have

01  {
02    "coord":{"lon":12.4958,"lat":41.903},
03    "sys":{"country":"Italy","sunrise":1369107818,"sunset":1369160979},
04    "weather":[{
05          "id":802,"main":"Clouds","description":"scattered clouds",
06           "icon":"03d"}],
07     "base":"global stations",
08     "main":{
09             "temp":290.38,
10             "humidity":68,
11             "pressure":1015,
12             "temp_min":287.04,
13             "temp_max":293.71},
14      "wind":{
15             "speed":1.75,
16             "deg":290.002},
17      "clouds":{"all":32},
18      "dt":1369122932,
19      "id":3169070,
20      "name":"Rome",
21      "cod":200
22  }

So the first thing we need to do is creating our data model so that we can parse the response and convert it into Java classes. Analyzing the response we have different “main” tags that we can use as class in Java:

  • coord (object)
  • sys (object)
  • weather (array)
  • main (object)
  • wind (object)
  • name: (String)

The response is quite simple and we can convert it manually. The UML class diagram for the model is shown below:

ami.JPG

JSON Weather Parser

Once we have created our model we have to parse it. We can create a specific class that handles this task. First we have to create the “root” object that receive as input the entire string containing all the JSON response:

1   // We create out JSONObject from the data
2   JSONObject jObj = new JSONObject(data);

Then we start parsing each piece of the response:

01  // We start extracting the info
02  Location loc = new Location();
03  
04  JSONObject coordObj = getObject("coord", jObj);
05  loc.setLatitude(getFloat("lat", coordObj));
06  loc.setLongitude(getFloat("lon", coordObj));
07  
08  JSONObject sysObj = getObject("sys", jObj);
09  loc.setCountry(getString("country", sysObj));
10  loc.setSunrise(getInt("sunrise", sysObj));
11  loc.setSunset(getInt("sunset", sysObj));
12  loc.setCity(getString("name", jObj));
13  weather.location = loc;

In the line 4,8 we create two “sub” object (coordObj and sysObj) having as parent the jObj as it clear from the JSON response. As we can see we use some helper methods to get String,int and float values:

01  private static JSONObject getObject(String tagName, JSONObject jObj)  throws JSONException {
02      JSONObject subObj = jObj.getJSONObject(tagName);
03      return subObj;
04  }
05  
06  private static String getString(String tagName, JSONObject jObj) throws JSONException {
07      return jObj.getString(tagName);
08  }
09  
10  private static float  getFloat(String tagName, JSONObject jObj) throws JSONException {
11      return (float) jObj.getDouble(tagName);
12  }
13  
14  private static int  getInt(String tagName, JSONObject jObj) throws JSONException {
15      return jObj.getInt(tagName);
16  }

And then we finally parse the weather information. We have to remember that weather tag is an array so we have to handle it differently

01  // We get weather info (This is an array)
02  JSONArray jArr = jObj.getJSONArray("weather");
03  
04  // We use only the first value
05  JSONObject JSONWeather = jArr.getJSONObject(0);
06  weather.currentCondition.setWeatherId(getInt("id", JSONWeather));
07  weather.currentCondition.setDescr(getString("description", JSONWeather));
08  weather.currentCondition.setCondition(getString("main", JSONWeather));
09  weather.currentCondition.setIcon(getString("icon", JSONWeather));
10  
11  JSONObject mainObj = getObject("main", jObj);
12  weather.currentCondition.setHumidity(getInt("humidity", mainObj));
13  weather.currentCondition.setPressure(getInt("pressure", mainObj));
14  weather.temperature.setMaxTemp(getFloat("temp_max", mainObj));
15  weather.temperature.setMinTemp(getFloat("temp_min", mainObj));
16  weather.temperature.setTemp(getFloat("temp", mainObj));
17  
18  // Wind
19  JSONObject wObj = getObject("wind", jObj);
20  weather.wind.setSpeed(getFloat("speed", wObj));
21  weather.wind.setDeg(getFloat("deg", wObj));
22  
23  // Clouds
24  JSONObject cObj = getObject("clouds", jObj);
25  weather.clouds.setPerc(getInt("all", cObj));

At the end we have our Weather class filled with the data retrieved.

HTTP Request and Response

Now we have to exchange information with the remote server using HTTP protocol. We have to send information and then read the response. We covered this topic in the previous post( Android HTTP Client: GET, POST, Download, Upload, Multipart Request) so we won’t describe it again, we simply show the code:

01  public class WeatherHttpClient {
02  
03      private static String BASE_URL = "http://api.openweathermap.org/data/2.5/weather?q=";
04      private static String IMG_URL = "http://openweathermap.org/img/w/";
05  
06      public String getWeatherData(String location) {
07          HttpURLConnection con = null ;
08          InputStream is = null;
09  
10          try {
11              con = (HttpURLConnection) ( new URL(BASE_URL + location)).openConnection();
12              con.setRequestMethod("GET");
13              con.setDoInput(true);
14              con.setDoOutput(true);
15              con.connect();
16  
17              // Let's read the response
18              StringBuffer buffer = new StringBuffer();
19              is = con.getInputStream();
20              BufferedReader br = new BufferedReader(new InputStreamReader(is));
21              String line = null;
22              while (  (line = br.readLine()) != null )
23                  buffer.append(line + "\r\n");
24  
25              is.close();
26              con.disconnect();
27              return buffer.toString();
28          }
29          catch(Throwable t) {
30              t.printStackTrace();
31          }
32          finally {
33              try { is.close(); } catch(Throwable t) {}
34              try { con.disconnect(); } catch(Throwable t) {}
35          }
36  
37          return null;
38  
39      }
40  
41      public byte[] getImage(String code) {
42          HttpURLConnection con = null ;
43          InputStream is = null;
44          try {
45              con = (HttpURLConnection) ( new URL(IMG_URL + code)).openConnection();
46              con.setRequestMethod("GET");
47              con.setDoInput(true);
48              con.setDoOutput(true);
49              con.connect();
50  
51              // Let's read the response
52              is = con.getInputStream();
53              byte[] buffer = new byte[1024];
54              ByteArrayOutputStream baos = new ByteArrayOutputStream();
55  
56              while ( is.read(buffer) != -1)
57                  baos.write(buffer);
58  
59              return baos.toByteArray();
60          }
61          catch(Throwable t) {
62              t.printStackTrace();
63          }
64          finally {
65              try { is.close(); } catch(Throwable t) {}
66              try { con.disconnect(); } catch(Throwable t) {}
67          }
68  
69          return null;
70  
71      }
72  }

Weather App

Finally, it is the time for our Activity. The layout is very simple and of course it is just a skeleton you need to improve it if you want to have a production app.

001 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
002     xmlns:tools="http://schemas.android.com/tools"
003     android:layout_width="match_parent"
004     android:layout_height="match_parent"
005     android:paddingBottom="@dimen/activity_vertical_margin"
006     android:paddingLeft="@dimen/activity_horizontal_margin"
007     android:paddingRight="@dimen/activity_horizontal_margin"
008     android:paddingTop="@dimen/activity_vertical_margin"
009     tools:context=".MainActivity" >
010 
011     <TextView
012         android:id="@+id/cityText"
013         style="?android:attr/textAppearanceMedium"
014         android:layout_width="wrap_content"
015         android:layout_height="wrap_content"
016         android:layout_centerHorizontal="true" />
017 
018     <ImageView
019         android:id="@+id/condIcon"
020         android:layout_width="wrap_content"
021         android:layout_height="wrap_content"
022         android:layout_alignParentLeft="true"
023         android:layout_below="@id/cityText" />
024 
025     <TextView
026         android:id="@+id/condDescr"
027         android:layout_width="wrap_content"
028         android:layout_height="wrap_content"
029         android:layout_below="@id/condIcon"
030         android:layout_alignLeft="@id/condIcon"
031        />
032 
033     <TextView
034         android:id="@+id/temp"
035         style="@style/tempStyle"
036         android:layout_width="wrap_content"
037         android:layout_height="wrap_content"
038         android:layout_marginLeft="12dp"
039         android:layout_alignBaseline="@id/condDescr"
040         android:layout_toRightOf="@id/condDescr"/>
041 
042     <TextView
043         android:id="@+id/pressLab"
044         android:layout_width="wrap_content"
045         android:layout_height="wrap_content"
046         android:layout_alignParentLeft="true"
047         android:layout_below="@id/condDescr"
048         android:text="Pressure"
049         android:layout_marginTop="15dp" />
050 
051     <TextView
052         android:id="@+id/press"
053         android:layout_width="wrap_content"
054         android:layout_height="wrap_content"
055         android:layout_alignBaseline="@id/pressLab"
056         android:layout_toRightOf="@id/pressLab"
057         style="@style/valData"/>
058 
059     <TextView
060         android:id="@+id/humLab"
061         android:layout_width="wrap_content"
062         android:layout_height="wrap_content"
063         android:layout_alignParentLeft="true"
064         android:layout_below="@id/pressLab"
065         android:text="Humidity" />
066 
067     <TextView
068         android:id="@+id/hum"
069         android:layout_width="wrap_content"
070         android:layout_height="wrap_content"
071         android:layout_alignBaseline="@id/humLab"
072         android:layout_toRightOf="@id/humLab"
073         android:layout_marginLeft="4dp"
074         style="@style/valData"/>
075 
076     <TextView
077         android:id="@+id/windLab"
078         android:layout_width="wrap_content"
079         android:layout_height="wrap_content"
080         android:layout_alignParentLeft="true"
081         android:layout_below="@id/humLab"
082         android:text="Wind" />
083 
084     <TextView
085         android:id="@+id/windSpeed"
086         android:layout_width="wrap_content"
087         android:layout_height="wrap_content"
088         android:layout_alignBaseline="@id/windLab"
089         android:layout_toRightOf="@id/windLab"
090         android:layout_marginLeft="4dp"
091         style="@style/valData" />
092 
093     <TextView
094         android:id="@+id/windDeg"
095         android:layout_width="wrap_content"
096         android:layout_height="wrap_content"
097         android:layout_alignBaseline="@id/windLab"
098         android:layout_toRightOf="@id/windSpeed"
099         android:layout_marginLeft="4dp"
100         style="@style/valData"/>
101 
102 </RelativeLayout>

In onCreate method we simply get the reference to the Views inside the layout so that we can populate them later after the request is completed.

01  @Override
02  protected void onCreate(Bundle savedInstanceState) {
03      super.onCreate(savedInstanceState);
04      setContentView(R.layout.activity_main);
05      String city = "Rome,IT";
06  
07      cityText = (TextView) findViewById(R.id.cityText);
08      condDescr = (TextView) findViewById(R.id.condDescr);
09      temp = (TextView) findViewById(R.id.temp);
10      hum = (TextView) findViewById(R.id.hum);
11      press = (TextView) findViewById(R.id.press);
12      windSpeed = (TextView) findViewById(R.id.windSpeed);
13      windDeg = (TextView) findViewById(R.id.windDeg);
14      imgView = (ImageView) findViewById(R.id.condIcon);
15  
16      JSONWeatherTask task = new JSONWeatherTask();
17      task.execute(new String[]{city});
18  }

and we start an AsyncTask, because as we already know network operations are time consuming so we can run them in the main thread otherwise we could have an ANR problem. The JSONWeatherTask is very simply

01  protected Weather doInBackground(String... params) {
02      Weather weather = new Weather();
03      String data = ( (new WeatherHttpClient()).getWeatherData(params[0]));
04  
05      try {
06          weather = JSONWeatherParser.getWeather(data);
07  
08          // Let's retrieve the icon
09          weather.iconData = ( (newWeatherHttpClient()).getImage(weather.currentCondition.getIcon()));
10  
11      } catch (JSONException e) {               
12          e.printStackTrace();
13      }
14      return weather;
15  
16      }

At line 3 we make the HTTP request and then we parse it at line 6. At line 9 we retrieve the icon that shows the weather condition.

Running the code we have:

kemon.JPG

Reference PAGE TOP

http://www.javacodegeeks.com/2013/06/android-build-real-weather-app-json-http-and-openweathermap.html

1 Comments Leave a comment

Please login in order to leave a comment.

Newest first
  • dshepdev 2014-03-25 12:55:43 Thread #75

    Looks Good, I Have To Give This A Try!

!

Sign-in to your Chupamobile Account.

The Easiest way to Launch your next App or Game.

Join Chupamobile and get instant access to thousands of ready made App and Game Templates.

Creating an account means you’re okay with Chupamobile’s Terms of Service and Privacy Policy.