I want to make a library to reduce my duplicate network works on every android projects or even give my jar to some other developers to using my methods for network communications.
So i build this:
import java.util.Map;
import org.json.JSONObject;
import com.android.volley.DefaultRetryPolicy;
import com.android.volley.Request.Method;
import com.android.volley.Request.Priority;
import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener;
import com.android.volley.VolleyError;
import com.android.volley.VolleyLog;
public class RequestResp {
private final static String WEB_SERVICE_URL = "http://blabla/api";
private final Priority priorityImmediatelly = Priority.IMMEDIATE;
private final Priority priorityHigh = Priority.HIGH;
private final Priority priorityNORMAL = Priority.NORMAL;
private String tag_req_default = "tag_req_default";
VolleyCustomRequest mVolleyCustomReq;
DefaultRetryPolicy drp = new DefaultRetryPolicy(15000,DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
public /*JSONObject*/ void sendParamsAsHighPriority(Map<String, String> params) {
mVolleyCustomReq = new VolleyCustomRequest(Method.POST,
WEB_SERVICE_URL, params, new Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
if (response != null) {
}
}
}, new ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(tag_req_default, error.getMessage());
}
}) {
#Override
public Priority getPriority() {
return priorityHigh;
}
};
mVolleyCustomReq.setRetryPolicy(drp);
VolleyController.getInstance().addToRequestQueue(mVolleyCustomReq,
tag_req_default);
/*return response; ?!?!?*/
}
}
But how to return response?! Cause if server was busy or down or something that make response a little late, developers in their applications get null!(i guess).
How to make a such this?! Build a jar library that has a class that has a method that give parameters and send it on specific URL, with volley library?
Define Interface like
public interface OntaskCompleted {
public void onSuccess(JSONObject response);
public void onError(String message);
}
Now Your activity should implement this interface and you have to override these method.
Now in you Volley class do this.
if (response != null) {
ontaskCompleted.onSuccess(JSONObject);
}
and
public void onErrorResponse(VolleyError error) {
VolleyLog.d(tag_req_default, error.getMessage());
ontaskCompleted.onError( error.getMessage());
}
Now your activity will get the result of error or success.
Hope it helps you.
Related
I have a serious problem.
I have a small app for a restaurant to manage the creation of orders, update, and so. Waiters use an android tablet to serve to the customers.
The thing is that since a week or so, I realized that tickets tend to duplicate items. After some research and diving into the logs, I realized that many times, when I call an AsyncTask to make a request to the server, it doesn't send ONE request, it sends several requests instead.
For that reason, if I call the "addItemToOrder" service four times, it will add four items instead of just one.
Here is my code. This is a "generic GET Async Task" that I call. It has an url, it may or not has some parameters, and it just creates a volley request that sends to the server. As you can see, it has 0 retries and, before you can ask, I just made sure that this AT is not being called more than once:
package es.vdevelop.tpvmobile.asynctask;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Handler;
import android.widget.Toast;
import com.android.volley.DefaultRetryPolicy;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.bugfender.sdk.Bugfender;
import org.json.JSONException;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;
import es.vdevelop.tpvmobile.Constants;
import es.vdevelop.tpvmobile.ErrorHelper;
import es.vdevelop.tpvmobile.FunctionsHelper;
abstract class GenericGetAsyncTask extends AsyncTask<Void, Void, Void> {
private static final String TAG = "DEBUG GenericGetAT";
Handler h;
WeakReference<Context> context;
String auxURL;
HashMap<String, String> postParams;
String query;
GenericGetAsyncTask(WeakReference<Context> context, Handler h) {
this.auxURL = "";
this.context = context;
this.h = h;
this.postParams = new HashMap<>();
this.query = "";
}
#Override
protected Void doInBackground(final Void... params) {
if (!FunctionsHelper.isConnected(context.get())) {
h.sendEmptyMessage(ErrorHelper.HANDLER_NO_INTERNET_ERROR);
Bugfender.d(TAG, "No internet connection");
ErrorHelper.mostrarError(context.get(), ErrorHelper.HANDLER_NO_INTERNET_ERROR, TAG);
return null;
}
String urlParcial = Constants.getUrl(context.get());
if (urlParcial.equals("")) {
h.sendEmptyMessage(ErrorHelper.HANDLER_FALTA_URL);
Bugfender.d(TAG, "Falta url");
ErrorHelper.mostrarError(context.get(), ErrorHelper.HANDLER_URL_INCORRECTA, TAG);
return null;
}
int metodo;
String url;
if (query == null || query.equals("")) {
url = urlParcial + this.auxURL;
metodo = Request.Method.POST;
} else {
url = urlParcial + this.auxURL + "?" + this.query;
metodo = Request.Method.GET;
}
Bugfender.d(TAG, "url -> " + url);
final RequestQueue queue = Volley.newRequestQueue(context.get());
final StringRequest request = new StringRequest(metodo, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
onResultRetrieved(response);
} catch (JSONException e) {
Bugfender.d(TAG, "Hubo un error de json en onResponse -> " + e.toString());
h.sendEmptyMessage(ErrorHelper.HANDLER_RESPUESTA_INCORRECTA);
ErrorHelper.mostrarError(context.get(), ErrorHelper.HANDLER_JSON, TAG);
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Bugfender.d(TAG, "Error recibido del servidor -> " + error.toString());
ErrorHelper.mostrarError(context.get(), ErrorHelper.HANDLER_RESPUESTA_INCORRECTA, TAG);
Toast.makeText(context.get(), "Error realizando llamada http -> " + error.toString(), Toast.LENGTH_SHORT).show();
h.sendEmptyMessage(ErrorHelper.HANDLER_ERROR);
}
}) {
#Override
protected Map<String, String> getParams() {
return postParams;
}
#Override
public Priority getPriority() {
return Priority.IMMEDIATE;
}
};
request.setRetryPolicy(new DefaultRetryPolicy(2000, 0, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
queue.add(request);
return null;
}
protected abstract void onResultRetrieved(String result) throws JSONException;
}
After that, then I just have to inherit from this generic AT with just some bit of code to make a simple request, just as you can see here in this "UpdateTicketAT":
package es.vdevelop.tpvmobile.asynctask;
import android.content.Context;
import android.os.Handler;
import com.bugfender.sdk.Bugfender;
import org.json.JSONException;
import org.json.JSONObject;
import java.lang.ref.WeakReference;
import es.vdevelop.tpvmobile.Constants;
import es.vdevelop.tpvmobile.ErrorHelper;
import es.vdevelop.tpvmobile.Functions;
public class UpdateTicketAsyncTask extends GenericGetAsyncTask {
private static final String TAG = "DEBUG UpdateTicketAT";
public UpdateTicketAsyncTask(WeakReference<Context> context, Handler h, String json) {
super(context, h);
this.auxURL = "actualizar_ticket.php";
this.postParams.put("ticket", json);
Bugfender.d(TAG, "Ticket que vamos a enviar -> " + json);
}
#Override
protected void onResultRetrieved(String response) throws JSONException {
Bugfender.d(TAG, "Respuesta obtenida del servidor -> " + response);
JSONObject result = new JSONObject(response);
int codigo = result.getInt("codigo");
if (codigo == 0) {
h.sendEmptyMessage(Constants.handlerOk);
Bugfender.d(TAG, "Ticket actualizado correctamente");
} else {
h.sendEmptyMessage(Constants.handlerError);
ErrorHelper.mostrarError(context.get(), codigo, TAG);
}
}
}
I can't find out what is happening here. Am I doing something wrong?
One important thing is that the calls to the server may not be all made in a row. I mean, I make a request, I get the response, and maybe a minute or two later, the request is made again!
I just can be aware of this by looking into the server logs..
I don't know what's happening here..
Anyway, thanks in advance!
I can see two ways to answer your question or not:
First: i don`t like your "0" in your DefaultRetryPolicy line, try to put some like this:
jsonObjectRequest.setRetryPolicy(new DefaultRetryPolicy(TIMEOUT_SERVICE,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
The first parameter is timeout, second is max retries (yes i know, you know that but check that is 1) and the last one is DefaultRetryPolicy.DEFAULT_BACKOFF_MULT ( again i know, blah blah, but check that is 1.0f) or put literal.
jsonObjectRequest.setRetryPolicy(new DefaultRetryPolicy(TIMEOUT_SERVICE,
1, 1.0f));
Second: Can you only set more time in your time out.
I hope this help you.
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 know there are enormous library or API used with android HTTP Get,Post,Put.But can somebody tell me which library are better for get post and put and other various library
If you want to make requests to a database from your app, I recommand you to use the Google's library made for it : Volley
You can find tutorials like this one which will permit you to make POST or GET requests.
You can also consult the documentation of Google on volley
There are mostly tow library used with network relate operation like send receive data or request,response e.t.c,
1) volley
2) Retrofit
Both are good library and both are flexible and manageable library.
For Retrofit Click Here
For volley Click Here
You should use volley, it is the best thing out there, here I'm uploading some code to help you out.
ApplicationController.java
You have to add this file in manifest file's application tag,
import android.app.Application;
import android.text.TextUtils;
import com.android.volley.DefaultRetryPolicy;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.VolleyLog;
import com.android.volley.toolbox.Volley;
public class ApplicationController extends Application {
public static final String TAG = "VolleyPatterns";
private static ApplicationController sInstance;
private RequestQueue mRequestQueue;
public static synchronized ApplicationController getInstance() {
return sInstance;
}
#Override
public void onCreate() {
super.onCreate();
sInstance = this;
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}
return mRequestQueue;
}
public <T> void addToRequestQueue(Request<T> req, String tag) {
req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
req.setRetryPolicy(new DefaultRetryPolicy(DefaultRetryPolicy.DEFAULT_TIMEOUT_MS,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT
));
VolleyLog.d("Adding request to queue: %s", req.getUrl());
getRequestQueue().add(req);
}
public <T> void addToRequestQueue(Request<T> req) {
req.setTag(TAG);
req.setRetryPolicy(new DefaultRetryPolicy(DefaultRetryPolicy.DEFAULT_TIMEOUT_MS,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT
));
getRequestQueue().add(req);
}
public void cancelPendingRequests(Object tag) {
if (mRequestQueue != null) {
mRequestQueue.cancelAll(tag);
}
}
}
CustomRequest.java
Custom request to connect to database and get data.
import android.app.ProgressDialog;
import android.content.Context;
import android.widget.Toast;
import com.android.volley.AuthFailureError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.TimeoutError;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.Map;
import raghav.bookthat.support.Constants;
public class CustomRequest {
static final String[] response = new String[1];
private StringRequestCompleteListener stringRequestCompleteListener;
public CustomRequest(StringRequestCompleteListener stringRequestCompleteListener) {
this.stringRequestCompleteListener = stringRequestCompleteListener;
}
public static String getResponse(String response) throws JSONException {
JSONObject jsonObject = new JSONObject(response);
if (jsonObject.getString("Error").equals("200")) {
return jsonObject.getString("response");
} else {
return null;
}
}
public void loadJSON(final HashMap<String, String> headers, final Context context, final ProgressDialog progressDialog) {
if (headers != null) {
StringRequest stringRequest = new StringRequest(Request.Method.POST, Constants.WEBSERVICE, new Response.Listener<String>() {
#Override
public void onResponse(String s) {
try {
response[0] = getResponse(s);
if (stringRequestCompleteListener != null && response[0] != null) {
stringRequestCompleteListener.onTaskCompleted(response[0]);
} else {
if (progressDialog != null) {
progressDialog.dismiss();
}
}
} catch (JSONException e) {
if (progressDialog != null) {
progressDialog.dismiss();
}
response[0] = null;
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
if (volleyError instanceof TimeoutError) {
Toast.makeText(context, "Please Wait\n The Internet is Quite Slow Down Here", Toast.LENGTH_SHORT).show();
loadJSON(headers, context, progressDialog);
} else {
if (progressDialog != null) {
progressDialog.dismiss();
}
}
}
}) {
#Override
public Map<String, String> getParams() throws AuthFailureError {
return headers;
}
#Override
public Priority getPriority() {
return Priority.IMMEDIATE;
}
};
ApplicationController.getInstance().addToRequestQueue(stringRequest);
}
}
}
StringRequestCompleteListener.java
Listener to handle response of volley
public interface StringRequestCompleteListener {
void onTaskCompleted(String response);
}
Use of custom request
HashMap<String, String> headers = new HashMap<>();
headers.put("method", "createBooking");
headers.put("PackageID", String.valueOf(bundle.getInt("PackageID")));
headers.put("UserID", String.valueOf(sharedPreferencesHelper.getUserID()));
headers.put("Price", txtTotalPrice.getText().toString());
headers.put("TotalPerson", edTotalPerson.getText().toString());
headers.put("BookingStartDateTime", txtStartDateTime.getText().toString());
headers.put("BookingEndDateTime", txtEndDateTime.getText().toString());
final ProgressDialog progress = SupportMethods.showProgressDialog(context);
progress.show();
new CustomRequest(new StringRequestCompleteListener() {
#Override
public void onTaskCompleted(String response) {
progress.dismiss();
if (response.equals("800")) {
Toast.makeText(context, "Location Already Booked On Given Time, \n Please Select Any Other Time Or Location", Toast.LENGTH_LONG).show();
} else if (response.equals("400")) {
Toast.makeText(context, "Error Occurred While Booking, Please Try Again", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(context, "Location Booked Successfully", Toast.LENGTH_LONG).show();
startActivity(new Intent(context, ActivityDrawer.class)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP));
startService(new Intent(context, BackgroundUpdateService.class).putExtra(Constants.UPDATE,Constants.BOOKING_UPDATE));
}
}
}).loadJSON(headers, context, progress);
AndroidManifest.xml
add this permission
<uses-permission android:name="android.permission.INTERNET" />
add ApplicationController to Application Tag
<application
android:name=".support.volley.ApplicationController"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:largeHeap="true"
android:supportsRtl="true"
android:theme="#style/AppTheme"><application>
You used this for Http..
httpclient-4.2.3.jar Download Link For Httpclient-4.2.3.jar
apache-httpcomponents-httpcore.jar Download Link for apche-httpcomponents
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());
}
}