I am not able to get success response status code from response like 200,201.. etc. As we can easily get error codes from RetrofitError class like error.isNetworkError() and error.getResponse().getStatus(). Is there any workaround for getting status codes?
As per Retrofit 2.0.2, the call is now
#Override
public void onResponse(Call<YourModel> call, Response<YourModel> response) {
if (response.code() == 200) {
// Do awesome stuff
} else {
// Handle other response codes
}
}
Hope it helps someone :-)
EDIT: Many apps could also benefit from just checking for success (response code 200-300) in one clause, and then handling errors in other clauses, as 201 (Created) and 202 (Accepted) would probably lead to the same app logic as 200 in most cases.
#Override
public void onResponse(Call<YourModel> call, Response<YourModel> response) {
if (response.isSuccessful()) {
// Do awesome stuff
} else if (response.code() == 401) {
// Handle unauthorized
} else {
// Handle other responses
}
}
You can get the status code in success() just like you do it in failure()
#Override
public void success(Object object, Response response) {
response.getStatus() // returns status code integer
}
Since you have a Response object in success callback as response.getStatus()
EDIT
I assume you are using okhttp with retrofit.
okhttp has a powerful tool called Interceptor
You can catch the response before retrofits Callback and get status code from the response:
OkHttpClient client = new OkHttpClient();
client.interceptors().add(new Interceptor(){
#Override
public Response intercept(Chain chain) throws IOException{
Request request = chain.request();
Response response = chain.proceed(request);
response.code()//status code
return response;
});
// then add it to you Restclient like this:
restAdapter = new RestAdapter.Builder()
.setEndpoint(URL_SERVER_ROOT)
.setClient(new OkClient(client)) //plus your configurations
.build();
To learn more about interceptors visit here.
i achieved it by following codes:
public abstract class BaseCallBack<T> {
public abstract void onSuccess(Response<T> response);
public abstract void onFailure(Response<T> response);
}
public abstract class SuccessCallback<T> extends BaseCallBack<T> implements Callback<T>{
#Override
public void onResponse(Call<T> call, Response<T> response) {
if(response.code()>= 400 && response.code() < 599){
onFailure(response);
}
else {
onSuccess(response);
}
}
#Override
public void onFailure(Call<T> call, Throwable t){
}
#Override
public void onSuccess(Response<T> response) {
}
#Override
public void onFailure(Response<T> response) {
}
}
When the rest api returns 400 etc then the onFailure method will be call by default. If you wanna do something onsuccess:(when returns 200 etc)
ServiceConnector.api.getHomePage().enqueue(new SuccessCallback<Void>() {
#Override
public void onSuccess(Response<Void> response) {
super.onSuccess(response);
}
});
you should get exception code iin onError response
HttpException httpException =((HttpException) e).code();
Related
I'm very new to android development. Trying to connect some site and get data from it. I have this function called only from onCreate in the main activity. Every time I turn virtual Android phone left or right I see new "run()" strings in EditText and requests in Wireshark. How to stop that properly?
Tried call.cancel() and mClient.dispatcher().cancelAll() inside OnResponse
protected void Load(String url) {
Request request = new Request.Builder()
.url(url)
.build();
mClient.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
#Override
public void onResponse(Call call, final Response response) throws IOException {
if (response.isSuccessful()) {
mHandler.post(new Runnable() {
#Override
public void run() {
mEdit.setText(mEdit.getText() + "run()\n");
}
});
}
}
});
}
retrofit supports enqueue canceling, and it works great.
And i think if you will try to run this code - your client enqueues would be stoped
protected void Load(String url) {
Request request = new Request.Builder()
.url(url)
.build();
Call<Response> mCall = mClient.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
if (call.isCanceled()) {
Log.e(TAG, "request was cancelled");
}
else {
Log.e(TAG, "other larger issue, i.e. no network connection?");
}
}
#Override
public void onResponse(Call call, final Response response) throws IOException {
if (response.isSuccessful()) {
mHandler.post(new Runnable() {
#Override
public void run() {
mEdit.setText(mEdit.getText() + "run()\n");
}
});
}
}
});
mCall.cancel();
}
I don't know you project structure and what kind of patterns you using(MVP, MVVM or else), but in simple, this code can be improved by returning Call
protected void Load(String url): Call<Response>
And then you can hadle you request status, and if it longer than 5 seconds for example, you call call.cancel() and request is stopping.
onCreate is called every time configuration changes (for example you rotate your phone/emulator). For more info: https://developer.android.com/guide/components/activities/activity-lifecycle
You can save your response to prevent new request on every onCreate. Something like this:
MainActivity {
private Response savedResponse;
onCreate() {
if (savedResponse == null) {
Load(url)
}
}
}
and in your onResponse save the response:
#Override
public void onResponse(Call call, final Response response) throws IOException {
if (response.isSuccessful()) {
savedResponse = response; // <----
mHandler.post(new Runnable() {
#Override
public void run() {
mEdit.setText(mEdit.getText() + "run()\n");
}
});
}
}
However, correct way would be to separete network calls/requests from activity lifecycle and load data somewhere else (Service, WorkManager, ...)
I am using retrofit 2.
When i receive an unsuccessful response do i have to close manually
the erroBody();
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (response.isSuccessful()) {
// Success
} else {
response.errorBody().close(); ???????????????????
}
}
No. There's no need to call response.errorBody().close(), during an unsuccessful response. In the same way, there's no need to call response.raw().close(); during a successful response.
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(#NonNull Call<ResponseBody> call,
#NonNull Response<ResponseBody> response) {
if (response.isSuccessful()) {
// successful response from server: HTTP status code is between 200 and 300
// log user in, etc
} else {
// unsuccessful response from server: HTTP status code is not between 200 and 300
// show toast, call onBackPressed(), etc
}
}
#Override
public void onFailure(#NonNull Call<ResponseBody> call, #NonNull Throwable t) {
// network exception occurred while talking to the server
// or an unexpected exception occurred while creating the request or processing the response
// Log.d(...);
}
});
I would like to handle my response from server , but I don't know how JSON (from server) its looks like. So I tried to display response as String , but I cant do it. Is it possible to display response as String? And then handle the response correctly. thanks
(Retrofit 1.9)
LoginService loginService = RetrofitClient.createService(LoginService.class);
loginService.searchOffer(getToken(), offerSearch, new Callback<String>() {
#Override
public void success(String offerSearchRequestResource, Response response) {
String responseFromSercer = response.getBody();
}
#Override
public void failure(RetrofitError error) {
}
});
change your response model to
JSONObject (from Gson)
then in your
public void success(...){response.body.toString();}
like this:
Call<JsonObject> call = YOUR_API_INTERFACE().YOUR_METHOD(YOUR_PARAMS);
call.enqueue(new Callback<JsonObject>() {
#Override
public void onResponse(Call<JsonObject> call, #NonNull Response<JsonObject> response) {
if(response.isSuccessful()) {
String responseFromSercer = response.body.toString();
}
}
#Override
public void onFailure(Call<JsonObject> call, Throwable t) {
.....
}
});
If you are sure the request runs successfully and there is a response back...use
System.out.println(response.getBody());
i'd also suggest you add Logging Interceptors here so that you can get a detailed view of all your API calls
I have an issue trying to use Okhttp with retrofit. I seem not to understand what I am doing wrong.
It gives showing up error: 'Anonymous class derived from Callback' must either be declared abstract or implement abstract method 'onResponse(Response<T>, Retrofit)' in 'Callback'
In my MainActivity I have this:
OkHttpClient httpClient = new OkHttpClient();
httpClient.interceptors().add(new Interceptor() {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request original = chain.request();
Request request = original.newBuilder()
.header("User-Agent", "Your-App-Name")
.header("Content-Type", "application/json")
.header("Authorization","authorization_code")
.method(original.method(), original.body())
.build();
return chain.proceed(request);
}
});
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient)
.build();
TestInterface service = retrofit.create(TestInterface.class);
Call<TestData> call = service.getPost();
/* It keeps pointing at this line below:
'Callback' must either be declared abstract" */
call.enqueue(new Callback<TestData>() {
#Override
public void onResponse(Response<TestData> response, Retrofit retrofit) {
// Get result Repo from response.body()
// response.isSuccess() is true if the response code is 2xx
int statusCode = response.code();
if (response.isSuccess()) {
System.out.println("Success: ");
} else {
}
}
#Override
public void onFailure(Throwable t) {
System.out.println("failed: "+t);
}
});
In my TestData Interface,I have this
public interface TestInterface {
#POST("/paths_to_web_directory")
Call<TestData>
getPost();
}
This is the way i see it done in other examples, So maybe i'm implementing it the wrong way. Kindly correct me. Thanks
The retrofit github project has a sample with a different method signature. Try this:
call.enqueue(new Callback<TestData>() {
#Override public void onResponse(Call<TestData> call, Response<TestData> response) {
}
#Override public void onFailure(Call<TestData> call, Throwable t) {
}
});
I am using Retrofit 1.9 in a big project and must check some data from response header even if call is failed - to analyse request code for example. We already know structure for async calls:
RestClient.get().asyncRequest(requestParams, new Callback<GenericResponse>() {
#Override
public void success(MyPojo pojo, Response response) {
//we can use pojo object or use whole response
}
#Override
public void failure(RetrofitError error) {
//we can handle only error but NOT response
}
});
How can we analyse Response in both cases here?
One solution is to use Profiler when RestAdapter is created, smth like:
RestAdapter restAdapter = new RestAdapter.Builder()
//other stuff
.setProfiler(new Profiler() {
#Override
public Object beforeCall() {
return null;
}
#Override
public void afterCall(RequestInformation requestInfo, long elapsedTime, int statusCode, Object beforeCallData) {
//get what I need
}
})
.build();
But maybe there is another solution to get response in failure() method. Any advices wil be apreciated!
You can get response body retriving it from RetrofitError.
#Override
public void failure(RetrofitError error) {
//here you get your response
Response response = error.getResponse();
//use data from response
int code = response.getStatus();
List<Header> = response.getHeaders();
// ...
}
I think this will solve your problem
RestAdapter restAdapter = new RestAdapter.Builder()
//other stuff
.setProfiler(new Profiler() {
#Override
public Object beforeCall() {
return null;
}
#Override
public void afterCall(RequestInformation requestInfo, long elapsedTime, int statusCode, Object beforeCallData) {
//get what I need
}
})
.setLogLevel(RestAdapter.LogLevel.FULL).build();
Now you can get the response
public void failure(RetrofitError error) {
String json = new String(((TypedByteArray)error.getResponse().getBody()).getBytes());
Log.v("failure", json.toString());
}
failure method in retrofit only tells the error occurred if want to see you can check that the arguments of error method in retrofit or you can call again the service if you want to call again when it comes to failure.