Android Openweathermap API: JSON, HTTP

This post describes how to use Android Openweathermap api to build android weather app that gives current weather information. This android 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 android weather app. For more information about API, you can visit the OpenWeatherMap web site.

You check this tutorial to  know how to retrieve current user position and the corresponding city name.

How to develop Android Weather app tutorial

I will show to you the final result so you can have an idea about what we will do in this post.

android openweathermap api

Openweathermap API requires to use API Key that has to be added to the request, like:

http://api.openweathermap.org/......&APPID={API_KEY}

In the tutorial below, we assume you have the API Key and you append it to the url. You can obtain it for free
after creating your account.

Android Openweathermap API: Current weather info

OpenWeatherMap offers several API to use to get weather information. We can use this provider to build an Android openweathermpa app. We want to use the one that gives us the current weather info. The URL to call to get this info is:
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:

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

{
"coord":{"lon":12.4958,"lat":41.903},
"sys":{"country":"Italy","sunrise":1369107818,"sunset":1369160979},
"weather":[{
"id":802,"main":"Clouds","description":"scattered clouds",
"icon":"03d"}],
"base":"global stations",
"main":{
"temp":290.38,
"humidity":68,
"pressure":1015,
"temp_min":287.04,
"temp_max":293.71},
"wind":{
"speed":1.75,
"deg":290.002},
"clouds":{"all":32},
"dt":1369122932,
"id":3169070,
"name":"Rome",
"cod":200
}

Parse JSON Data

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:

The definitive guide to build a weather app in Android. Go to… Click To Tweet
 

openweathermap class diagram

 

Android 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:

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

Then we start parsing each piece of the response:

// 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;

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:

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);
}

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

// 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));

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

Android HTTP Request and Response

Now we have to exchange information between our android app and the remote server using HTTP protocol so that the app invokes Android Openweathermap API. 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:

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 + "rn");

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;

}
}

Android 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.

<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"
style="?android:attr/textAppearanceMedium"
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"
style="@style/tempStyle"
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"
style="@style/valData"/>

<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"
style="@style/valData"/>

<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"
style="@style/valData" />

<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"
style="@style/valData"/>

</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.

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String city = "Rome,IT";

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});
}

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

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;

}

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:

openweathermap current weather api
openweathermap api how to build android app

It could be interesting integrate a physical object using IoT project with weather forecast and Arduino.

The source code available @github.

Recently another post describes how to build location aware app in Android to retrieve UV Index.

I’ve released a new WeatherLib for Android that simplifies the weather app coding helping you in many app details. This lib supports Openweathermap and other weather provider. If you are interested give a look here
You can even join the new community to talk about it.

weatherlib

 

Hopefully, at the end of this post you gained the knowlegde how to implement a weather app using Android Openweathermap as weather provider.

77 Comments

  1. isaac2k11 May 28, 2013
  2. rohan kandwal June 8, 2013
  3. Wetzel402 June 20, 2013
  4. sher July 26, 2013
  5. rogierv July 31, 2013
  6. survivingwithandroid August 1, 2013
  7. Gurpreet August 20, 2013
  8. AndroidDev101 August 23, 2013
  9. touchwood Inc August 24, 2013
  10. survivingwithandroid August 26, 2013
  11. survivingwithandroid August 26, 2013
  12. touchwood Inc August 27, 2013
  13. artem August 27, 2013
  14. survivingwithandroid August 27, 2013
  15. AndroidDev101 August 28, 2013
  16. survivingwithandroid August 28, 2013
  17. Huân Núi August 30, 2013
  18. alan123 September 25, 2013
  19. survivingwithandroid September 30, 2013
  20. jorge100613 October 7, 2013
  21. survivingwithandroid October 7, 2013
  22. wolf October 9, 2013
  23. survivingwithandroid October 10, 2013
  24. sathish October 23, 2013
  25. sathish October 23, 2013
  26. survivingwithandroid October 24, 2013
  27. survivingwithandroid October 24, 2013
  28. Priya December 19, 2013
  29. Sagar Sadavarte December 25, 2013
  30. Sagar Sadavarte December 25, 2013
  31. dude January 22, 2014
  32. deepak January 28, 2014
  33. survivingwithandroid January 28, 2014
  34. survivingwithandroid January 28, 2014
  35. Sagar Sadavarte January 28, 2014
  36. Rushikesh Gomekar February 4, 2014
  37. Toni February 7, 2014
  38. Rushikesh Gomekar February 9, 2014
  39. survivingwithandroid February 9, 2014
  40. survivingwithandroid February 9, 2014
  41. Сергей Ласкин February 9, 2014
  42. Toni February 9, 2014
  43. Toni February 11, 2014
  44. Сергей Ласкин February 12, 2014
  45. Сергей Ласкин February 12, 2014
  46. Toni February 20, 2014
  47. Mike February 21, 2014
  48. giupardeb February 28, 2014
  49. survivingwithandroid February 28, 2014
  50. giupardeb March 1, 2014
  51. davide dellai March 18, 2014
  52. survivingwithandroid March 18, 2014
  53. davide dellai March 18, 2014
  54. Steve April 1, 2014
  55. JR April 11, 2014
  56. JR April 11, 2014
  57. survivingwithandroid April 11, 2014
  58. JR April 11, 2014
  59. Prashanth Puranik April 12, 2014
  60. survivingwithandroid April 17, 2014
  61. survivingwithandroid April 17, 2014
  62. Steve May 2, 2014
  63. survivingwithandroid May 20, 2014
  64. alex June 13, 2014
  65. jr_roberth July 15, 2014
  66. Deepak Kanyan July 28, 2014
  67. ThemuRR February 19, 2015
  68. ThemuRR February 20, 2015
  69. Suyahmin Taluk April 5, 2015
  70. Karthick Udaiy May 9, 2015
  71. Juan Ignacio Alvarez May 26, 2015
  72. surya April 19, 2016
    • Francesco Azzola April 19, 2016
  73. Taimoor Azam June 22, 2016
  74. Carlos July 17, 2016

Add Comment