I'm using Retrofit and I'm in touch with my webservice but I can not get an answer and the field I want. Example: campo1 and assign to a variable and print it.
I think I'm not calling onResponse properly, as it's coming as null
Send JSON:
{
"select":"select id || ' | ' ||senha_terminal,nome,login_web,null,5,null n2,7,senha_terminal,senha_web,data_inclusao from usuario where id in (3257) order by id desc"
}
Expected response:
[
{
"campo1": "3257 | 74327",
"campo2": "Sidnei",
"campo3": "sidnei01",
"campo4": null,
"campo5": 5,
"campo6": null,
"campo7": 7,
"campo8": "74327",
"campo9": "56c07af798f309dbd75822a849ce47b6",
"campo10": "2012-02-08T11:00:06"
}
]
I would like to get field1 and assign in a variable response.
Main:
package com.example.romeu.myapplication;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.Button;
import org.json.JSONException;
import org.json.JSONObject;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.converter.scalars.ScalarsConverterFactory;
public class MainActivity extends AppCompatActivity implements Callback<SelectModel> {
public Button btnConsultar;
Call<SelectModel> call;
Response<SelectModel> response;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ApiInterface.URL_BASE)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
ApiInterface apiInterface = retrofit.create(ApiInterface.class);
try
{
JSONObject paramObject = new JSONObject();
paramObject.put("select", "select id || ' | ' ||senha_terminal,nome,login_web,null,5,null n2,7,senha_terminal,senha_web,data_inclusao from usuario where id in (3257) order by id desc");
onResponse(call, response);
}
catch (JSONException e)
{
e.printStackTrace();
}
}
#Override
public void onResponse(Call<SelectModel> call, Response<SelectModel> response)
{
String resposta = response.body().getCampo1();
Log.i("MSG", resposta);
}
#Override
public void onFailure(Call<SelectModel> call, Throwable t) {
}
}
ApiInterface:
package com.example.romeu.myapplication;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.Headers;
import retrofit2.http.POST;
/**
* Created by romeu on 01/03/18.
*/
public interface ApiInterface {
String URL_BASE = "https://services-dev.redetendencia.com.br/api-rest";
#Headers("Content-Type: application/json")
#POST("select")
Call<SelectModel> getSelect(#Body String body);
}
Model:
package com.example.romeu.myapplication;
/**
* Created by romeu on 01/03/18.
*/
class SelectModel {
public String campo1,campo2,campo3,campo4,campo5,campo6,campo7,campo8,campo9,campo10;
public SelectModel(){}
//Getters
public String getCampo1() {
return campo1;
}
public String getCampo2() {
return campo2;
}
public String getCampo3() {
return campo3;
}
public String getCampo4() {
return campo4;
}
public String getCampo5() {
return campo5;
}
public String getCampo6() {
return campo6;
}
public String getCampo7() {
return campo7;
}
public String getCampo8() {
return campo8;
}
public String getCampo9() {
return campo9;
}
public String getCampo10() {
return campo10;
}
}
I think you are trying to achieve an async request. But the callback does not work this way:
onResponse(call, response);
you are actually just invoking onResponse( .. ) directly with null response. Also, you do not construct Call at all it is also null. Replace above line with:
Call<SelectModel> call = apiInterface.getSelect(paramObject.toString());
call.enqueue(MainActivity.this);
Note: paramObject.toString() is only a suggestion. I am not sure how it is supposed to be attached to the request body. Maybe you can put only that string without any JsonObject.
That enqueues async request which when gets response, will invoke onResponse( .. ).
Related
I am a newbie in Android. I have a rest API I developed in Django which I want my Android app to interact with.
I am using Retrofit In Android Studio
To save a new user through the API I pass four fields (staff_id,email,password,password2) to my API.
It all works fine in Postman and returns the appropriate responses for both a success (HTTP 200) and bad request (HTTP 400)
This Is The Image of a 201 Response on The Android App Which is correct
However the HTTP 400 response in Android does not return a JSON. In Postman I get this for the HTTP 400
{
"error_message": "That email is already in use.",
"response": "Error"
}
But In Android I don’t get the Same JSON Response from the response.errorBody(). Instead I Get A HTML Response LIke This:
<DOCTYPE HTML PUBLIC"-//W3C//DTD HTML 4.0 transitional//EN>
<html>
<head>
<title>400</title>
<meta http-eqiv="Cache-Control"
content ="no-cache"/>
</head>
<body>
<p>
Bad Request
</p>
</body>
</html>
Here’s My Android Studio Code
Api.java:`
package nkemokongwu.com.ng.leave.activities.api;
import nkemokongwu.com.ng.leave.activities.models.NewStaff;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.Header;
import retrofit2.http.Headers;
import retrofit2.http.POST;
public interface Api {
#FormUrlEncoded
#POST("authenticate/api/api_signup/")
Call<ResponseBody> signup(
#Field("staff_id") int staff_id,
#Field("email") String email,
#Field("password") String password,
#Field("password2") String password2
);
#FormUrlEncoded
#POST("authenticate/api/api_login")
Call<ResponseBody> userLogin(
#Field("email") String email,
#Field("password") String password
);
}
RetrofitClient.Java
package nkemokongwu.com.ng.leave.activities.api;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class RetrofitClient {
private static final String BASE_URL = "http://nsitf.pythonanywhere.com/";
private static RetrofitClient mInstance;
private Retrofit retrofit;
private RetrofitClient() {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
public static synchronized RetrofitClient getInstance() {
if (mInstance == null) {
mInstance = new RetrofitClient();
}
return mInstance;
}
public Api getApi() {
return retrofit.create(Api.class);
}
}
SignUpActivity.java
package nkemokongwu.com.ng.leave.activities.authentication;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.util.Patterns;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import java.io.IOException;
import java.util.Objects;
import nkemokongwu.com.ng.leave.R;
import nkemokongwu.com.ng.leave.activities.api.RetrofitClient;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class SignUpActivity extends AppCompatActivity implements View.OnClickListener {
private EditText editTextstaff_id,editTextemail,editTextpassword,editTextpassword2;
private static final String TAG = "MyActivity";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sign_up);
editTextstaff_id = findViewById(R.id.editTextstaff_id);
editTextemail = findViewById(R.id.editTextemail);
editTextpassword = findViewById(R.id.editTextpassword);
editTextpassword2 = findViewById(R.id.editTextpassword2);
findViewById(R.id.text_already_have_account).setOnClickListener(this);
findViewById(R.id.buttonSignUp).setOnClickListener(this);
}
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
private void userSignUp() {
String temp = editTextstaff_id.getText().toString().trim();
int staff_id = 0;
if (!"".equals(temp)) {
staff_id = Integer.parseInt(temp);
} else {
editTextstaff_id.setError("Staff ID Is Required");
editTextstaff_id.requestFocus();
return;
}
String email = editTextemail.getText().toString().trim();
String password = editTextpassword.getText().toString().trim();
String password2 = editTextpassword2.getText().toString().trim();
if (email.isEmpty()) {
editTextemail.setError("Email is required");
editTextemail.requestFocus();
return;
}
if (!Patterns.EMAIL_ADDRESS.matcher(email).matches()) {
editTextemail.setError("Enter a valid email");
editTextemail.requestFocus();
return;
}
if (password.isEmpty()) {
editTextpassword.setError("Password required");
editTextpassword.requestFocus();
return;
}
if (password2.isEmpty()) {
editTextpassword2.setError("Confirmation Password Required");
editTextpassword2.requestFocus();
return;
}
if (!Objects.equals(password, password2)) {
editTextpassword.setError("Passwords Do Not Match");
editTextpassword.requestFocus();
return;
}
Call <ResponseBody> call =RetrofitClient
.getInstance()
.getApi()
.signup(staff_id,email,password,password2);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (response.code() == 201){
try {
Toast.makeText(SignUpActivity.this,response.body().string(),Toast.LENGTH_LONG).show();
} catch (IOException e) {
e.printStackTrace();
}
} else if (response.code() == 400){
try {
Toast.makeText(SignUpActivity.this,response.errorBody().string(), Toast.LENGTH_LONG).show();
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Toast.makeText(SignUpActivity.this,t.toString(),Toast.LENGTH_LONG).show();
}
});
//
}
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
public void onClick(View v) {
switch (v.getId()) {
case R.id.buttonSignUp:
userSignUp();
break;
case R.id.text_already_have_account:
startActivity(new Intent(this, LoginActivity.class));
break;
}
}
}
`
I have tried the following;
1. Annotated the Signup call with #Headers to specify Accept and Content-Type
2. Modified my Django API code to include content type as well.
None of which have helped. I have also scoured through Stack Overflow to find a solution and everything I’ve tried still did not work.
I would appreciate any help to point me in the right direction. Is it my android code or do I have to modify the Django Rest API? The latter is unlikely given that I get the correct response on Postman.
Thank you for any help you can offer.
I figured it out! For anyone who is facing this, the problem is with the API itself. In my Django Rest API Serializer, I had some of my responses like:
return Response(status=status.HTTP_400_BAD_REQUEST)
return Response(status=status.HTTP_401_UNAUTHORIZED)
Now this was the issue for Retrofit cos it changes the response from a successful response (code 200) to an error response which in turn returns an error when attempting to view the response.body() in retrofit. The response is only available in response.errorbody() which returns some strange okhttp stuff that dosen’t help at all!!
Instead what I should have done in my API was:
First define an empty list:
context={}
Then add the error values with
context['status'] = 'Error'
context['message'] = 'Invalid credentials'
context['code']=status.HTTP_401_UNAUTHORIZED
return Response(data=context)
This returns
Postman Image Of Response
Which is perfect and can be easily modelled into a Java Class or Pojo as you wish. As the API’s Actual response code is 200, the response.body() is available and won’t return an error.
That was the issue!
I am trying to consume web api written in asp.net core 2.2 in android using Retrofit rest client. successfully Getting data from Api's but unable to Post Data to server using Retrofit. the webapi is working fine via postman and Javascript.
following is what i have tried..
My Activity Class
private Retrofit retrofit = new Retrofit.Builder().baseUrl("https://sga.somee.com/api/")
.addConverterFactory(ScalarsConverterFactory.create()).addConverterFactory(GsonConverterFactory.create()).build();
private ShopApi _shopsApi;
//constructor
public MainActivity2(){
//api classes must be initialized in constructors
_shopsApi = retrofit.create(ShopApi.class);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
Shop _shop = new Shop();
_shop.shop_name = "Starbucks";
_shop.shop_owner = "Unknown";
_shop.shop_longitude = 49545.3455;
_shop.shop_latitude = 55353.554;
_shop.shop_image = "path/path.png";
PostShop(_shop);
}
public void PostShop(Shop shop){
/*
JsonObject obj = new JsonObject();
obj.addProperty("shop_name",shop.shop_name);
obj.addProperty("shop_owner",shop.shop_owner);
obj.addProperty("shop_longitude",shop.shop_longitude);
obj.addProperty("shop_latitude",shop.shop_latitude);
obj.addProperty("shop_image",shop.shop_image);
Log.d(TAG, obj.toString());
*/
Call<ResponseBody> AddShop = _shopsApi.AddShop(shop);
AddShop.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
Toast.makeText(MainActivity2.this,response.raw().body().toString(),Toast.LENGTH_LONG).show();
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Toast.makeText(MainActivity2.this,"Failded to add new shop",Toast.LENGTH_LONG).show();
}
});
}
My ShopApi Class
package com.example.madee.sga.API;
import com.example.madee.sga.Models.Shop;
import java.util.List;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.Headers;
import retrofit2.http.POST;
import retrofit2.http.Path;
public interface ShopApi {
#GET("Shops/GetAll/{page}")
Call<List<Shop>> GetAllShops(#Path("page") int page );
#Headers({"Content-Type: application/json"})
#POST("Shops/AddNew")
Call<ResponseBody> AddShop(#Body Shop _shop);
}
You can also see that i have tried posting data with JsonObject too in MainActivity but same failure 400 Bad Requset
This Error comes because you set params in body of POST request. Add Paramtere like this.
#Headers({"Content-Type: application/json"})
#FormUrlEncoded
#POST("Shops/AddNew")
Call<ResponseBody> AddShop(#Field("ShopName") String ShopName, #Field("OwnerName") String OwnerName, #Field("Longitude") int Longitude,#Field("Latitude") int Latitude,#Field("Imagepath") String Imagepath,#Field("ShopId") String ShopId);
And call this function as:
Call<ResponseBody> AddShop = _shopsApi.AddShop(shop.shop_name, shop.shop_owner, shop.shop_longitude, shop.shop_latitude, shop.shop_image,shop.shop_id);
And i assumed your server accept same paramters name as u written in code. if it is not same changed it accordingly.
I am using OkHttp3 to do a GET API call, which works, however I would like to update a TextView (jsonTextView) in the UiThread with the result of the GET call.
I have tried 10 different ways but it does not work. Always tells me that can't resolve this or that therefore I ask that if you decide to help me, please take into account posting any dependencies on your answer such as import or declaration.
I left a line in my rest class: "CODE TO UPDATE jsonTextView IN UITHREAD". In your opinion what is the best way to achieve this?
Thank you so much in advance, I already lost hours on this.
This is my activity
package it.test.test;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.EditText;
import android.os.*;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
Button fetchUpdateButton;
TextView jsonTextView;
EditText assetCode;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fetchUpdateButton = (Button) findViewById(R.id.fetchUpdateButton);
fetchUpdateButton.setOnClickListener(fetchAssetUpdateClick);
jsonTextView = (TextView) findViewById(R.id.jsonTextView);
assetCode = (EditText) findViewById(R.id.assetCode);
}
View.OnClickListener fetchAssetUpdateClick = new View.OnClickListener() {
#Override
public void onClick(View v) {
REST r = new REST();
try {
r.getAssetUpdates(assetCode.getText().toString());
} catch (Exception e) {
e.printStackTrace();
jsonTextView.setText("API Fetch Failed");
}
}
};
}
This is my REST class
package it.test.test;
import android.util.Log;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Headers;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
/**
* Created by fabio on 25/02/2017.
*/
public class REST {
private final OkHttpClient client = new OkHttpClient();
public void getAssetUpdates(String assetCode) throws Exception {
Request request = new Request.Builder()
.url("http://10.0.0.3:8080/api/api/assets/getAsset?networkAssetCode=" + assetCode)
.build();
client.newCall(request).enqueue(new Callback() {
#Override public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
#Override public void onResponse(Call call, Response response) throws IOException {
try (final ResponseBody responseBody = response.body()) {
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
Headers responseHeaders = response.headers();
for (int i = 0, size = responseHeaders.size(); i < size; i++) {
System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i));
}
System.out.println(responseBody.string());
CODE TO UPDATE jsonTextView IN UITHREAD
}
}
});
}
}
You can't update the other class UI from the REST class unless you put the callback into the method definition.
public void getAssetUpdates(String assetCode, Callback callback) {
...
client.newCall(request).enqueue(callback);
}
it's simply moving around some variables
Then, in the onClick define your callback so you can access your TextView in that Activity class ,
#Override
public void onClick(View v) {
...
r.getAssetUpdates(assetCode.getText().toString(),
new Callback() {
#Override public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
#Override public void onResponse(Call call, Response response) throws IOException {
try (final ResponseBody responseBody = response.body()) {
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
...
// update UI in here
}
}
);
}
And I do think Okhttp requires a usage of runOnUiThread.
OkHTTP Update UI from enqueue callback
Note that if you have JSON and REST, then Retrofit is going to be better than pure Okhttp.
One solution is to give an Activity to REST and call runOnUiThread().
Create own listener & pass the listener object from your activity..
And return the call back from Rest to your Activity
Step 1: Create interface
public interface MyListener
{
void restResult(String result);
}
Step 2:Implement this listener to your activity
YourActivity implements MyListener
Step 3:Pass the listener to Rest class
Rest rest=new Rest(this);//this-- your listener object
Step 4:Modify Rest Constructor
Private MyListener myListener;
Rest(MyListener myListener){
this.myListener=myListener;
}
//After your Rest completed pass the result
CODE TO UPDATE jsonTextView IN UITHREAD
myListener.restResult(responseBody.string());
Step 5: In your Activity get your result
Update the textview using
#override
restResult(String result){
yourtextview.settext(result);
}
I wanna to save the result from OnResponse method to use it for updating the UI
i tried to save the result into String var then call it into main thread but it doesn't work .
here's my code with some comments ,
any help ?
package com.example.blacknight.testokhttp;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import static android.R.string.ok;
public class MainActivity extends AppCompatActivity {
public final String URL_MOVIE = "http://api.themoviedb.org/3/movie/popular?api_key=" + API_KEY;
String res_120 ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(URL_MOVIE)
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
}
#Override
public void onResponse(Call call, Response response) throws IOException {
Log.v("BK-201 URL: " , response.body().string());
// wanna save the result to update UI
res_120 = response.body().string();
}
});
// just for test : if the result has been saved or not
Log.i("BK-111 : " , res_120);
}
}
Let's say you want to update a TextView element in you UI with the response in a String format. You could do something like this. I keeped your test log to help you follow the code, just in case.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(URL_MOVIE)
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
}
#Override
public void onResponse(Call call, Response response) throws IOException {
Log.v("BK-201 URL: " , response.body().string());
// wanna save the result to update UI
res_120 = response.body().string();
updateUI(response.body().string());
}
});
}
void updateUI(String string) {
textView.setText(string);
Log.i("BK-111 : " , res_120);
}
Here's a working code for anyone have the same problem or new on using OkHttp , Unfortunately i'm using AsyncTask
Thaks to Jofre Mateu
package com.example.blacknight.testokhttp;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class MainActivity extends AppCompatActivity {
public final String URL_MOVIE = "http://api.themoviedb.org/3/movie/popular?api_key=" + API_KEY ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new MovieTask().execute();
}
public class MovieTask extends AsyncTask<String , Void , String>
{
#Override
protected String doInBackground(String... params) {
try {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(URL_MOVIE)
.build();
Response response = client.newCall(request).execute();
String res_120 = response.body().string();
return res_120;
} catch (Exception e ){
return null;
}
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
TextView textView = (TextView) findViewById(R.id.testView_test);
textView.setText(s);
}
}
}
I am trying to read the httpstatus code e body in the success case of a request. So I created the code below to test but I failed to get the onNext called, I tried to use the okhttp (com.squareup.okhttp.Response) and retrofit Response (retrofit.Response) class, but I couldn't make it work.
Can someone help me to read the body and httpstatus code here? I would like to keep using the Observables.
Thanks in advance.
package com.app.rest;
import com.squareup.okhttp.Response;
import retrofit.GsonConverterFactory;
import retrofit.Retrofit;
import retrofit.RxJavaCallAdapterFactory;
import retrofit.http.GET;
import rx.Observable;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
public class TestApiClient {
public interface Test {
#GET("/posts")
Observable<Response> getPosts();
}
public TestApiClient() {
new Retrofit.Builder()
.baseUrl("http://jsonplaceholder.typicode.com")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build().create(Test.class).getPosts().subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber<Response>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
e.toString();
}
#Override
public void onNext(Response response) {
response.toString();
}
});
}
}
I got the answer.
import com.squareup.okhttp.ResponseBody;
import retrofit.Response;
...
public Observable<Response<ResponseBody>> xxx(){}
...
Playlist playlist = Playlist.parse(((ResponseBody)response.body()).byteStream());
Actually, response.body() is a Object, You can cast it to another type.In this case, it is ResponseBody.
I got it working with the code below, it was to needed to use the generics of retrofit.Response with ResponseBody:
package com.app.rest;
import com.squareup.okhttp.ResponseBody;
import retrofit.GsonConverterFactory;
import retrofit.Response;
import retrofit.Retrofit;
import retrofit.RxJavaCallAdapterFactory;
import retrofit.http.GET;
import rx.Observable;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
public class TestApiClient {
public interface Test {
#GET("/posts")
Observable<Response<ResponseBody>> getPosts();
}
public TestApiClient() {
new Retrofit.Builder()
.baseUrl("http://jsonplaceholder.typicode.com")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build().create(Test.class).getPosts().subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber<Response<ResponseBody>>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
e.toString();
}
#Override
public void onNext(Response<ResponseBody> response) {
response.toString();
}
});
}
}
You need to define your interface's Observable as
#GET("/posts")
Observable<Result<MyPost>>
Then you can easily get the response body in onNext() like this:
#Override
public void onNext(Result<MyPost> result) {
result.response().body();
}
Sometimes the response.toString() or response.body() gives you unreadable string, I had to get the bytes from the response body and construct a new string from it.
#Override
public void onNext(Response<ResponseBody> response) {
try {
String responseStr = new String(response.body().bytes());
Log.d("responseBodyResponse", responseStr);
} catch (Exception e) {
Log.d("responseBodyResponse Exception", e.getMessage());
}
}