0

I am trying to learn how to make REST calls from Kotlin using Retrofit. I have followed the example on Loopcupcakes.com which works and writes the result nicely to the logcat. That's all good and I (broadly) understand what it's doing. I'm now trying to adapt this to use my API, but my running-before-I-can-walk approach is giving me problems in the implementation.

My API works fine, and returns a result in postman

{
    "APIResult": [
        {
            "id": 200,
            "status_message": "Success",
            "developer_message": "",
            "user_message": "Success",
            "suppliers": [
                {
                    "supplier_name": "Supplier 1",
                    "tariff_name": "Variable 1",
                    "tariff_start_date": "2021-04-01"                        
                },
                {
                    "supplier_name": "Supplier 2",
                    "tariff_name": "Fixed",
                    "tariff_start_date": "2021-05-01"                        
                }
            ]
        }
    ]
}

The call in Kotlin doesn't return an error, but logcat displays D/TAG_: null

I have the gradle and the manifest right as the original code was working. This is my code:

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import retrofit2.http.GET

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
            
        val service = Retrofit.Builder()
            .baseUrl("https://api.domain.com/")
            .addConverterFactory(MoshiConverterFactory.create())
            .build()
            .create(CurrentSupplier::class.java)

            service.getSupplier().enqueue(object : Callback<SupplierResponse> {

            override fun onFailure(call: Call<SupplierResponse>, t: Throwable) {
                Log.d("TAG_", "An error happened!")
                t.printStackTrace()
            }

            override fun onResponse(call: Call<SupplierResponse>, response: Response<SupplierResponse>) {
                /* This will print the response of the network call to the Logcat */
                Log.d("TAG_", response.body().toString())
            }
        })
    }
}

data class SupplierResponse(val results: List<Supplier>)
data class Supplier(val id: Int)//, val tariff_name: String)

interface CurrentSupplier {
    @GET("/supplier?key=xxx&ipaddress=1.1.1.1&operation=current")
    fun getSupplier(): Call<SupplierResponse>
}

So, my question is, how do I configure the interface and/or data classes to get to the supplier name and tariff name elements?

Tim Foster
  • 149
  • 1
  • 11

3 Answers3

0

try remove the first "/" on getSupplier() of interface CurrentSupplier

If you want to have more informations about retrofit call you can use logging interceptor Logging with Retrofit 2

Rémy
  • 313
  • 3
  • 17
0

I think SupplierResponse does not match the Call 's return type. You can replace SupplierResponse by String and log response . If it isn't null, you have to change SupplierResponse.

Dharman
  • 30,962
  • 25
  • 85
  • 135
0

Your BASE_URL is as follows

https://api.domain.com/

Now coming to your interface call which is this

 @GET("/supplier?key=xxx&ipaddress=1.1.1.1&operation=current")

I believe the end URL becomes like this

https://api.domain.com//supplier?key=xxx&ipaddress=1.1.1.1&operation=current

Which is not the right domain I believe. So you can get rid of the extra / and you should be good to go.

che10
  • 2,176
  • 2
  • 4
  • 11
  • Yes, you're right. Thank you, it does indeed add double forward slashes. My bad! It still doesn't return the elements though. How do I map id, developer_msg and suppliers/supplier_name? I'm trying to implement the logging interceptor suggested by @Remy but I'm struggling to get that working too (complete newbie, sorry!) – Tim Foster Jun 04 '21 at 12:52
  • The mapping would be done by Moshi and you are already using, it shall parse your JSON response to your data class that you have made. – che10 Jun 04 '21 at 13:08
  • For adding OkHttp, you would need to add its dependency in your `build.gradle` then with a simple line like this you can create its client `private val httpClient = OkHttpClient.Builder().build()` and assign it to Retrofit as `.client(httpClient)` simply where you are assigning Moshi and other stuff. – che10 Jun 04 '21 at 13:10
  • Ah ok. Cool. Thanks @Che10. I can see that the call is being made and returned now as I'm seeing the raw response in the logcat. Can someone help me define the supplier class so that it gets returned to there properly. Am I right in assuming my APIResult is what's causing the problem (APIResult/id and APIResult/suppliers/supplier_name)? – Tim Foster Jun 04 '21 at 13:31
  • There is an extension in Android Studio @TimFoster which helps you generate data class based off JSON response you provide it and beside that is a good value to assign them default values too. Here is the link for the [plugin](https://plugins.jetbrains.com/plugin/9960-json-to-kotlin-class-jsontokotlinclass-) – che10 Jun 04 '21 at 13:34
  • Perfect. Thank you @che10. It's working exactly as you describe. Thank you for your help with this. – Tim Foster Jun 04 '21 at 15:52