I’m developing an Android application that uses Retrofit to call a model hosted on Render. The endpoint is supposed to accept a request with a state and a year, and return a JSON object containing predicted rainfall data.
Here’s an example of a typical JSON response:
{
"predicted_rainfall": {
"APR": 124.20799999999997,
"AUG": 358.282,
"DEC": 68.95199999999994,
"FEB": 27.997999999999966,
"JAN": 18.76000000000003,
"JUL": 911.7139999999999,
"JUN": 666.5559999999996,
"MAR": 44.099999999999994,
"MAY": 177.19000000000023,
"NOV": 259.6499999999997,
"OCT": 305.5620000000003,
"SEP": 296.3400000000001
},
"state": "KERALA",
"year": "1901"
}
The endpoint is "https://rainfallpredictionmodel.onrender.com/predict/rainfall"
.
I created a Retrofit setup to call this endpoint, but it always fails with an error stating that it “failed to connect.” Initially, I used Volley but faced the same issue, prompting the switch to Retrofit.
Here’s the code for the Retrofit setup:
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.EditText
import android.widget.Toast
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import okhttp3.OkHttpClient
import org.json.JSONObject
import java.util.concurrent.TimeUnit
class BottomSheetRainfall : BottomSheetDialogFragment() {
private val TAG = "RainfallFragment"
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_bottom_sheet_rainfall, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val submitButton = view.findViewById<Button>(R.id.submit_rainfall)
val stateNameEditText = view.findViewById<EditText>(R.id.state_name)
val yearEditText = view.findViewById<EditText>(R.id.year)
val okHttpClient = OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS) // Increased connection timeout
.readTimeout(30, TimeUnit.SECONDS) // Increased read timeout
.writeTimeout(30, TimeUnit.SECONDS) // Increased write timeout
.build()
val retrofit = Retrofit.Builder()
.baseUrl("https://rainfallpredictionmodel.onrender.com/")
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build()
val rainfallService = retrofit.create(RainfallService::class.java)
submitButton.setOnClickListener {
val state = stateNameEditText.text.toString().uppercase()
val year = yearEditText.text.toString()
if (state.isNotEmpty() && year isNotEmpty()) {
val request = RainfallRequest(state, year)
rainfallService.predictRainfall(request).enqueue(object : Callback<RainfallResponse> {
override fun onResponse(
call: Call<RainfallResponse>,
response: Response<RainfallResponse>
) {
if (response.isSuccessful) {
val predictedRainfall = response.body()?.predicted_rainfall ?: emptyMap()
Toast.makeText(
requireContext(),
"Rainfall data retrieved successfully",
Toast.LENGTH_SHORT
).show()
} else {
Toast.makeText(
requireContext(),
"Error: ${response.message()}",
Toast.LENGTH_SHORT
).show()
}
}
override fun onFailure(call: Call<RainfallResponse>, t: Throwable) {
Log.e(TAG, "Error during API call", t)
Toast.makeText(requireContext(), "Error: ${t.localizedMessage}", Toast.LENGTH_SHORT).show()
}
})
} else {
Toast.makeText(requireContext(), "Please enter both state and year", Toast.LENGTH_SHORT).show()
}
}
}
}
The RainfallService
interface looks like this:
package com.example.safenet
import retrofit2.Call
import retrofit2.http.Body
import retrofit2.http.POST
interface RainfallService {
@POST("predict/rainfall")
fun predictRainfall(@Body request: RainfallRequest): Call<RainfallResponse>
}
And here are the data classes for the request and response:
package com.example.safenet
data class RainfallRequest(val state: String, val year: String)
data class RainfallResponse(val predicted_rainfall: Map<String, Double>)
Despite this setup, I keep getting the following error: “Failed to connect to https://rainfallpredictionmodel.onrender.com/predict/rainfall
.” The same error occurs with both Retrofit and Volley. I would appreciate any advice on resolving this issue.