Networking in Android

Networking in Android | Network call | API call
22 November 2023
1
Share

Networking in Android involves communicating with remote servers or APIs to fetch data, send data, or perform other operations over the internet.

Android Networking in Nutshell

In a nutshell, android networking or any networking works in the following way:

  • Request— Make an HTTP request to an URL (called as endpoint) with proper headers generally with Authorisation Key if required.
  • Response — The Request will return a response which can be error or success. In the case of success, the response will contain the contents of the endpoint (generally they are in JSON format).

Refer to this for the detailed working of networking:  client-server-model-how-it-works

  • Parse & Store — We will parse this JSON and get the required values and store them in our data class.

Refer to this : JSON parsing

There are several ways to handle networking in Android:

HttpClient and HttpUrlConnection (Deprecated from API level 22)

This is a basic and traditional way to make HTTP requests in Android.

Performing a GET Request using HttpURLConnection:

import android.os.AsyncTask
import java.io.BufferedReader
import java.io.InputStreamReader
import java.lang.Exception
import java.net.HttpURLConnection
import java.net.URL

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

    override fun doInBackground(vararg params: String): String {
        var result = ""
        var urlConnection: HttpURLConnection? = null
        try {
            val url = URL(params[0])
            urlConnection = url.openConnection() as HttpURLConnection
            val inputStream = urlConnection.inputStream
            val reader = BufferedReader(InputStreamReader(inputStream))
            val stringBuilder = StringBuilder()
            var line: String?
            while (reader.readLine().also { line = it } != null) {
                stringBuilder.append(line).append("\n")
            }
            result = stringBuilder.toString()
        } catch (e: Exception) {
            e.printStackTrace()
        } finally {
            urlConnection?.disconnect()
        }
        return result
    }

    override fun onPostExecute(result: String) {
        // Handle the result here
        // This method runs on the UI thread
    }
}

To use this NetworkTask, execute it like this:

val url = "https://api.example.com/data"
val networkTask = NetworkTask()
networkTask.execute(url)

However, using AsyncTask for network operations is a more traditional approach and might not be the best choice for larger applications or complex use cases due to potential memory leaks and lifecycle issues.

These were traditional ways to make HTTP requests, but they are now deprecated. It’s recommended to use newer methods like Volley, Retrofit, or OkHttp for networking tasks.

Limitations

Complexity and Boilerplate Code: Making simple HTTP requests using HttpURLConnection often involves writing a lot of boilerplate code. This can lead to increased complexity, reduced readability, and higher chances of errors.

Low-Level API: HttpURLConnection is a low-level API, which means you have to handle many details manually, such as connection management, request headers, timeouts, error handling, and parsing responses.

Poor Performance: In certain scenarios, HttpURLConnection may exhibit poorer performance compared to other libraries like OkHttp. OkHttp is optimized for performance, caching, and managing connections efficiently.

Limited Features: It lacks some advanced features provided by modern networking libraries, such as automatic request cancellation, built-in support for caching, interceptors, and network traffic monitoring.

Maintenance and Compatibility: With Android’s evolving APIs, maintaining compatibility and handling deprecation of certain methods in HttpURLConnection might become an issue over time.

Due to these limitations, many developers prefer using OkHttp or Retrofit (which uses OkHttp under the hood) for handling network operations in Android. OkHttp simplifies networking tasks, provides a cleaner API, better performance, and additional features, making it a preferred choice for many Android developers. Retrofit, on the other hand, further abstracts and simplifies the networking layer by providing a high-level interface for defining RESTful APIs.

Retrofit for networking in Android

Using Retrofit for networking in Android is a popular choice due to its simplicity, flexibility, and strong integration with Kotlin’s coroutine support. Retrofit simplifies the process of making HTTP requests and processing responses. Here’s a basic guide on how to use Retrofit:

1.Add Dependencies:

Update your build.gradle file to include the Retrofit and Gson dependencies:

dependencies {
    // Retrofit for handling API requests
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0' // Gson converter for JSON serialization/deserialization
    
    // For coroutines support
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2'
}

2.Model Classes:

Create a data class to represent the structure of the data you expect to receive from the API:

data class Post(
    val userId: Int,
    val id: Int,
    val title: String,
    val body: String
)

3.Create Retrofit Interface:

Define an interface that specifies the API endpoints and their associated HTTP methods:

import retrofit2.http.GET
import retrofit2.http.Path

interface ApiService {
    @GET("endpoint/{id}")
    suspend fun getData(@Path("id") id: Int): YourResponseModel // Change YourResponseModel to your actual response model
}

4.Create Retrofit Instance:

Create a Retrofit instance that will serve as the entry point for API calls. Set up the base URL and specify converters.

object RetrofitClient {
    private const val BASE_URL = " https://jsonplaceholder.typicode.com/ " // Replace with your base URL
    
    private val retrofit: Retrofit = Retrofit.Builder()
        .baseUrl(BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .build()

    val apiService: ApiService = retrofit.create(ApiService::class.java)
}

5.Make Network Requests:

Now, you can use the created ApiService to make network requests:

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch

// Inside your activity or fragment
val service = RetrofitClient.create()

GlobalScope.launch(Dispatchers.IO) {
    try {
        val response = service.getData(1) // Pass parameters as needed
        // Process the response on the main(UI) thread if needed
        // Example: Update UI with response data
        GlobalScope.launch(Dispatchers.Main) {
            // Update UI
        }
    } catch (e: Exception) {
        // Handle exceptions
    }
}

Remember to handle exceptions appropriately and consider using error handling mechanisms like try-catch blocks or Kotlin’s runCatching for better error management.

This basic setup demonstrates how Retrofit simplifies the process of making network requests in Android using Kotlin and allows you to focus more on defining APIs and handling responses. Adjust the model classes and API endpoints according to your specific use case.

Check out this real-time example of retrofit library Weather App in Android using Retrofit.

Volley

Volley is a networking library provided by Google. It simplifies the process of making network requests and is efficient for small requests. It manages the processing and caching of network requests. Here’s an example of how you can use Volley in Kotlin for networking:

  1. First, add the Volley dependency to your build.gradle file
dependencies {
    implementation 'com.android.volley:volley:1.2.1'
}

2. Now, let’s create a simple network request using Volley to perform a GET request:

import android.os.Bundle
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import com.android.volley.Request
import com.android.volley.Response
import com.android.volley.toolbox.JsonObjectRequest
import com.android.volley.toolbox.Volley
import org.json.JSONObject

class MainActivity : AppCompatActivity() {

    private lateinit var resultTextView: TextView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        resultTextView = findViewById(R.id.resultTextView)

        // Instantiate the RequestQueue using Volley
        val queue = Volley.newRequestQueue(this)

        val url = "https://jsonplaceholder.typicode.com/posts/1" // Sample API endpoint

        // Request a JSONObject response from the provided URL
        val jsonObjectRequest = JsonObjectRequest(
            Request.Method.GET, url, null,
            Response.Listener<JSONObject> { response ->
                // Display the response
                resultTextView.text = "Response: $response"
            },
            Response.ErrorListener { error ->
                // Handle errors
                resultTextView.text = "Error: ${error.message}"
            }
        )

        // Add the request to the RequestQueue
        queue.add(jsonObjectRequest)
    }
}

In this example:

  • We create a RequestQueue using Volley.newRequestQueue(this) to manage network requests.
  • We define the URL endpoint for the GET request.
  • We create a JsonObjectRequest using JsonObjectRequest() with the appropriate request type, URL, and callbacks for success and failure.
  • The success callback (Response.Listener) updates the resultTextView with the response.
  • The error callback (Response.ErrorListener) handles any errors that occur during the request.
  • Remember to handle the necessary permissions in your AndroidManifest.xml if your app requires internet access

Limitation:

No Active Development: Google has officially deprecated Volley, indicating that there won’t be active development or new features added to the library. While it’s still functional and used in many apps, its future support might be limited.

Complex Customization: Although Volley simplifies basic network operations, customizing requests or handling complex scenarios might require more effort compared to other libraries. It lacks certain advanced functionalities found in newer libraries like Retrofit.

Memory Consumption: Volley keeps an extensive cache of responses in memory, which can lead to increased memory consumption, especially when handling large responses or numerous requests.

SSL/TLS Configuration: Volley might have limitations in configuring SSL/TLS settings or handling certain SSL configurations, which could be crucial for secure connections to specific servers.

Deprecated Components: As the library is deprecated, certain components or functionalities within Volley might be marked as deprecated, leading to potential concerns when targeting newer Android versions.

Handling Large File Downloads: For large file downloads, Volley might not be the most efficient choice as it loads the entire response into memory, which can cause issues with memory consumption for large files.

Given these limitations and its deprecated status, developers often explore alternatives like Retrofit coupled with OkHttp for robust networking in Android applications. Retrofit simplifies API integration by providing a higher level of abstraction and customization options while utilizing OkHttp for networking operations. It’s advisable to consider these alternatives for long-term support and ease of maintenance in your Android projects.

Volley simplifies many aspects of networking in Android by handling request queuing, caching, and threading for you. However, note that Google announced the deprecation of Volley in favor of newer networking libraries like OkHttp and Retrofit. While Volley is still functional and widely used, consider exploring other options for networking in Android for long-term support and compatibility.

Conclusion(Which should be used)

  • For simple, straightforward API calls where you want to avoid additional dependencies, HttpURLConnection might be suitable.
  • If you need more advanced features, strong community support, and ease of use, Retrofit is a robust choice, especially for RESTful APIs.
  • Volley, while deprecated, might still be a feasible option for projects that already use it, but it might not be the best choice for new projects considering its limited future support.
  • Ultimately, the choice depends on the project’s specific requirements, complexity, and the developer’s familiarity with the library. For most cases involving RESTful APIs and a balance between simplicity and functionality, Retrofit paired with OkHttp tends to be a popular and reliable choice in the Android ecosystem.