Creating a Weather Application for Mars Using Volley

Final product image
What You'll Be Creating

Introduction

In this tutorial, I will show you a possible use case of what we learnt in the previous article about Volley. We will create a weather application for Mars, using the information collected by the Curiosity rover, which is made available to everyone by NASA through the {MAAS} API.

First, we will set up the project in Android Studio and design the user interface. We will then structure the core of the application using Volley. Since every beautiful application features some images, I will show you how to fetch a random one using Flickr's API. We will download the picture with Volley, mostly because of its great caching system. Finally, we will add some fancy details to give the application a gorgeous look and feel.

1. Project Setup

First, create a new project in Android Studio. Since Volley is backwards compatible, you can choose whatever API level you prefer. I opted for API 21, but you should be fine as long as the API level is 8 (Froyo) or higher.

Step 1: User Interface

Our application has a single, simple activity. You can call it MainActivity.java, as suggested by Android Studio. Open the layout editor and double-click activity_main.xml.

Since we would like to have about 70% of the screen dedicated to the image and the rest to the weather information, we need to use the XML attribute layout_weight. Of course, we can use absolute values too, but it wouldn't be the same. Unfortunately, the Android world features displays that are anything but homogenous, and specifying an absolute value for the height of the image could result in a 90-10 ratio on very small devices and a 70-30, or even a 60-40 relation, on larger devices. The layout_weight attribute is what you need to solve this problem.

Inside the first child, add the ImageView:

In the second RelativeLayout, we add a list of TextView items. Two of them are views in which the average temperature and the atmosphere opacity are shown. The third is an error label.

The layout should now be complete. You can add more details if you want, but a complex and detailed user interface is not within the scope of this tutorial.

Step 2: Theme and Permissions

There are two more things we need to take care of before starting to dig into the core of the application. Change the inherited theme of the application to android:Theme.Material.Light.NoActionBar. This means that we don't need to hide the action bar at run time.

Finally, add the internet permission to the project's manifest.

2. Application Core

Step 1: Import Volley

As we discussed in the previous article, the simplest and most reliable way to use Volley is by importing the library as a new module. Download the source code of the library, import it via File > New > Module, and tell the compiler in the project's build.gradle file to include it in the project.

Step 2: Implement Helper Class

As I already pointed out in the previous article, if you need to fire multiple requests, it is better to use a shared request queue. You should avoid creating a request queue each time you schedule a request by invoking Volley.newRequestQueue, because you don't want to end up with memory leaks and other unwanted problems.

To do that, you first have to create a class using the singleton pattern. The class is referenced using a static, globally visible variable, which then handles the object RequestQueue. This way, you end up with a single RequestQueue for the application. Then, extending the Application class, you have to tell to the operating system to generate this object at application startup, even before the first activity is created.

Since we're in the Android environment, we slightly modify the common singleton structure. The class needs to create a new instance of itself in the Application.onCreate method—not in a generic getInstance method when it is null.

To achieve this, create a new class and name it MarsWeather.java. Next, extend the Android Application class, override the onCreate method, and initialize the RequestQueue object of the static instance.

In the singleton class, we construct the object of the class using a public and synchronized function getInstance. Inside this method, we return the mInstance variable. The onCreate method is invoked when the application is started so the mInstance variable will already be set the first time the getInstance method is invoked.

Next, tell in the AndroidManifest.xml file that you want MarsWeather to be loaded at application startup. In the <application> tag, add the attribute name as follows:

That's it. An instance of the Application class is created, even before MainActivity is created. Along with all the other standard operations, onCreate generates an instance of the RequestQueue.

We need to implement three other methods to finish up the helper class. The first method replaces Volley.newRequestQueue, which I'll name getRequestQueue. We also need a method to add a request to the queue, add, and a method that's responsible for canceling requests, cancel. The following code block shows what the implementation looks like.

TAG is a generic token you use to identify the request. In this specific case, it can be whatever you want:

Step 3: Implement the Custom Request

As you already know, Volley provides three standard request types: StringRequest, ImageRequest, and JsonRequest. Our application is going to use the latter to fetch weather data and retrieve the list of random images.

By default, Volley sets the priority of the request to NORMAL. Usually that would be fine, but in our application we have two requests that are quite different and we therefore need to have a different priority in the queue. Fetching the weather data needs to have a higher priority than fetching the URL of the random image.

For that reason, we need to customize the JsonRequest class. Create a new class named CustomJsonRequest.java, and make sure it extends JsonObjectRequest. Next, override the getPriority method as shown below.

Step 4: Fetching Data

We’re finally arrived to the most interesting part of this tutorial in which we write the implementation to fetch the weather data. The endpoint of the request is:

The APIs are browsable so open the link to inspect the resulting JSON. The JSON contains a simple object, result, that includes a series of strings, ranging from temperatures to wind direction and sunset time.

Start by declaring the following variables in the MainActivity class:

You can call MarsWeather.getInstance outside of onCreate. Since the class will already be initialized, you don’t need to wait for the onStart method to call it. Of course, you have to set the references of the user interface views in the onCreate method.

After doing that, it's time to implement the loadWeatherData method. We create a custom Volley request and set the priority to HIGH. We then invoke the helper's add method to add it to the request queue. The important thing to note is the result listener, since it's going to affect the user interface.

As you can see, the method takes the minimum and maximum temperatures, computes the average temperature, and update the user interface. I also implemented a simple method to handles errors.

We now only need to call loadWeatherData in onCreate and you're done. The app is now ready to show the weather of Mars.

3. Fetching Image Data

Now that you have the core of the app ready and working, we can focus on making the app visually more appealing. We are going to do this by fetching a random Mars image and displaying it to the user.

Step 1: Fetch a Random Picture

You will need a Flickr API key to fetch a random list of contextualized images. The image endpoint is the following:

As you can see, the request is fairly simple. You are telling Flickr to give you results formatted as JSON (format=json), but we don't specify a JSON callback (nojsoncallback=1). You are searching an image (method=flickr.photos.search) and the tags you are interested in are related to Mars (tags=mars,planet,rover). Take a look at the documentation for more information about the format of the request URL.

Start by declaring the following variables:

Next, implement the searchRandomImage method:

As you can see, Flickr sends back a JSONArray containing the images. The method I wrote to fetch a random image generates a random number between zero and to the size of the array. It takes the item corresponding to that index from the array of results and constructs the URL for the image following these guidelines.

Like before, we need a method for error handling:

Finally, call searchRandomImage in the onCreate method and don't forget to catch any exceptions.

Step 2: Show the Picture

Now that we have an URL to load, we can show the picture. You already learned how to do this in the previous article.

In the onResponse method we wrote in the previous step, we are finally able to handle the result.

Step 3: Showing a New Image Every Day

Maybe you already noticed that we are bypassing Volley's caching system by fetching a random image every time the application is launched. We need to find a way to show the same image on a particular day.

The simplest way to achieve this is by using Android’s SharedPreferences. Start by declaring the variables we'll need for this.

Next, in the onCreate method, before the call to searchRandomImage, initialize mSharedPref.

The idea is to store the current day every time we fetch a new random picture. Of course, we store the URL of the image alongside the day. When the application launches, we check whether we already have an entry in the SharedPreferences for the current day. If we have a match, we use the stored URL. Otherwise we fetch a random image and store its URL in the SharedPreferences.

In searchRandomImage, after the definition of imageUrl, add the following lines of code:

The onCreate method, after the definition on mSharedPref, now becomes:

That's it. Your application is ready. Feel free to download the source files of this tutorial on GitHub to see the completed project. Take a look at the project it if you're running into issues.

Bonus Tip: Improving the User Interface

Step 1: Font

The font used in a user interface often determines the look and feel of an application. Let's start by changing the default Roboto font with a more appealing font, such as Lato light.

Create a new folder named fonts in the assets folder. If you can’t find the assets folder, you have to create it at the same level as the java folder. The folder structure should look something like app\src\main\assets\fonts.

Copy the file Lato-light.ttf in the fonts folder. In the onCreate method, you need to override the default typeface of the views in which you'd like to use the new font.

Step 2: Transparent Status Bar

Following the guidelines for Android Material Design, we can make the status bar transparent. This way, the background will be partially visible through the status bar.

You can achieve this by making a small change in the application's theme. Edit the project's v21\style.xml file like this:

Make sure that the AndroidManifest.xml is already set to use the theme:

Conclusion

We made a long journey. In the first article, we started talking about Volley and its applications. In this tutorial, we looked at a practical way to implement the concepts we learned by building a weather application for Mars. You should now have a good understanding of the Volley library, how it works, and what you can use it for.

Tags:

Comments

Related Articles