How to get data with passing parameter in android retrofit kotlin - kotlin

I want to pass String parameter to the interface and get String data processed with String I passed.
But I can't response.isSuccessful == true.
"/danmun/m" is get one String parameter and return String data.
How can I get the processed String data which I passed.
interface Danmun_processing {
#GET("http://118.67.123.8/danmun/m")
fun getDataParam(#Query("param1") param1 : String): Call<String>
}
val danmunProcessing = retrofit.create(Danmun_processing::class.java)
val sentence = "sample string data"
danmunProcessing.getDataParam(sentence).enqueue(object : Callback<String> {
override fun onResponse(
call: Call<String>,
response: Response<String>
) {
if(response.isSuccessful) {
}
else {
}
}
override fun onFailure(call: Call<String>, t: Throwable) {
}
})
I want to get the processed String data with using data I passed.

Related

How to leave json object as raw string in Moshi

I want be able to save json object as raw json String. I've already have solution wit JSONObject, but it seems a bit redundant. Is there any way to get json string from reader?
class ObjectAsStringFactory : JsonAdapter.Factory {
override fun create(
type: Type,
annotations: MutableSet<out Annotation>,
moshi: Moshi
): JsonAdapter<*>? {
val delegateAnnotations = Types.nextAnnotations(annotations, ObjectAsString::class.java)
?: return null
if (Types.getRawType(type) !== String::class.java) {
throw IllegalArgumentException("#ObjectAsString requires the type to be String. Found this type: $type")
}
val delegateAdapter: JsonAdapter<String?> = moshi.adapter(type, delegateAnnotations)
return ObjectAsStringAdapter(delegateAdapter)
}
class ObjectAsStringAdapter(private val wrapped: JsonAdapter<String?>) : JsonAdapter<String>() {
override fun fromJson(reader: JsonReader): String? {
return (reader.readJsonValue() as? Map<*, *>)?.let { data ->
try {
JSONObject(data).toString()
} catch (e: JSONException) {
return null
}
}
}
override fun toJson(writer: JsonWriter, value: String?) {
wrapped.toJson(writer, value)
}
}
}
Try JsonReader.nextSource(). You can read the encoded JSON bytes either as a String or as a ByteString.
String encodedJson;
try (BufferedSource bufferedSource = reader.nextSource()) {
encodedJson = bufferedSource.readUtf8();
}

Kotlin Type mismatch: inferred type is String but Unit was expected

Im trying to get the return result to return a string, I believe this might be a noob question but I'm very new to kotlin so please don't be harsh. All solutions welcome!
private val client = OkHttpClient()
fun getRequest(id: String) {
val url = "http://localhost:8000/api/v1/discord?discordid=$id"
val request = Request.Builder()
.url(url)
.header("User-Agent", "OkHttp Bot")
.build()
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
println("Error: ${e.message}")
}
override fun onResponse(call: Call, response: Response) {
response.use {
if (!response.isSuccessful) throw IOException("Unexpected code $response")
var result = response.body!!.string()
return result
}
}
})
}
onResponse function has no return type. If you trying to return some value it will throw some error.
So if you want do somthing with the response, you can create a method and pass response body as paramter and do anything with that.
override fun onResponse(call: Call, response: Response) {
response.use {
if (!response.isSuccessful) throw IOException("Unexpected code $response")
var result = response.body?.string()?:""
someMethod(result)
}
}
fun someMethod(response:String){
//Update UI here
}

How to return an object from an api-call-function in Kotlin? [duplicate]

How can I return a value after a callback in kotlin, I tried using Thread.sleep but it doesn't work
fun searchColorFromAPI(): Colors {
val service: RetrofitService = ServiceGenerator.createService(RetrofitService::class.java)
val result: MutableList<String> = arrayListOf()
val call: Call<Colors?>? = service.unityConverter(result)
call?.enqueue(object : Callback<Colors?> {
override fun onResponse(call: Call<Colors?>?, response: Response<Colors?>) {
//switchProgressVisibility()
if (response.isSuccessful) {
val serviceResponse: Colors? = response.body()
if (serviceResponse != null) {
mColors = serviceResponse
}
else {
//buildToast(getString(R.string.null_response))
}
}
else {
//buildToast(getString(R.string.response_unsuccessful))
val errorBody: ResponseBody = response.errorBody()
Log.e(TAG, errorBody.toString())
}
}
override fun onFailure(call: Call<Colors?>?, t: Throwable?) {
/* buildToast(getString(R.string.error_calling_service))
Log.e(TAG, t?.message)*/
}
})
return mColors
}
Always, the mColors is returned before the onFailure or onResponse because they're asynchronous. Before this code was in MainActivity but I was advised to take off, but now when I try get mColors I get the empty value before and after the onResponse is executed, please I'm still learning Kotlin and Android.
Your problem stems from the fact that Retrofit call is asynchronous, so as soon as you call searchColorFromAPI it returns you mColors but the API call may not have been made yet, so you get the mColors value before API call.
To solve this issue, you can do
Use callback, this will require little modification in your current setup, but the 2nd option is preferable over this. Using callback your function should look like this.
/* Now instead of returning a value, your function takes a function (named callback)
as parameter. when your api call finishes, you can call the callback function and
pass the api response.
*/
fun searchColorFromAPI(callback: (Colors?) -> Unit) {
val service: RetrofitService = ServiceGenerator.createService(RetrofitService::class.java)
val result: MutableList<String> = arrayListOf()
val call: Call<Colors?>? = service.unityConverter(result)
call?.enqueue(object : Callback<Colors?> {
override fun onResponse(call: Call<Colors?>?, response: Response<Colors?>) {
//switchProgressVisibility()
if (response.isSuccessful) {
val serviceResponse: Colors? = response.body()
/** pass API response to callback */
callback(serviceResponse)
}
else {
val errorBody: ResponseBody = response.errorBody()
Log.e(TAG, errorBody.toString())
callback(null)
}
}
override fun onFailure(call: Call<Colors?>?, t: Throwable?) {
callback(null)
}
})
}
And in your activity declare a function as follows.
// This function will be called when your api call finishes
// and it will give you the api response
fun apiCallback(colors: Colors?){
if(colors == null){
// API Call failed
}
else{
// use colors as returned by API
}
}
And now call to searchColorFromApi should look like this
searchColorFromApi(apiCallback)
Use Live Data, declare following field in your viewmodel, if you are not using viewmodel then declare it in the class which has searchColorFromApi function.
var colors: MutableLiveData<Colors> = MutableLiveData()
and modify your searchColorFromAPI function as follows
fun searchColorFromAPI() {
val service: RetrofitService = ServiceGenerator.createService(RetrofitService::class.java)
val result: MutableList<String> = arrayListOf()
val call: Call<Colors?>? = service.unityConverter(result)
call?.enqueue(object : Callback<Colors?> {
override fun onResponse(call: Call<Colors?>?, response: Response<Colors?>) {
//switchProgressVisibility()
if (response.isSuccessful) {
val serviceResponse: Colors? = response.body()
if (serviceResponse != null) {
colors.postValue(response.body)
}
}
else {
colors.postValue(null)
val errorBody: ResponseBody = response.errorBody()
Log.e(TAG, errorBody.toString())
}
}
override fun onFailure(call: Call<Colors?>?, t: Throwable?) {
colors.postValue(null)
}
})
}
and in your activity do following
fun setupObservers(){
yourApiCallingClass.colors.observe(this, Observer {
// this code is called when ever value of color field changes
})
}
You can use live data ,that gets updated once the callback receives ,the same live data is observed by the caller fragment/activity
You can use coroutines to return a value from function which has asyn calls in it.
You can use interface callbacks to activity/ fragment to trigger the updates received from retrofit calls.

How to call enqueue callback?

I tried to use enqueue callback but it shows that as an error like "Type mismatch.
Required: Callback<*List<-Location>>"
and this is exactly what I wrote.
fun searchLocation(searchString: String){
showProgress.value = true
val retrofit = Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory(GsonConverterFactory.create())
.build()
val service = retrofit.create(WeatherNetwork::class.java)
service.getLocation(searchString).enqueue(object : Callback<List<Location>>{
override fun onFailure(call: Call<List<Location>>, t: Throwable) {
}
override fun onResponse(
call: Call<List<Location>>,
response: Response<List<Location>>
) {
}
})
}
May be it'll be more clear with the pic
UPD: WeatherNetwork
const val BASE_URL = "/My API/"
interface WeatherNetwork{
#GET ("search?")
fun getLocation(SearchString : String) : List<Location>
}
Your WeatherNetwork is wrong, your api call needs to return a Call
change:
#GET ("search?")
fun getLocation(SearchString : String) : List<Location>
}
To
#GET ("search?")
fun getLocation(SearchString : String) : Call<List<Location>>
}
Side note:
I think you need to change your #GET("search?") to make it work.
For example if your REST URI is : localhost/search?st="wikipedia"
You need to update your function to:
#GET ("search")
fun getLocation(#Query("st") SearchString : String) : List<Location>
}
have a look at : Retrofit 2 - URL Query Parameter

how can i get data from method return value

i use kotlin
i want to get data from method
fun Example() : String{
var value : String
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
print("Getting Data Failed")
}
override fun onResponse(call: Call, response: Response) {
value = "aaa"
}
}
return value
}
finally i want to get value..
but Callback function works late
how can i get value data("aaa")
As far as I understood from your question, you want to perform the request synchronously. This can be done with code like:
fun Example(): String {
val response = client.newCall(request).execute()
val value = if (response.isSuccessful()) {
"aaa"
} else {
error("request failed")
}
return value
}