What’s Http and why should I care?
Http or, Hypertext Transfer Protocol is an application protocol. Applications use http to communicate with servers on the web.
Http defines how messages should be formatted and transmitted over the internet. Http also defines what the server should do with the messages it receives.
Most Android apps use Http to send and receive data over the internet
If your app needs to communicate over the internet, to fetch data from the cloud or save data in the cloud, then chances are that you will need to use Http to do that.
What’s OkHttp and why should I use it?
OkHttp makes it very easy to connect to the internet using Http.
- It takes care of connecting to the server
- It takes care of bad connection issues and will try and reconnect where possible
- It will try alternative server IP addresses if one should fail and alternatives are available
- You can use it Synchronously where you need to deal with using threads
- You can use it Asynchronously where OkHttp handles the threads for you
- You can use OkHttp from Android 2.3 and above
We’ll be showing you how to use OkHttp to download an image.
We use the OkHttp library to connect to a server and download an image. If the download is successful then the image is displayed, if not, then an error image is displayed.
We handle three possible errors:
- An error image is displayed
- If there is no internet connection. A Toast message is also displayed. Note that if the image that you want to download exists in the cache, then it will be displayed and not the error image
- If there is an available internet connection but for some reason the connection was not established. No Toast is displayed
- A different error image is displayed if a connection was made and a response returned but for some reason the image could not be downloaded. A possible reason could be that the image was not found on the server (status code 404)
We also make use of OkHttp’s caching facility. The image is cached after being successfully downloaded. Any subsequent requests to download the image will simply retrieve it from the cache, making things super-fast.
Pressing the Download Image button downloads our website’s Header image
The two error images: The top one displays if there was a successful connection but the required information was not returned. The bottom one displays if there is a connection problem
Here’s how we use the OkHttp library to download an image
First, you need to get the library.
Getting the library
Android Studio makes it very easy to get the OkHttp library and include it in your app.
With Android Studio running, select File>Project Structure… and the following window pops up:
Select the module, app in this case and click on the Dependencies tab.
To add a library, press the green plus sign (+) or Alt + Insert and then select Library dependency from the pop-up window:
Now enter com.squareup.okhttp:okhttp:2.2.0 in the search box and execute the search. Android Studio finds and lists all available library options. Select the library as highlighted in blue below:
Press OK to complete the selection.
Next, press Apply and Gradle syncs the library in your project. You can see it’s notification in the cream coloured band at the top of the window, Gradle project sync in progress… :
Press OK to close the window.
You can confirm that the library has now been included in your project by opening up the build.gradle(app) file (in the Project window on the left):
And there it is, com.squareup.okhttp:okhttp:2.2.0.
You’re now ready to use OkHttp in your app.
To be able to access the internet and to monitor the state of the network connection, you’ll need to include these permissions in your manifest file:
Include these permissions in your AndroidManfifest.xml file
Get the client
In the communication process, your mobile device is known as the client and the device containing the data that you want to access, the server.
OkHttp uses a client object to take care of the connection and transfer of data between the client device and the server. So, you'll need to create a new OkHttpClient object:
Create a client and use it to communicate with the server
The OkHttp client takes your request, sends it to the server and returns the server’s response to you.
You’ll need an address
You also need a URL; it’s the address of the resource that you’re looking for. The URL also contains information of what needs to be done with what you’re looking for. For example, the address:
- specifies if the communication should be encrypted (then you’ll use https instead of http) or not
- contains the path to the data that you’re looking for, for example, /images/my_image.jp
The OkHttp client adds its own fields to the URL that you supply to make the communication process fast and reliable.
The OkHttp client makes the connection, retrying various options if necessary, and returns the response to you. The connection object is then placed in a pool for reuse.
Create a cache
Using the cache is optional but pretty much required if you want to make your app’s internet connections fast (it also reduces bandwidth usage). The little bit of extra coding is well worth the effort.
OkHttp caches the response in the Android System’s file system. Subsequent requests for the object use the cached version.
Here’s how we create the cache:
A quick explanation
We create a cache directory, cacheDirectory by creating a new File object. We pass the File object two parameters:
- getCacheDir – returns the path to our app’s cache directory
- the name of the cache file
Then within a try/catch statement, we create the OkHttp cache, passing it the app’s cache directory and cache size as parameters.
For more on using the file system and the cache, have a look at our tutorial, Using Android’s file system for saving application data.
Make a note
- Never do any networking on the main thread
- Don’t try to update the User Interface (the main thread) from a worker thread
You can read all about threads in our tutorial, Processes and threads (it also contains a link to a tutorial on how to use threads)
We’ve put it all in our AsynchronousDownloadImage() method
We’ve put all the code that builds our http request, executes the request and handles the response in our AsynchronousDownloadImage() method.
We call this method:
- when the user presses the Download Image button – if the request is successful then the image is downloaded and displayed
- in the activity’s onResume() method – but only when the boolean isImageDisplaying is true. Essentially this ensures that we display the correct image when the device’s orientation changes
Note that the image is cached when first downloaded. Any subsequent request to download the image retrieves it from the cache and not the network.
If the image has been downloaded and cached and the network connection is lost, the image will still display.
Basically there are two steps in our AsynchronousDownloadImage() method:
- first build the request
- then put the request in a queue to wait for execution. This step also handles the result of the http request:
- this is where we handle the failure to connect
- and where we handle the returned response
Building the request
Build your Http request using OkHttp’s Request.Builder class:
Create a new Request object using the Request.Builder class
We build a simple http request, passing the URL of the image that we want to download to the url() method.
Calling build() builds the request.
Once you’ve built your request, you can call execute() to execute it immediately. It will run on the main thread so you will have to take care of this by using a worker thread or an IntentService.
Have you seen our IntentService tutorial, Using an IntentService to do background work?
We’re going to use OkHttp’s Asynchronous option where it takes care of running the internet connection on a separate thread.
Queue the request
We want the http request to execute on a worker thread so we use the OkHttp’s Call class’s enqueue() method:
Use enqueue() to download the image on a separate thread
enqueuer() schedules the request to be executed sometime in the future. Usually it runs immediately unless there are other requests in the queue.
There are two required methods, one of which is executed by the call back:
- onFailure() – the request failed to execute due to connectivity problems, timeouts or cancellation
- onResponse() – the http request was successfully received and a response returned by the server. Although a response was received, it doesn’t mean that your request was successful. For example the server may have returned a 404 response code (page not found). You’ll have to handle this when extracting the information from the response
What happens on failure?
onFailure() is called if there was a connectivity problem.
Remember that the request and response are executed on a worker thread. So you cannot use the result to directly update the main thread or UI (user interface).
We use a runnable to update the ImageView to display the failed.png image. We also set the isRequestProblem boolean to true (we’ll use it in the Activity’s lifecycle method, onResume(), to display the correct image when the device’s orientation is changed).
What happens on success?
onResponse() is called when the server successfully returns a response.
Note, receiving a response does not mean that the request was successful. All it means is that the server received your request and has responded to it. You will have to determine whether or not the response was successful for you.
We use the Response class’s isSuccessful() method to evaluate whether the response was successful (the returned status codes fall within 200 – 300) or not. If it wasn’t successful then we throw an exception.
Then we check whether the response status code is 200 (the SUCCESSFUL_DOWNLOAD constant).
If it is then we get an input stream from the response body, and use the BitmapFactory class’s decodeStream() method to convert it into a bitmap. The bitmap is then passed to our updateImage() method:
We use an if statement to evaluate the returned status code
If the status code is not 200 then we use a runnable to display the error image.
Update the image
Once again, remember that the request and response is executed on a worker thread. So you cannot use the result to directly update the main thread or UI (user interface).
Again we use a runnable to update the User Interface:
Our updateImage() method uses a runnable to update the ImageView
If the bitmap is not null then we display it in the image view. We also set the isImageDisplaying boolean to true. We’ll use this in onResume() to ensure that we display the downloaded image when the device’s orientation is changed.
If the bitmap is null then we simply display the ic_launcher icon in the ImageView.
Saving the instance state
Changing the device’s configuration, for example changing its orientation, destroys the activity. It is then recreated from scratch. All variables are reset when the activity is recreated.
We’d like to recreate the activity so that it displays the same image that was displaying before the activity was destroyed. The user shouldn’t be aware that the activity has been destroyed and recreated.
We use three booleans to indicate which image is showing:
- isRequestProblem – if true then the request problem image is showing
- isResponseProblem - if true then the response problem image is showing
- isImageDisplaying - if true then the downloaded image is showing
We use the onSaveInstanceState() method to save these booleans when the activity is destroyed. We then get their values back when onCreate() is executed to rebuild the activity.
We then check their values in the onResume() method and execute the appropriate code to display the correct image.
You may be interested in these tutorials:
So what’s with the getResponseDetails() method?
Well, it’s just a little extra, showing some of the Response class’s methods that we can use to get information out of the returned response.
Check out the OkHttp classes documentation
Have a look at some useful recipes that show you what you can do with OkHttp
If you’re interested in downloading lots of images, have a look at our Picasso tutorial where we show you how to use Square’s Picasso library to download images.
I hope that you have found this tutorial helpful.
This project was created using Android Studio.
Want to learn how to harness the power of third-party Api’s like Twitter, Youtube, Flickr, Imgur and thousands more? You can build the functionality of these apps directly into your apps, accessing their data, making your apps leap ahead of the competition.
We also briefly introduce you to Http, OkHttp, Api’s, Json and Picasso making it easy to understand as we work through the tutorial.
Check out our eBook package, Let your apps take a giant leap.