How can I get data from response body? - android

I need to get "status" value from my response. I tried JSONObject but it gave that java.lang.reflect.InvocationTargetException error in the code below. I need that because I make some process with status value like start new activity etc. How can I get this?
private fun doReq(){
val client = OkHttpClient().newBuilder()
.build()
val mediaType = "application/json;charset=utf-8".toMediaTypeOrNull()
val body: RequestBody = jsonSended.toRequestBody(mediaType)
val request: Request = Request.Builder()
.url("https://apiapiapi/auth")
.method("POST", body)
.addHeader("Content-Type", "application/json")
.addHeader("Authorization", "$authValue")
.addHeader("x-iyzi-rnd", "$randomString")
.addHeader("cache-control", "no-cache")
.build()
val response = client.newCall(request).execute()
println(response.body?.string()) // I CAN GET RESPONSE BODY
var json = JSONObject(response.body.toString())
var status = json.getString("status") // HERE NOT WORKING...
println(status)
}
In the response when server return failure : {"status":"failure","errorCode":"12","errorMessage":"invalid","locale":"tr","systemTime":1610022545347,"conversationId":"123412341234"}
If server return valid my response is very very long but it also have status so I can get that status value and do something with that. Is that correct way to do it? I need advice.

Use response.response or make request in try catch block statement, it will solve the problem

Something like this
private fun doReq(){
try {
var errorResponce: ErrorResponce? = null
val client = OkHttpClient().newBuilder()
.build()
val mediaType = "application/json;charset=utf-8".toMediaTypeOrNull()
val body: RequestBody = jsonSended.toRequestBody(mediaType)
val request: Request = Request.Builder()
.url("https://apiapiapi/auth")
.method("POST", body)
.addHeader("Content-Type", "application/json")
.addHeader("Authorization", "$authValue")
.addHeader("x-iyzi-rnd", "$randomString")
.addHeader("cache-control", "no-cache")
.build()
val response = client.newCall(request).execute()
println(response.body?.string()) // I CAN GET RESPONSE BODY
if (response.errorBody() != null) {
errorResponce = conversorDeErro.convert(response.errorBody()!!)
}
}
catch (e: IOException) {
println(e);
}
finally {
return errorResponce;
}
}

You should read response.body?.string() exactly once and store the result.
val response = client.newCall(request).execute()
println(response.body?.string()) // This permanently consumes the output, you should store the result
var json = JSONObject(response.body.toString()) // toString() is not the response body, it is a debug representation of the response body
var status = json.getString("status")

Related

upload audio file with binary body with retrofit

I need to upload audio file with binary body with retrofit like the image bellow in postman:
how can i upload audio file with binary body like the image with retrofit?
This is what I did but its not work:
#Multipart
#POST("upload")
fun uploadAudio(
#Part audio_file: MultipartBody.Part
): Call<ModelGetAudioUrl>
And this is how I prepare audio file for multipartbody.Part:
According to your screenshot, you propably don't want to use a multipart body. So something like
#POST("upload")
fun uploadAudio(#Body audio_file: TypedInput): Call<ModelGetAudioUrl>
or #Body audio_file: RequestBody should work (see How to send byte[] array in retrofit).
I solve it by using okhttp:
val client = OkHttpClient().newBuilder()
.callTimeout(90, TimeUnit.SECONDS)
.readTimeout(90, TimeUnit.SECONDS)
.connectTimeout(90, TimeUnit.SECONDS)
.writeTimeout(90, TimeUnit.SECONDS)
.build();
val mediaType = "audio/wave".toMediaTypeOrNull();
val body = RequestBody.create(mediaType, soundFile)
val request = Request.Builder()
.url("https://api.assemblyai.com/v2/upload")
.method("POST", body)
.addHeader("authorization", "99fa2a59e27e4688b9f7edcdc8ed7185")
.addHeader("Transfer-Encoding", "chunked")
.addHeader("Content-Type", "audio/wave")
.build()
Thread {
try {
val response = client.newCall(request).execute().use {
if (it.isSuccessful) {
val str = it.body?.string()
if (!str.isNullOrEmpty()) {
val json = JSONObject(str)
sendUrlToTranscript(json.getString("upload_url"))
}
}
context.runOnUiThread {
if (!it.isSuccessful) {
loading.hideDialog()
}
}
}
}catch (e: Exception) {
e.printStackTrace()
Log.d("uploadAudio", "uploadAudio: ${e.message}")
}
}.start()

Api call with basic auth and headers working with okhttp but not working with retrofit

I have an api call with basic auth, multiple headers and request body. But my request is not working with retrofit. So just to verify I checked with okhttp and it is working.
Below is my retrofit code
Api Interface
#POST("login")
suspend fun login(#HeaderMap headers:HashMap<String,String>, #Body body: RequestBody): retrofit2.Response<Any>
Retrofit Instance
#Singleton
#Provides
fun injectRetrofitAPI() : ApiInterface {
val logging = HttpLoggingInterceptor()
logging.level = HttpLoggingInterceptor.Level.BODY
val client = OkHttpClient.Builder()
.addInterceptor(logging)
.build()
return Retrofit.Builder().client(client)
.addConverterFactory(MoshiConverterFactory.create())
.baseUrl(AppConstants.BASE_URL).build().create(ApiInterface::class.java)
}
This is how I am creating my headers and body
private fun createParameters() {
headers["db"] = "P"
headers["latitud"] = "0"
headers["longitud"] = "0"
headers["apiKey"] = "a9f1b3fd3d5a62782f24d2d00afe4532"
headers["Content-Type"] = "application/json"
val credentials = String.format("%s:%s", "centro", "Salud1011.")
val auth = "Basic " + Base64.encodeToString(credentials.toByteArray(), Base64.NO_WRAP)
headers["Authorization"] = auth
body = MultipartBody.Builder().setType(MultipartBody.FORM)
.addFormDataPart("usuario", binding.etUsername.text.toString())
.addFormDataPart("password", binding.etPwd.text.toString())
.build()
Log.d("okhttp", "createParameters: ")
}
And I am simply calling it like this
viewModel.login(body, headers)
Api is giving response but it is going in failure case. I am suspecting that body parameters are not being sent in request as in error it is saying related to username and password.
Below is the OkHttp code which works
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
.addFormDataPart("usuario","FELIPEG")
.addFormDataPart("password","Fel10**11$$")
.build();
Request request = new Request.Builder()
.url("http://200.6.231.237:11000/gasolinera/v1/login")
.method("POST", body)
.addHeader("db", "P")
.addHeader("latitud", "0")
.addHeader("longitud", "0")
.addHeader("apiKey", "a9f1b3fd3d5a62782f24d2d00afe4532")
.addHeader("Authorization", "Basic Y2VudHJvOlNhbHVkMTAxMS4=")
.addHeader("Content-Type", "application/json")
.build();
Response response = client.newCall(request).execute();
I can't find the exact issue with retrofit.

Troubles with OkHttpClient() POST not working KOTLIN

I am attempting to make a sync call that needs to complete before proceeding with storing a user in the cloud. I believe the issue is within the RequestBody as it looks like it is just a byte array. Below is the code:
val client = OkHttpClient()
val mediaType: MediaType? = "application/json".toMediaTypeOrNull()
val body: RequestBody =
RequestBody.create(mediaType, "{\"type\":\"DEFAULT\",\"name\":\"lkjlkj\"}")
val request: Request = okhttp3.Request.Builder()
.url("https://api.example.com/endpoint")
.post(body)
.addHeader("Accept", "application/json")
.addHeader("Content-Type", "application/json")
.addHeader(
"Authorization",
"Bearer SK-xxxxxx-4QAXH"
)
.build()
Toast.makeText(this#RegisterActivity, "Entering Call",Toast.LENGTH_SHORT).show()
val response: Unit = client.newCall(request).execute().use {
Toast.makeText(this#RegisterActivity, "sent call, awaiting response",Toast.LENGTH_SHORT).show()
if (it.isSuccessful){
val content = JSONObject(it.body.toString())
desiredString = content.getJSONArray("desiredStringField").toString()
Toast.makeText(this#RegisterActivity, desiredString,Toast.LENGTH_SHORT).show()
}
if (!it.isSuccessful){
Toast.makeText(this#RegisterActivity, "failed",Toast.LENGTH_SHORT).show()
}
}
The code doesn't crash but it seems the call never completes, as it never makes it into the it.isSuccessful or !it.isSuccessful. Perhaps its a bad formed call somehow. Please help if you can.
Try to enqueue the request and manage the response using a Callback:
client.newCall(request).enqueue(object : Callback {
override fun onResponse(call: Call, response: Response) {
if (!response.isSuccessful){
Toast.makeText(this#RegisterActivity, "failed",Toast.LENGTH_SHORT).show()
return
}
try {
val content = JSONObject(response.body?.string() ?: "")
desiredString = content.getJSONArray("desiredStringField").toString()
Toast.makeText(this#RegisterActivity, desiredString,Toast.LENGTH_SHORT).show()
} catch (e: JSONException) {
// Error parsing JSON object
}
}
override fun onFailure(call: Call, e: IOException) {
Toast.makeText(this#RegisterActivity, "failed",Toast.LENGTH_SHORT).show()
}
}

Volley to Retrofit2 - How to do a String Request with Retrofit2?

I would like to migrate to Retrofit2 the following Volley string request.
This request retrieves a response body as String, which I parse myself.
fun updatePodcastEpisodesRQ( url: String) {
val feedReq = StringRequestUTF8(
Request.Method.GET,
url,
{ response: String? -> ...},
{ error: VolleyError ->...}
)
App.instance?.addToRequestQueue(feedReq, TAG_JSON_REQUEST1)
}
Please note that the URL can be any address, as a result there is no baseUrl as defined in Retrofit.Builder() when doing JSON request for example.
Is it possible to do such a simple request with Retrofit2 ?
In fact, okhttp3 fulfilled all my needs. I migrated from Volley to okhttp3.
private val client = OkHttpClient()
suspend fun getFeed(url: String): String {
val request = Request.Builder()
.url(url)
.build()
client.newCall(request).execute().use { response ->
if (!response.isSuccessful)
throw IOException("Error occurred - code:${response.code} message=${response.message}")
if (response.body == null)
throw IOException("Error occurred - null body")
return response.body!!.string()
}
}

Retrofit2: Add post parameter into interceptor

Inside my Android kotlin app i'm calling some apis by using retrofit2 like
#FormUrlEncoded
#POST("something/some")
fun callMyApi(
#Field("myField") myField: String
): Deferred<MyResponseClass>
Now i need to add some common post params to all my api request (and keep the specific ones for each call, in this case i need to keep "myField"), so i'm using an interceptor:
val requestInterceptor = Interceptor { chain ->
val newRequest = chain.request()
.newBuilder()
.post(
FormBody.Builder()
.add("common1Key", "common1")
.add("common2Key", "common2")
.add("common3Key", "common3")
.build()
)
.build()
return#Interceptor chain.proceed(newRequest)
}
But this implementation fails because the interceptor seems to overwrite myField.
How can i fix it?
We can create Interceptor by using two or more common query parameter.
val requestInterceptor = Interceptor { chain ->
val url = chain.request()
.url()
.newBuilder()
.addQueryParameter("common1key", "common1")
.addQueryParameter("common2key", "common2")
.addQueryParameter("common3key", "common3")
.build()
val request = chain.request()
.newBuilder()
.url(url)
.build()
return#Interceptor chain.proceed(request)
}
I have added Interceptor for post form body.
interface PostWebApiService {
#POST("posts")
#FormUrlEncoded
fun savePost(
#Field("title") title: String
): Deferred<Post>
companion object {
operator fun invoke(): PostWebApiService {
val requestInterceptor = Interceptor { chain ->
var request = chain.request()
val requestBuilder = request.newBuilder()
val formBody = FormBody.Builder()
.add("body", "Body")
.add("userId", "12")
.build()
var postBodyString = bodyToString(request.body())
val concat = if (postBodyString.isNotEmpty()) "&" else ""
postBodyString = postBodyString + concat + bodyToString(formBody)
request = requestBuilder.post(
RequestBody.create(
MediaType.parse("application/x-www-form-urlencoded;charset=UTF-8"),
postBodyString
)
)
.build()
return#Interceptor chain.proceed(request)
}
val okHttpClient = OkHttpClient.Builder()
.addInterceptor(requestInterceptor)
.build()
return Retrofit.Builder()
.client(okHttpClient)
.baseUrl("http://jsonplaceholder.typicode.com/")
.addCallAdapterFactory(CoroutineCallAdapterFactory())
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(PostWebApiService::class.java)
}
fun bodyToString(request: RequestBody?): String {
try {
var buffer = Buffer()
request?.writeTo(buffer)
return buffer.readUtf8()
} catch (e: IOException) {
return "error"
}
}
}
}

Categories

Resources