Build Android weather app using Openweathermap API: Step by Step guide [UPDATED]

This post describes how to use Android Openweathermap API to build an Android weather app that gives current weather information. This full guide covers all the aspects you need to know to build an Android weather app. During this guide you will learn:

  • How to use Openweathermap API
  • How to parse JSON data
  • How to make HTTP requests in Android
  • How to create an Android UI

As weather provider, this Android weather app will use OpenWeatherMap a free weather service that provides some interesting API really easy to use.

If you are interested on the Android app source code you can download it here:

The final result is shown below so that you can have an idea about what we will do in this post.

android openweathermap api

Android Openweathermap API Key

Before starting, it is necessary to get the API key we will use later. To get the API Key it is necessary to create your account.. Then login:

openweathermap api

Now click on API Keys in the menu in the top and get your key:

 

Openweathermap API Key for Android weather app

Now we can your our key to invoke the APIs

[plain]http://api.openweathermap.org/……&APPID={API_KEY}[/plain]

 

In the tutorial below, we assume you have the API Key and you append it to the URL.

Android Openweathermap API: Current weather info

OpenWeatherMap offers several API to use to get weather information. This Android weather app uses the Openweathermap API that gives us the current weather info.

The URL to call to get this info is:

[text]http://api.openweathermap.org/data/2.5/weather?q=city,country&APPID={your_key}[/text]

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

[json]{
  "coord": {
    "lon": 12.48,
    "lat": 41.89
  },
  "weather": [
    {
      "id": 800,
      "main": "Clear",
      "description": "clear sky",
      "icon": "01d"
    }
  ],
  "base": "stations",
  "main": {
    "temp": 278.71,
    "pressure": 1023,
    "humidity": 48,
    "temp_min": 277.15,
    "temp_max": 280.15
  },
  "visibility": 10000,
  "wind": {
    "speed": 7.7,
    "deg": 350
  },
  "clouds": {
    "all": 0
  },
  "dt": 1546509000,
  "sys": {
    "type": 1,
    "id": 6792,
    "message": 0.0447,
    "country": "IT",
    "sunrise": 1546497475,
    "sunset": 1546530690
  },
  "id": 6539761,
  "name": "Rome",
  "cod": 200
}
[/json]

Parsing Openweathermap JSON Data

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 classes in Java:

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

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

[bctt tweet=”The definitive guide to build a weather app in Android.”]

weather uml model

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 receives as input the entire string containing all the JSON response:

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

Then we start parsing each piece of the response:

[java]// 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;
[/java]

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:

[java]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);
}
[/java]

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

[java]// 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));[/java]

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 can invoke 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:

[java]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/";
private static String APPID = "{your_key}";
public String getWeatherData(String location) {
HttpURLConnection con = null ;
InputStream is = null;

try {
con = (HttpURLConnection) ( new URL(BASE_URL + location + "&APPID=" + APPID)).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;

}
}[/java]

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.

[xml]<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>[/xml]

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.

[java]@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});
}
[/java]

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

[java]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;
}
[/java]

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:

weather android openweathermap
weather android app

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

Hopefully, at the end of this post, you gained the knowledge on how to implement an Android Openweathermap app that shows the current weather information.

    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. survivingwithandroid April 11, 2014
    60. Prashanth Puranik April 12, 2014
    61. survivingwithandroid April 17, 2014
    62. survivingwithandroid April 17, 2014
    63. Steve May 2, 2014
    64. survivingwithandroid May 20, 2014
    65. alex June 13, 2014
    66. jr_roberth July 15, 2014
    67. Deepak Kanyan July 28, 2014
    68. Lee February 19, 2015
    69. ThemuRR February 19, 2015
    70. Lee February 20, 2015
    71. ThemuRR February 20, 2015
    72. Samir Mohamed February 23, 2015
    73. Suyahmin Taluk April 5, 2015
    74. 'K' May 9, 2015
    75. Karthick Udaiy May 9, 2015
    76. Juan Ignacio Alvarez May 26, 2015
    77. Juan Ignacio Alvarez May 26, 2015
    78. Mr.Thoai October 19, 2015
    79. Luis Pato December 4, 2015
    80. surya April 19, 2016
      • Francesco Azzola April 19, 2016
      • Anonymous December 21, 2018
    81. Taimoor Azam June 22, 2016
    82. Carlos July 17, 2016
    83. Daniel August 26, 2016
    84. Francesco Azzola November 6, 2016
      • Jakub Smolewski November 6, 2016
    85. Pingback: Parse JSON data in Android November 24, 2016
    86. Garvit arya March 23, 2017
    87. shakib January 3, 2020

    Add Your Comment