Android Networking: Fundamentals

Sep 6 2022 · Kotlin 1.6, Android 12, Android Studio Chipmunk | 2021.2.1 Patch 1

Part 1: Learn About HTTP & Threading

06. Challenge: Use HttpUrlConnection

Episode complete

Play next episode

Next
About this episode

Leave a rating/review

See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 05. Parse Data as JSON Next episode: 07. Parse JSON Data

Get immediate access to this and 4,000+ other videos and books.

Take your career further with a Kodeco Personal Plan. With unlimited access to over 40+ books and 4,000+ professional videos in a single subscription, it's simply the best investment you can make in your development career.

Learn more Already a subscriber? Sign in.

Notes: 06. Challenge: Use HttpUrlConnection

The student materials have been reviewed and are updated as of July 2022.

Transcript: 06. Challenge: Use HttpUrlConnection

The best way to make sure you’ve got a good understanding of creating requests and parsing the data is to pratice it on an example. In this challenge, you have to do two things.

The first thing is to create another API request, to add notes. You can use the documentation provided in each of the project folders, to form the endpoint & the data you need to send in the body. And the second thing is implement the JSON parsing, using the knowledge you’ve gained in the previous episode.

One hint: When adding the requestProperties to the HttpURLConnection, add the header “Authorization”, and have it set to the token you received from the server to authenticate yourself.

That’s it! Now pause the video, and solve the challenge! Then once you’re done, unpause the video, and compare the two solutions! Good luck! :]

To make it easier to enter the app, open the LoginActivity. Now add the following code, to the onCreate() function:

if (App.getToken().isNotBlank()) {
  startActivity(MainActivity.getIntent(this))
}

This will check the token, and if it exists in the preferences, you won’t have to log in again. Now head over to the AddTaskDialogFragment.kt, and add the networkStatusChecker to the top of the class, like before:

private val networkStatusChecker by lazy {
  NetworkStatusChecker(activity?.getSystemService(ConnectivityManager::class.java))
}

Then add the checks as before, to the API call:

networkStatusChecker.performIfConnectedToInternet {
  activity?.runOnUiThread {
    ...
  }
}

This is pretty usual and you will do this for all the calls. Finally, open the RemoteApi, and the addTask function, and add the following, remember, you can copy most of this base setup code from the login or the register calls:

Thread(Runnable {

}).start()

Just like before, you’re starting a new thread for the request. Next, add the base configuration, and the endpoint path:

Thread(Runnable {
  val connection = URL("$BASE_URL/api/note").openConnection() as HttpURLConnection
  connection.requestMethod = "POST"
  connection.setRequestProperty("Content-Type", "application/json")
  connection.setRequestProperty("Accept", "application/json")
  connection.setRequestProperty("Authorization", App.getToken())
  connection.readTimeout = 10000
  connection.connectTimeout = 10000
  connection.doOutput = true
  connection.doInput = true

  connection.disconnect()
}).start()

Also make sure to add the Authorization token for the request, to be able to create a new task. And remember to disconnect the connection.

connection.setRequestProperty("Authorization", App.getToken())

In this call, you have to format the three properties for adding a new note into JSON, do this the following way:

Thread(Runnable {
  val connection = URL("$BASE_URL/api/note").openConnection() as HttpURLConnection
  connection.requestMethod = "POST"
  connection.setRequestProperty("Content-Type", "application/json")
  connection.setRequestProperty("Accept", "application/json")
  connection.setRequestProperty("Authorization", App.getToken())
  connection.readTimeout = 10000
  connection.connectTimeout = 10000
  connection.doOutput = true
  connection.doInput = true

  val request = JSONObject()
  request.put("title", addTaskRequest.title)
  request.put("content", addTaskRequest.content)
  request.put("taskPriority", addTaskRequest.taskPriority)
  
  connection.disconnect()
}).start()

Finally, write the data to the server, and consume the response:

Thread(Runnable {
  val connection = URL("$BASE_URL/api/note").openConnection() as HttpURLConnection
  connection.requestMethod = "POST"
  connection.setRequestProperty("Content-Type", "application/json")
  connection.setRequestProperty("Accept", "application/json")
  connection.setRequestProperty("Authorization", App.getToken())
  connection.readTimeout = 10000
  connection.connectTimeout = 10000
  connection.doOutput = true
  connection.doInput = true

  val request = JSONObject()
  request.put("title", addTaskRequest.title)
  request.put("content", addTaskRequest.content)
  request.put("taskPriority", addTaskRequest.taskPriority)

  try {
    connection.outputStream.use { outputStream ->
      outputStream.write(request.toString().toByteArray())
    }

    val reader = InputStreamReader(connection.inputStream)

    reader.use { input ->
      val response = StringBuilder()
      val bufferedReader = BufferedReader(input)

      bufferedReader.useLines { lines ->
        lines.forEach {
          response.append(it.trim())
        }
      }
    }
  } catch (error: Throwable) {
  }

  connection.disconnect()
}).start()

Now once you’ve got the entire response in JSONObject, create a task from it:

Thread(Runnable {
  val connection = URL("$BASE_URL/api/note").openConnection() as HttpURLConnection
  connection.requestMethod = "POST"
  connection.setRequestProperty("Content-Type", "application/json")
  connection.setRequestProperty("Accept", "application/json")
  connection.setRequestProperty("Authorization", App.getToken())
  connection.readTimeout = 10000
  connection.connectTimeout = 10000
  connection.doOutput = true
  connection.doInput = true

  val request = JSONObject()
  request.put("title", addTaskRequest.title)
  request.put("content", addTaskRequest.content)
  request.put("taskPriority", addTaskRequest.taskPriority)

  try {
    connection.outputStream.use { outputStream ->
      outputStream.write(request.toString().toByteArray())
    }

    val reader = InputStreamReader(connection.inputStream)

    reader.use { input ->
      val response = StringBuilder()
      val bufferedReader = BufferedReader(input)

      bufferedReader.useLines { lines ->
        lines.forEach {
          response.append(it.trim())
        }
      }

      val jsonObject = JSONObject(response.toString())

      val task = Task(
          jsonObject.getString("id"),
          jsonObject.getString("title"),
          jsonObject.getString("content"),
          jsonObject.getBoolean("isCompleted"),
          jsonObject.getInt("taskPriority")
      )

      onTaskCreated(task, null)
    }
  } catch (error: Throwable) {
    onTaskCreated(null, error)
  }

  connection.disconnect()
}).start()

And that’s all! Run the app, and create a new note! :]

Good job! With this challenge completed, you have a good understanding of parsing and creating requests, using the HttpURLConnection and JSONObjects! But it was a bit cumbersome to do it all manually! In the next episode, you’ll see how to do it with a little help from a library called GSON! :]