How to use OpenWeatherMap UV Index
Posted on 25 Oct 2016
This post describes how to use OpenWeatherMap UV Index. This is an interesting API because we can use it to explore some important aspects of Android and of location-aware API. OpenWeatherMap provides this API for free! As you may already know, OpenWeatherMap also provides a full set of APIs about weather information: you can get current weather conditions, forecast, historical information and so on. This information is free, and we can use OpenWeatherMap APIs free of charge.
At the end of this article, we will build an Android app that gets the UV index and shows it using Material Design guidelines.
Before diving into the details of the app, it is useful to have some idea about the UV index.
Brief introduction to the UV index
The UV index (or ultraviolet index) is an international standard for measuring the ultraviolet radiation at a particular place and time.
Its purpose is to help people protect themselves from UV radiation. This index, therefore, is very important and useful.
The UV radiation is measured using a linear scale proportional to the UV intensity.
It is important, then, to know how to get this information from OpenWeatherMap.
OpenWeatherMap UV Index API
To get the UV index from OpenWeatherMap, the current location needs to be expressed in terms of latitude and longitude:
http://api.openweathermap.org/v3/uvi/{lat},{lon}/current.json?appid={your-api-key}
– and, of course, the API key.
You can the API key to create an account. This is free – you can use this link.
If you want to have a UV index at a specific time, you can use this API:
http://api.openweathermap.org/v3/uvi/{location}/{datetime}.json?appid={api_key}
where datetime is expressed using the ISO 8601 standard. As you can see, these two APIs are very simple to use. For more information, you can go to the API documentation.
As the documentation explains, the JSON response is easy to parse. It looks like this:
{
"time": "2016-03-03T12:00:00Z",
"location": {
"latitude": 40.75,
"longitude": -74.25
},
"data": 3.11
}
Now we have all the information we need to build our app.
It is very simple to invoke the OpenWeatherMap API once we know the current location (latitude and longitude). Let us assume that, by now, we already have these details.
Our Android app has to make an HTTP call to the OpenWeatherMap API and parse the JSON response. (For more information, see this article.)
As the HTTP client’s library, the app uses the OkHttp library, so the build.gradle is:
dependencies {
..
compile 'com.android.support:appcompat-v7:23.2.1'
compile 'com.android.support:design:23.2.1'
compile 'com.google.android.gms:play-services:8.4.0'
compile 'com.squareup.okhttp3:okhttp:3.2.0'
}
Once the dependency is configured, making an HTTP request is very simple:
private void handleConnection(Location loc) {
double lat = loc.getLatitude();
double lon = loc.getLongitude();
// Make HTTP request according to OpenWeatherMap API
String url = UV_URL + ((int) lat) + "," + ( (int) lon) + "/current.json?appid=" + APP_ID;
System.out.println("URL ["+url+"]");
Request request = new Request.Builder()
.url(url)
.build();
httpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
// Handle failure in HTTP request
}
@Override
public void onResponse(Call call, Response response) throws IOException {
// OK, we have the response ... parse it
try {
JSONObject obj = new JSONObject(response.body().string());
final double uvIndex = obj.optDouble("data");
System.out.println("UV Index ["+uvIndex+"]");
JSONObject jsonLoc = obj.getJSONObject("location");
final double cLon = jsonLoc.getDouble("longitude");
final double cLat = jsonLoc.getDouble("latitude");
Handler handler = new Handler(MainActivity.this.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
// Handle UI Update
}
});
}
catch(JSONException jex) {
jex.printStackTrace();
}
}
});
}
The final result is shown in the picture below:
The colour of the value shown in the image above changes according to the UV Index scale.
Get current longitude and latitude
As explained earlier, to get the current UV index, we need to use the current location, expressed using latitude and longitude.
As you may already know, Google Play Services is a set of services that extend the Android app features, providing a set of new services such as Google Maps, Google+ and Location Service. Using Google Play Location Services, we can build a location-aware app.
Google Play Services set-up
The first thing to do is to set up Google Play Location Services in build.gradle:
dependencies {
..
compile 'com.google.android.gms:play-services:8.4.0'
..
}
Now the library is ready, and we can use it in developing our Android app.
Moreover, the Android UV Index app should be aware of the current location so that it can pass the latitude and longitude to the OpenWeatherMap API to get the current UV index.
We then have to develop a Google Play Services client to invoke the services provided by Google Play, so that the app can retrieve the current location.
Google Play Location Services client
Creating the client is very simple – we need just a few lines of code:
private void initGoogleClient() {
googleClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
At line 5, we specify that we use LocationServices.API. The initGoogleClient is called using the onCreate method so that we initialise the Google Play Location Services client as soon as the app starts.
It is important to remember to disconnect the client from the services when the app stops:
@Override
protected void onStop() {
googleClient.disconnect();
super.onStop();
}
– and to reconnect the client when the app starts:
@Override
protected void onStart() {
googleClient.connect();
super.onStart();
}
One more thing: before Google Play Services is ready, you need to register the app to listen when the connection fails or the connection is ready:
// Connection failure
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
showErrorMessage();
return;
}
// Connection established
@Override
public void onConnected(@Nullable Bundle bundle) {
getUVIndex();
}
The Google Play Services client is ready, and, as you can see, when the connection is ready the app retrieves the UV index.
Assembling the location-aware app
At the end, to invoke the UV Index API correctly, we can ask for the last known location using:
private Location getLocation() {
try {
Location loc = LocationServices.FusedLocationApi.getLastLocation(googleClient);
return loc;
}
catch(SecurityException se) {}
return null;
}
}
– where googleClient is the client we talked about in the previous section.
This method can return a null value, so the app can register itself for location updates, meaning it will be informed when the location changes:
LocationRequest req = new LocationRequest();
req.setInterval(60 * 60 * 1000);
req.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
LocationServices.FusedLocationApi.requestLocationUpdates(googleClient, req, this);
– where the interval is the notification interval. To learn more about LocationRequest, please refer to the official documentation.
Test location-aware app
To test the app, you need to use a simple Android app that returns a fake GPS location and enables a fake GPS position in your smartphone under the Developer section in the configuration menu.
Source code is available at GitHub.