Eunice Obugyei

Kotlin Networking.jpg

As an Android developer, it's highly likely that you have heard about Kotlin and all it's awesomeness :). For those who haven't heard about it, Kotlin is a relatively new programming language created by JetBrains(developers of the intelliJ IDEA).

Kotlin is a statically-typed programming language that runs on the JVM(Java Virtual Machine). It can also be compiled to JavaScript source code. As amazing as Kotlin is, this is not an introduction to Kotlin tutorial. There's a bunch of those around. This tutorial utilizes Kotlin as a language to cover networking in Android. Most applications do not work in isolation but connect to online services to help better serve their users.

In this tutorial, you'll work on an application that connects to the GitHub API to retrieve a list public repositories In the process, we'll cover:

  • How to check your network connection status
  • How to perform network operations
  • Some open source libraries for making network operations

This tutorial assumes you're using Android Studio

final.png


Getting Started

Download and extract the starter project for this tutorial. Open the starter project in Android Studio by selecting Open an existing Android Studio project from the Quick Start menu:

quick_start_menu.png

Navigate to and select the starter project. Now let's explore some of the files in the project

Open Util.kt. This file contains package-level functions and properties. These can be called from any class in the same package as Util.kt

Next open the MainActivity.kt file. You will notice two things:

  1. Just like all the other files under the base package(com.andev.githubrepolist), MainActivity ends with a kt extension. This signifies that it is a kotlin file.
  2. Android Studio seem to recognize it as a text file. This is because Android Studio can only work with Kotlin after you've installed the Kotlin plugin. Let's go ahead and do that.

Installing The Kotlin Plugin

To install the plugin, Go to File | Settings | Plugins | Install JetBrains plugin...(on a Mac, Go to Android Studio | Preferences | Plugins | Install JetBrains plugin...)

Search for and select Kotlin from the resulting list. Click Install.

kotlin_install.png


When the download and installation is complete, click on the Restart Android Studio button and follow the prompts to restart Android Studio

With the Kotlin plugin successfully installed, the IDE can now recognize Kotlin files.

Configuring Kotlin in the project

Installing the Kotlin plugin gives the IDE the ability to work with Kotlin but your app still doesn't know how to handle code written in Kotlin.

To configure Kotlin in your project, Go to Tools | Kotlin | Configure Kotlin in Project

configure_kotlin.png

You are then prompted to choose the version of Kotlin. Select the plugin version(it is advisable to select the latest version. At the time of writing this tutorial, the current version is 1.0.6) and click OK.

select_kotlin_version.png

After the Kotlin configuration, the app's build.gradle files should be updated with the 'kotlin-stdlib' dependency and the 'kotlin-android' plugin declaration

Click on Sync Now to build the project. Build and run. The app currently shows a blank screen.

screenshot_1.png

Required Permissions

In order to perform network operations in Android, the app's manifest file must include some permissions: the INTERNET and ACCESS_NETWORK_STATE permissions.

The ACCESS_NETWORK_STATE permission, allows your application to check the network connectivity state of the device whiles the INTERNET permission allows your application to make network calls from the device.

Open manifests/AndroidManifest.xml and add the permission declarations just before the application tag:

            
                <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
                <uses-permission android:name="android.permission.INTERNET"/>
            
        

Before adding any code, you’ll need to configure Android Studio to automatically insert unambiguous import statements to save you from having to add each one manually.

Go to File | Settings | Editor | General | Auto Import(on a Mac, Go to Android Studio | Preferences | Editor | General | Auto Import)

Select the Add unambiguous imports on the fly checkbox and click OK.

Checking Network Connectivity

It is advisable to check the network connectivity state of the device before performing any network operations.

Open MainActivity.kt and add the function below to the class:

            
                private fun isNetworkConnected(): Boolean {
                    val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager// 1
                    val networkInfo = connectivityManager.activeNetworkInfo // 2
                    return networkInfo != null && networkInfo.isConnected // 3
                }
            
        

The isNetworkConnected() function checks if the device has an active internet connection by:

  1. Retrieving an instance of the ConnectivityManager class from the current application context. The ConnectivityManager class is simply your go to class if you need any information about the state of network connectivity. It can also be set up to report network connection changes to your application.
  2. Retrieving information about the current active network connection. This will be null if there's no network connection.
  3. And checking if the device is connected to an available network connection.

Since network operations can take some time, it is advisable to put up a progress screen during the process and use alerts to prompt the user for any actions you require of them. In this case, you will need to prompt the user to connect to a network if the device is not already connected to one.

First add the following import statement to the top of the file:

            
                import android.support.v7.app.AlertDialog
            
        

In the onCreate() function, replace the showListFragment(ArrayList<Repository/>()) line with the following lines of code:

            
                if (isNetworkConnected()) {
                    progressDialog = ProgressDialog(this)
                    progressDialog?.setMessage("Please wait...")
                    progressDialog?.setCancelable(false)
                    progressDialog?.show()

                    startDownload(GET_REPO_URL)
                } else {
                    AlertDialog.Builder(this).setTitle("No Internet Connection")
                    .setMessage("Please check your internet connection and try again")
                    .setPositiveButton(android.R.string.ok) { dialog, which -> }
                    .setIcon(android.R.drawable.ic_dialog_alert).show()
                }
            
        

The above lines of code displays a progress dialog and calls the startDownload() function if the device is connected to a network. If it isn't connected, it displays an alert to the user.

Build and run.

A network connected device will show a ProgressDialog:

screenshot_2.png

A device not connected to any network will show an alert prompting the user to check their connection:

screenshot_3.png


Performing Network Operations

You should avoid performing long running operations such as network calls on the UI thread. From Android 3.0 and above, performing network calls on the main UI thread will result in a NetworkOnMainThreadException being thrown.

The AsyncTask class allows you to perform background tasks and publish the results on the main UI thread without having to perform any thread manipulations.

Since AsyncTask is an abstract class, it must be subclassed to be used. Let's go ahead and create a new Kotlin class:

Select the package in which you want the class created and go to File | New | Kotlin File/Class:

create_kotlin_class.png

In the New Kotlin Class\File dialog, enter DownloadRepositoryTask as the name of the class and select Class in the Kind dropdown and click OK:

create_kotlin_class_2.png

Replace the class declaration with the following lines of code:

            
                class DownloadRepositoryTask : AsyncTask<String, Void, String>() {

                    override fun doInBackground(vararg params: String): String? {

                        return null
                    }

                    override fun onPostExecute(result: String) {

                    }

                }
            
        

A few things to note here:

  1. Just like all the classes you've seen in the app so far, this class does not begin with the public keyword. This is because in Kotlin, the default visibility modifier is public.
  2. We used :NameOfParentClass()(instead of extends NameOfParentClass in Java) to declare DownloadRepositoryTask as a subclass of AsyncTask
  3. The doInBackground() function is where the background task is performed.
  4. When the task is complete, the onPostExecute() function is called with the results.

Open MainActivity.kt and add the following code to the startDownload() function:

            
                DownloadRepositoryTask().execute(downloadUrl)
            
        

This calls an instance of the DownloadRepositoryTask class, with the url to download from as it's parameter.

Connecting to the API and Retrieving the repositories

Add the following function to the DownloadRepositoryTask class:

            
                @Throws(IOException::class)
                private fun downloadData(urlString: String): String {
                    var inputStream: InputStream? = null
                    try {
                        val url = URL(urlString)
                        val conn = url.openConnection() as HttpURLConnection
                        conn.requestMethod = "GET"
                        conn.connect()

                        inputStream = conn.inputStream
                        return inputStream.bufferedReader().use { it.readText() }
                    } finally {
                        if (inputStream != null) {
                            inputStream.close()
                        }
                    }
                }
            
        

The above function creates, opens a connection to the resource referenced by the specified URL and returns the response as a string

Now replace the return statement in doInBackground() with the following lines of code:

            
                try {
                    return downloadData(params[0]);
                } catch (IOException e) {
                    e.printStackTrace();
                    return null;
                }
            
        

When the data download is complete, the result has to be returned to the Activity that made the call. This can be done by setting up the Activity as a Listener for the download complete event. To do this, you need to create an interface that declares the function to call when the download is complete.

To create a Kotlin interface, select the package in which you want the interface created and go to File | New | Kotlin File/Class

In the New Kotlin Class\File dialog, enter TaskCompleteListener as the name of the interface, select Interface in the Kind dropdown and click OK:

create_kotlin_interface.png 

Add the following function declaration to the TaskCompleteListener class:

            
                fun downloadComplete(repositories: ArrayList<Repository>)
            
        

Now open MainActivity.kt and let it implement the TaskCompleteListener interface.

The MainActivity class declaration should now look like this:

            
                class MainActivity : AppCompatActivity(), TaskCompleteListener
            
        

Next, implement the downloadComplete() function declared in TaskCompleteListener by adding the function below to MainActivity:

            
                override fun downloadComplete(repositories: ArrayList<Repository<) {

                }
            
        

Open DownloadRepositoryTask.kt

Now we have to declare a TaskCompleteListener property and add a constructor which takes a TaskCompleteListener parameter and sets the declared property. In Kotlin this can be done by adding (var taskCompleteListener: TaskCompleteListener?) to the end of the class name in the class declaration.

Your DownloadRepositoryTask class declaration should now look like this:

            
                class DownloadRepositoryTask(var taskCompleteListener: TaskCompleteListener?) : AsyncTask<String, Void, String>()
            
        

The above line of code declares a class with a primary constructor that takes a TaskCompleteListener parameter, declares and initializes it as property.

Next add the following lines of code to the onPostExecute() function:

            
                try {
                    taskCompleteListener?.downloadComplete(retrieveRepositoriesFromResponse(result))
                } catch (e: JSONException) {
                    e.printStackTrace()
                }
            
        

This utilizes the package-level function declared in the Utils.kt file to convert and pass the results to the TaskCompleteListener using downloadComplete()

Open MainActivity.kt

Replace the code in startDownload() with the following line of code:

            
                DownloadRepositoryTask(this).execute(downloadUrl)
            
        

Next, add the following lines of code to the downloadComplete() function:

            
                showListFragment(repositories);
                if (progressDialog != null) {
                    progressDialog?.hide();
                }
            
        

The above code receives a list of Repository objects, calls showListFragment() to display them to the user and hide the progress dialog.

Now build and run

screenshot_4.png

That's it. You have created an app that connects to the GitHub API and retrieves and displays a list of public repositories.

Open Source libraries

As you may have noticed, performing network operations in Android can be a little bit of a hassle. From opening and closing connections to retrieving and converting InputStreams, this can be a lot to do.

That's where open source libraries come into play. There are a number of great open source libraries that have been designed to make performing network operations in Android very simple. We'll take a look at three of the most popular ones:

OkHttp

OkHttp is an efficient Java HTTP library which supports both synchronous and asynchronous network calls. It works with Android 2.3 and above. It handles opening and closing of connections and retrieving and converting the InputStream to string. OkHttp is built as a Java library, not an Android library so it does not handle the Android Framework limitation that permits views to be only updated on the main UI thread. To update views, you will need to use the runOnUiThread() method provided in the Android Activity super class.

OkHttp is very simple and easy to use.

You start by adding it as dependency to your project.

Open build.gradle and add the following lines of code to the dependencies tag:

            
                compile 'com.squareup.okhttp3:okhttp:3.6.0'
            
        

Now open MainActivity.kt and add the function below to the class:

            
                private fun makeRequestWithOkHttp(url: String) {
                    val client = OkHttpClient()
                    val request = okhttp3.Request.Builder().url(url).build() // 1

                    client.newCall(request).enqueue(object : okhttp3.Callback { // 2
                        override fun onFailure(call: okhttp3.Call, e: IOException) {
                            e.printStackTrace()
                        }

                        @Throws(IOException::class)
                        override fun onResponse(call: okhttp3.Call, response: okhttp3.Response) {
                            val result = response.body().string() // 3

                            this@MainActivity.runOnUiThread {
                                try {
                                    downloadComplete(retrieveRepositoriesFromResponse(result)) // 4
                                } catch (e: JSONException) {
                                    e.printStackTrace()
                                }
                            }
                        }
                    })
                }
            
        

The above lines of code:

  1. Builds an OkHttpClient request with the url passed to it
  2. Queues the request
  3. Retrieves the response as a string.
  4. Converts and passes the results to the ownloadComplete() function

Now replace the code in the startDownload() method with this:

            
                makeRequestWithOkHttp(downloadUrl)
            
        

Build and run.

screenshot_4.png

Volley

Volley is an Android HTTP library for making network calls in a faster and easier way. Unlike OkHttp, Volley works with Android 1.6 and above. It also does not require any extra work with updating views.

To use Volley, first add it as a dependency to the project.

Open build.gradle and add the following lines of code to the dependencies tag:

            
                compile 'com.android.volley:volley:1.0.0'
            
        

Now open MainActivity.kt and add the function below to the class:

            
                private fun makeRequestWithVolley(url: String) {

                    val queue = Volley.newRequestQueue(this) // 1

                    val stringRequest = StringRequest(Request.Method.GET, url, // 2
                    Response.Listener<kotlin.String> { response ->
                        try {
                            downloadComplete(retrieveRepositoriesFromResponse(response)) // 3
                        } catch (e: JSONException) {
                            e.printStackTrace()
                        }
                    }, Response.ErrorListener { })
                    queue.add(stringRequest) // 3

                }
            
        

The above lines of code:

  1. Creates a new Volley request queue
  2. Request a string response from the provided URL.
  3. Converts and passes the results to the downloadComplete() function
  4. Add the request to the request queue.

Now replace the code in the startDownload() method with this:

            
                makeRequestWithVolley(downloadUrl)
            
        

Build and run.

screenshot_4.png

Retrofit

Retrofit is an Android and Java library which is great for retrieving and uploading structured data such as JSON and XML. Retrofit makes HTTP requests using OkHttp.

Unlike Volley and OkHttp, Retrofit provides a number of libraries that does the data conversion for you:

  • Gson: com.squareup.retrofit2:converter-gson
  • Jackson: com.squareup.retrofit2:converter-jackson
  • Moshi: com.squareup.retrofit2:converter-moshi
  • Protobuf: com.squareup.retrofit2:converter-protobuf
  • Wire: com.squareup.retrofit2:converter-wire
  • Simple XML: com.squareup.retrofit2:converter-simplexml
  • Scalars (primitives, boxed, and String): com.squareup.retrofit2:converter-scalars

To use Retrofit, first add the Retrofit and data conversion dependencies to the project(In our case we'll use gson)

Open build.gradle and add the following lines of code to the dependencies tag:

            
                compile 'com.squareup.retrofit2:retrofit:2.1.0'
                compile 'com.squareup.retrofit2:converter-gson:2.1.0'
            
        

Then create a new interface and name it RetrofitAPI; this will define the HTTP operations.

Now create a new Kotlin interface which will define the HTTP operations. Call it RetrofitAPI

Add the following code to the RetrofitAPI interface:

            
                @GET("/repositories")
                fun retrieveRepositories(): Call<ArrayList<Repository>>
            
        

The above specifies the request function and the URL for the request call.

Next open MainActivity.kt and add the function below to the class:

            
                private fun makeRetrofitCalls() {
                    val retrofit = Retrofit.Builder().baseUrl("https://api.github.com") // 1
                    .addConverterFactory(GsonConverterFactory.create()) // 2
                    .build()

                    val retrofitAPI = retrofit.create<RetrofitAPI>(RetrofitAPI::class.java)  // 3

                    val call = retrofitAPI.retrieveRepositories()  // 4

                    call.enqueue(object : Callback<ArrayList<Repository>> { // 5
                        override fun onResponse(call: Call<ArrayList<Repository>>,
                                                response: retrofit2.Response<ArrayList<Repository>>) {
                            downloadComplete(response.body()) // 6
                        }

                        override fun onFailure(call: Call<ArrayList<Repository>>, t: Throwable) {
                            Toast.makeText(this@MainActivity, t.message, Toast.LENGTH_SHORT).show()
                        }
                    })
                }
            
        

The above lines of code:

  1. Sets the base URL for the resource
  2. Adds a GsonConverterFactory instance as the converter to deserialize the response.
  3. Generates an implementation of the RetrofitAPI.
  4. Generates the request call.
  5. Queues the request call.
  6. Passes the results to downloadComplete().

Now replace the code in the startDownload() method with this:

            
                makeRetrofitCalls()
            
        

Build and run.

screenshot_4.png

Hope this tutorial has been helpful. You can check out the full source code for this tutorial on GitHub.

About the Author
Eunice Obugyei

Eunice Obugyei
DreamOVal

Eunice is a Software Engineer working at DreamOval and an Android Tutorial Writer on https://www.raywenderlich.com. You can follow her on Twitter as @euniceadu2 or onher blog.

 

 

 

 

Related Search Term(s): Kotlin, Tutorials

Create, Design, Develop and Connect at AnDevCon D.C. 2017!

Thoughts? Leave a comment: