How to read the String response from Retrofit - android

I need to handle a functionality based on the retrofit response.
The post method has the request as json format and getting the response as Text true
I have tried to get this response as the following code snippet. But always I get false though I get true in postman response.
private void callPostLoginAPI(String webServiceResponse) {
ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class);
Call<ResponseBody> result = apiService.getPostDealer(postLoginAPI(webServiceResponse));
result.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
String postLoginResponse = null;
try {
postLoginResponse = response.body().string();
} catch (IOException e) {
e.printStackTrace();
}
if (postLoginResponse != null || (!postLoginResponse.equals(""))) {
if (postLoginResponse.equals("true")) {
try {
if (PreferenceClass.getInstallationID(Loginpage.this) == null ||
PreferenceClass.getInstallationID(Loginpage.this).equals("")) {
request_appInstallation_API(0);
} else {
checkAppUpdate();
}
} catch (Exception e) {
e.printStackTrace();
}
} else {
Toast.makeText(Loginpage.this, "Please contact CMS Admin", Toast.LENGTH_LONG).show();
}
} else {
Toast.makeText(Loginpage.this, "Something went wrong... Please try again", Toast.LENGTH_LONG).show();
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Toast.makeText(Loginpage.this, t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
UPDATE:
As I tried the following,and I havent gotten the respective "Postman response value" .
ApiInterface apiService = ApiClient.getClient1().create(ApiInterface.class);
Call<Boolean> result = apiService.getPostDealer(postLoginAPI(webServiceResponse));
result.enqueue(new Callback<Boolean>() {
#Override
public void onResponse(Call<Boolean> call, Response<Boolean> response) {
Log.i("Response", response.body().toString());
if (response.isSuccessful()) {
if (response.body() != null) {
Log.i("callPostLoginAPI", response.body().toString());
Toast.makeText(Dealer_Loginpage.this, "returned", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(Dealer_Loginpage.this, "Nothing returned", Toast.LENGTH_LONG).show();
}
}
}
#Override
public void onFailure(Call<Boolean> call, Throwable t) {
Toast.makeText(Dealer_Loginpage.this, "Nothing returned", Toast.LENGTH_LONG).show();
}
});
ApiClient.getClient1() :
public static Retrofit getClient1() {
if (retrofit1 == null) {
retrofit1 = new Retrofit.Builder().baseUrl(GlobalClass.sBase_Url).
addConverterFactory(ScalarsConverterFactory.create()).
addConverterFactory(GsonConverterFactory.create()).build();
}
return retrofit1;
}

Solution:
Attach this:
postLoginResponse.replaceAll("[^A-Za-z]+", "");
After the line:
postLoginResponse = response.body().string();
and try.

Related

Access Raw Response After Conversion

I've a backend that returns 200 HTTP code even if the request had errors:
{
"error": {
"message": "Generic error",
"code": 13000
}
}
Now, how can I access raw response body, after using:
.addConverterFactory(GsonConverterFactory.create(gson))
I've tried:
response.raw().body().string()
But I get:
java.lang.IllegalStateException: Cannot read raw response body of a converted body.
I've implemented a generic APICallback class, that should "block" the success and fire an APIError event:
abstract class APICallback<T> implements Callback<T> {
abstract void onSuccess(Call<T> call, T result);
#Override
public void onResponse(Call<T> call, Response<T> response) {
if (response.body() != null) {
if (response.body() instanceof APIError) {
// this is not working
} else {
onSuccess(call, response.body());
}
} else {
apiError = new APIError("Unknown error");
bus.post(new APIErrorEvent(apiError));
}
}
#Override
public void onFailure(#NonNull Call<T> call, #NonNull Throwable t) {
String message = t.getLocalizedMessage() != null ? t.getLocalizedMessage() : "Unknown error";
apiError = new APIError(message);
bus.post(new APIErrorEvent(apiError, source));
}
}
I'd like to mantain the "auto-converter" capability...many thanks in advance.
For error response you have to take response.errorBody() not response.body()
abstract class APICallback<T> implements Callback<T> {
abstract void onSuccess(Call<T> call, T result);
#Override
public void onResponse(Call<T> call, Response<T> response) {
if (response.body() != null) {
if (response.body() instanceof APIError) {
// this is not working
} else {
onSuccess(call, response.body());
}
} else {
apiError = new APIError("Unknown error");
bus.post(new APIErrorEvent(apiError));
}
}
#Override
public void onFailure(#NonNull Call<T> call, #NonNull Throwable t) {
String message = t.getLocalizedMessage() != null ? t.getLocalizedMessage() : "Unknown error";
apiError = new APIError(message);
bus.post(new APIErrorEvent(apiError, source));
}
}
change to
abstract class APICallback<T> implements Callback<T> {
abstract void onSuccess(Call<T> call, T result);
#Override
public void onResponse(Call<T> call, Response<T> response) {
if (response.isSuccessful()) {
if (response.body() != null) {
onSuccess(call, response.body());
}
} else {
if (response.errorBody() != null) {
if (response.errorBody() instanceof APIError) {
}
} else {
apiError = new APIError("Unknown error");
bus.post(new APIErrorEvent(apiError));
}
}
}
#Override
public void onFailure(#NonNull Call<T> call, #NonNull Throwable t) {
String message = t.getLocalizedMessage() != null ? t.getLocalizedMessage() : "Unknown error";
apiError = new APIError(message);
bus.post(new APIErrorEvent(apiError, source));
}
}

retrofit2 get json object without jsonArray name

I want to take jsonobject using retrofit without class definition, the result is null. How about this ?
I have a get query with JSON response :
[{"Kuota":"12"}]
This my code get data JSONObject .
public void GetKuota(String Key) {
IBookingService iBookingService = APIClient.getClient().create(IBookingService.class);
Call<ResponseBody> call = iBookingService.getKuota(Key);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if(!response.isSuccessful()) {
JSONObject jsonObject;
try {
jsonObject = new JSONObject(response.body().toString());
// Log.d(jsonObject.getString("Kuota"));
datas =String.valueOf(jsonObject.getInt("Kuota"));
} catch (JSONException e) {
e.printStackTrace();
}
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
}
});
}
Suggestion:
Create a model class, lets say Kuota
public class Kuota {
public int Kuota;
}
Then rewrite the Retrofit callback like this.
iBookingService.getKuota(Key).enqueue(new Callback<List<Kuota>>() {
#Override
public void onResponse(Call<List<Kuota>> call, Response<List<Kuota>> response) {
if(response.code() == 200 && response.body() != null) {
try {
for(Kuota k: response.body()) {
Log.d("Kuota Value" , " " + k.kuota);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
#Override
public void onFailure(Call<List<Kuota>> call, Throwable t) {
}
});
Replace iBookingService data holder from ResponseBody to List< Kuota >
if not added, please add the JSON serializer while setting up Retrofit instance.
new Retrofit.Builder()
.......
.addConverterFactory(GsonConverterFactory.create())
.build();
And also add the dependency
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'

how to make generic retrofit library for api calling

i'm working on API integration. i want to make generic class for API integration. which can comfortable with for all API integration.right now i'm using separate code for all API. i'm new in android application development. so please guide me.
public void getHomeCategoryDetailApi(Context context) {
final ProgressDialog loadingDialog = ProgressDialog.show(context, "Please wait", "Loading...");
Retrofit restAdapter = ApiLists.retrofit;
ApiLists apiCall = restAdapter.create(ApiLists.class);
Call<HomeCategoryModelClass> call = apiCall.homePageCatListAPI();
Log.d(TAG, "CategoryDetail : " + call.request()+" \n"+apiCall.homePageCatListAPI().toString());
call.enqueue(new Callback<HomeCategoryModelClass>() {
#Override
public void onResponse(Call<HomeCategoryModelClass> call, Response<HomeCategoryModelClass> response) {
Log.d(TAG, "onResponse: CategoryDetail:" + response.body());
Log.d(TAG, "onResponse: response.code():" + response.code());
if (response.body() == null) {
loadingDialog.dismiss();
globalClass.showAlertDialog(getActivity(), getString(R.string.InternetAlert), getString(R.string.InternetMessage), false);
} else {
loadingDialog.dismiss();
if (response.body().getStatusCode().equalsIgnoreCase("1")) {
homeCategoryImageMenu = (ArrayList<Menu>) response.body().getMenu();
thirdHorizontalRecyclerAdapter.notifyDataSetChanged();
} else {
globalClass.showAlertDialog(getActivity(), "Alert", "" + response.body().getStatus(), false);
}
}
if (response.errorBody() != null) {
try {
Log.d(TAG, "onResponse: response.errorBody()===>" + response.errorBody().string());
if (loadingDialog.isShowing() && loadingDialog != null) {
loadingDialog.dismiss();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public void onFailure(Call<HomeCategoryModelClass> result, Throwable t) {
Log.d(TAG, "onFailure: " + result.toString());
loadingDialog.dismiss();
globalClass.showAlertDialog(getActivity(), getString(R.string.InternetAlert), getString(R.string.InternetMessage), false);
}
});
}
Here is Bast Way to call API
public class APIResponse {
private static String TAG = APIResponse.class.getSimpleName();
public static <T> void callRetrofit(Call<T> call, final String strApiName, Context context, final ApiListener apiListener) {
final ProgressDialog progressDialog = new ProgressDialog(context);
progressDialog.setMessage("Loading...");
progressDialog.setCancelable(false);
progressDialog.show();
call.enqueue(new Callback<T>() {
#Override
public void onResponse(Call<T> call, Response<T> response) {
if (strApiName.equalsIgnoreCase("LoginApi")) {
if (response.isSuccessful()) {
Log.d(TAG, "onResponse: " + response.body().toString());
// NearByNurse nearByNurse = (NearByNurse) response.body(); // use the user object for the other fields
// apiListener.success(url,nearByNurse);
progressDialog.dismiss();
} else {
try {
Log.d(TAG, "onResponse: " + response.errorBody().string());
apiListener.error(strApiName, response.errorBody().string());
progressDialog.dismiss();
} catch (IOException e) {
e.printStackTrace();
}
}
} else if (strApiName.equalsIgnoreCase("")) {
//Patient user = (Patient) response.body();
}
}
#Override
public void onFailure(Call<T> call, Throwable t) {
Log.d(TAG, "onFailure: " + t.toString());
if (strApiName.equalsIgnoreCase("searchNearbyTest")) {
apiListener.failure(strApiName, t.toString());
}
progressDialog.dismiss();
}
});
}
In API Calling Side
private void loginApi() {
Retrofit retrofit = ApiLists.retrofit;
ApiLists apiList = retrofit.create(ApiLists.class);
Call<JsonElement> loginApiCall = apiList.loginApi("kjdf", "fkldngdkl", "lkfdxngl", "kjngn", "jksdgkj");
APIResponse.callRetrofit(loginApiCall, "LoginApi", LoginActivity.this, this);
}
#Override
public void success(String strApiName, Object response) {
if (strApiName.equals("LoginApi")) {
}
}
#Override
public void error(String strApiName, String error) {
if (strApiName.equals("LoginApi")) {
}
}
#Override
public void failure(String strApiName, String message) {
if (strApiName.equals("LoginApi")) {
}
and interface call on API response.
public interface ApiListener {
void success(String strApiName, Object response);
void error(String strApiName, String error);
void failure(String strApiName, String message);
}
This's my common function basic call Api.java
public class Api {
private void basicCall(Call<DataResponse> call) {
if (call == null) {
listener.onResponseCompleted(Config.STATUS_404, "404 not found", null);
return;
}
call.enqueue(new Callback<DataResponse>() {
#Override
public void onResponse(#NonNull Call<DataResponse> call, #NonNull Response<DataResponse> response) {
int code = response.code();
//Check http ok
if (code == HttpURLConnection.HTTP_OK) {
//Check status
if (response.body().getStatus() == Config.STATUS_OK) {
//Everything's OK
listener.onResponseCompleted(Config.STATUS_OK, response.body().getError(), response.body().getData());
} else {
listener.onResponseCompleted(Config.STATUS_FAILED, response.body().getError(), null);
}
} else if (code == HttpURLConnection.HTTP_UNAUTHORIZED) {
try {
ErrorResponse error = Api.gson.fromJson(response.errorBody().string(), ErrorResponse.class);
listener.onResponseCompleted(Config.STATUS_401, error.getError(), error.getData());
} catch (IOException e) {
e.printStackTrace();
}
} else {
listener.onResponseCompleted(Config.STATUS_404, "404 not found", null);
}
}
#Override
public void onFailure(#NonNull Call<DataResponse> call, #NonNull Throwable t) {
listener.onResponseCompleted(Config.STATUS_404, "404 not found", null);
}
});
}
//And you can use
public void getProductList(OnResponseCompleted listener) {
this.listener = listener;
Call<DataResponse> call = apiService.getProductList();
basicCall(call);
}
}
//or orther function
This's ApiService.java
public interface ApiInterface {
#POST("product/list")
Call<DataResponse> getProductList();
}
This's OnResponseCompleted.java
public interface OnResponseCompleted {
void onResponseCompleted(int status, String error, Object data);
}
i want to make like this .i just pass some require parameter....
public void showAlertDialog(Context context, String title, String message,
Boolean status) {
AlertDialog alertDialog = new AlertDialog.Builder(context).create();
alertDialog.setTitle(title);
// Set Dialog Message
alertDialog.setMessage(message);
alertDialog.setCancelable(false);
if (status != null)
// Set alert dialog icon
alertDialog.setIcon((status) ? R.drawable.ic_success : R.drawable.ic_fail);
// Set OK Button
alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
});
// Show Alert Message
alertDialog.show();
}
Try this code..
In this code Retrofit object set up done in one class and all api calling into interface..
public class ApiClient {
private final static String BASE_URL = "https://api.github.com";
public static ApiClient apiClient;
private Retrofit retrofit = null;
public static ApiClient getInstance() {
if (apiClient == null) {
apiClient = new ApiClient();
}
return apiClient;
}
//private static Retrofit storeRetrofit = null;
public Retrofit getClient() {
return getClient(null);
}
private Retrofit getClient(final Context context) {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder client = new OkHttpClient.Builder();
client.readTimeout(60, TimeUnit.SECONDS);
client.writeTimeout(60, TimeUnit.SECONDS);
client.connectTimeout(60, TimeUnit.SECONDS);
client.addInterceptor(interceptor);
client.addInterceptor(new Interceptor() {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
return chain.proceed(request);
}
});
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client.build())
.addConverterFactory(GsonConverterFactory.create())
.build();
return retrofit;
}
}
after that call the api into api interface..
public interface ApiInterface {
#GET("{affenpinscher}/images")
Call<Product> getProductData(#Path("affenpinscher") String breed);
#GET("getProductDetailByProductId?ProductId=3")
Call<JsonObject> ITEM_DESCRIPTION_RESPONSE_CALL();
#POST("linke")
Call<Response> passJsonData(#Body JsonData jsonData);
#GET("/users/waadalkatheri/repos")
Call<Response> getdata();
}
and when you call api in activity or fragment used below code..
ApiInterface apiInterface = ApiClient.getInstance().getClient().create(ApiInterface.class);
Call<ResponseData> responseCall = apiInterface.getdata();
responseCall.enqueue(new Callback<ResponseData>() {
#Override
public void onResponse(Call<ResponseData> call, retrofit2.Response<ResponseData> response) {
if (response.isSuccessful() && response.body() != null && response != null) {
Toast.makeText(getApplicationContext(), "GetData" + response.body().getLanguage(), Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call<ResponseData> call, Throwable t) {
Log.d("Errror", t.getMessage());
}
});

enqueue multiple GET request when using nested retrofit 2.0

I am using Retrofit 2.0 to make api calls with nesting multiple requests. All api's works fine individually.
But when i nested all retrofit, First request execute perfectly but after that when i register second request it's not callback in enqueue method (i.e. it's directly returning null without inserting enqueue's inner methods like onResponse, onFailure)
My Code :-
public class Main2Activity extends AppCompatActivity {
Gson gson;
JSONObject jsonResult=null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
gson=new GsonBuilder().create();
firstRequest(); //-- First retrofit request
}
private void firstRequest() {
Retrofit retrofit=new Retrofit.Builder().baseUrl(getResources().getString(R.string.Api_Url)).addConverterFactory(GsonConverterFactory.create(gson)).build();
CityRetailsApi service = retrofit.create(CityRetailsApi.class);
Call call_first= service.getMainCatFlag();
call_first.enqueue(new Callback() {
#Override
public void onResponse(Call call, Response response) {
Log.d("MainActivity", "Status Code = " + response.code());
if (response.isSuccessful()){
MainCatFlag result = (MainCatFlag) response.body(); //-- Get First request response
JSONObject json2nd = secondRequest(); //-- Second request
}
}
#Override
public void onFailure(Call call, Throwable t) {
Log.d("MainActivity", "Error");
}
});
}
private JSONObject secondRequest() {
try {
Retrofit retrofit=new Retrofit.Builder().baseUrl(getResources().getString(R.string.Api_Url)).addConverterFactory(GsonConverterFactory.create(gson)).build();
CityRetailsApi service = retrofit.create(CityRetailsApi.class);
Call call_second= service.getMainCat();
call_second.enqueue(new Callback() {
#Override
public void onResponse(Call call2, Response response1) {
Log.d("MainActivity", "Status Code = " + response1.code());
if (response1.isSuccessful()) {
MainCat result = (MainCat) response1.body();
if (result.getSuccess()==1)
{
try {
jsonResult= new JSONObject(new Gson().toJson(result));
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
#Override
public void onFailure(Call call, Throwable t) {
Log.d("MainActivity", "Error");
}
});
}catch (Exception e){
Log.d("MainActivity", "Error= " + e);
}
return jsonResult;
}
}
In above code firstRequest() executed correctly and proving response but the secondRequest (inside firstRequest() enqueue method) not working fine. Not showing any error, success message in console. Can any one please help me to override this problem.
If any problem in my code, please let me know.
Thank you in advance.
You made a mistake that when you using retrofit enquene,it's called asynchronously, so you can't get the result outside of the callback method!
So, you should process your result inside the onResponse method like this:
private void secondRequest() {
try {
call_second.enqueue(new Callback() {
#Override
public void onResponse(Call call2, Response response1) {
Log.d("MainActivity", "Status Code = " + response1.code());
if (response1.isSuccessful()) {
MainCat result = (MainCat) response1.body();
if (result.getSuccess()==1)
{
try {
jsonResult= new JSONObject(new Gson().toJson(result));
// process your jsonResult here
...
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
#Override
public void onFailure(Call call, Throwable t) {
Log.d("MainActivity", "Error");
}
});
}catch (Exception e){
Log.d("MainActivity", "Error= " + e);
}
}

Retrofit 2.0 - How to get response body for 400 Bad Request error?

So when I make a POST API call to my server, I get a 400 Bad Request error with JSON response.
{
 "userMessage": "Blah",
"internalMessage": "Bad Request blah blah",
"errorCode": 1
}
I call it by
Call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
//AA
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
//BB
}
}
However the problem is that once I get the response, onFailure() is invoke so that //BB is called. Here, I have no way to access the JSON response.
When I log the api request and response, it doesn't show JSON response at all. And Throwable t is IOException. However, strangely, when I make the same call on Postman, it does return the expected JSON response with 400 error code.
So my question is how can I get the json response when I get 400 Bad Request error? Should I add something to okhttpclient?
Thanks
You can do it in your onResponse method, remember 400 is a response status not an error:
if (response.code() == 400) {
Log.v("Error code 400",response.errorBody().string());
}
And you can handle any response code except 200-300 with Gson like that:
if (response.code() == 400) {
Gson gson = new GsonBuilder().create();
ErrorPojoClass mError=new ErrorPojoClass();
try {
mError= gson.fromJson(response.errorBody().string(),ErrorPojoClass.class);
Toast.makeText(context, mError.getDescription(), Toast.LENGTH_LONG).show();
} catch (IOException e) {
// handle failure to read error
}
}
Add this to your build.gradle : compile 'com.google.code.gson:gson:2.7'
If you want create Pojo class go to Json Schema 2 Pojo and paste your example Json response. Select source type Json and annotation Gson .
You can try the below code to get 400 response. You can get error response from errorBody() method.
Call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
//get success and error response here
if (response.code() == 400) {
if(!response.isSuccessful()) {
JSONObject jsonObject = null;
try {
jsonObject = new JSONObject(response.errorBody().string());
String userMessage = jsonObject.getString("userMessage");
String internalMessage = jsonObject.getString("internalMessage");
String errorCode = jsonObject.getString("errorCode");
} catch (JSONException e) {
e.printStackTrace();
}
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
//get failure response here
}
}
}
EDIT: Fixed method name from toString to string
Handle ErrorResponse with your class object
Kotlin
val errorResponse = Gson().fromJson(response.errorBody()!!.charStream(), ErrorResponse::class.java)
Java
ErrorResponse errorResponse = new Gson().fromJson(response.errorBody.charStream(),ErrorResponse.class)
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
DialogHelper.dismiss();
if (response.isSuccessful()) {
// Success
} else {
try {
JSONObject jObjError = new JSONObject(response.errorBody().string());
Toast.makeText(getContext(), jObjError.getString("message"), Toast.LENGTH_LONG).show();
} catch (Exception e) {
Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_LONG).show();
}
}
}
First step:
Create your POJO class for error response. In my case, ApiError.java
public class ApiError {
#SerializedName("errorMessage")
#Expose
private String errorMessage;
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage= errorMessage;
}
}
Second Step:
Write below code in your api callback.
Call.enqueue(new Callback<RegistrationResponse>() {
#Override
public void onResponse(Call<RegistrationResponse> call, Response<RegistrationResponse> response)
{
if (response.isSuccessful()) {
// do your code here
} else if (response.code() == 400) {
Converter<ResponseBody, ApiError> converter =
ApiClient.retrofit.responseBodyConverter(ApiError.class, new Annotation[0]);
ApiError error;
try {
error = converter.convert(response.errorBody());
Log.e("error message", error.getErrorMessage());
Toast.makeText(context, error.getErrorMessage(), Toast.LENGTH_LONG).show();
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public void onFailure(Call<RegistrationResponse> call, Throwable t) {
//do your failure handling code here
}
}
Here ApiClient.retrofit is your retrofit instance which is static.
I got similar issue, but existing code was stick to RxJava 2 chain.
Here's my solution:
public static <T> Observable<T> rxified(final Call<T> request, final Class<T> klazz) {
return Observable.create(new ObservableOnSubscribe<T>() {
AtomicBoolean justDisposed = new AtomicBoolean(false);
#Override
public void subscribe(final ObservableEmitter<T> emitter) throws Exception {
emitter.setDisposable(new Disposable() {
#Override
public void dispose() {
request.cancel();
justDisposed.set(true);
}
#Override
public boolean isDisposed() {
return justDisposed.get();
}
});
if (!emitter.isDisposed())
request.enqueue(new Callback<T>() {
#Override
public void onResponse(Call<T> call, retrofit2.Response<T> response) {
if (!emitter.isDisposed()) {
if (response.isSuccessful()) {
emitter.onNext(response.body());
emitter.onComplete();
} else {
Gson gson = new Gson();
try {
T errorResponse = gson.fromJson(response.errorBody().string(), klazz);
emitter.onNext(errorResponse);
emitter.onComplete();
} catch (IOException e) {
emitter.onError(e);
}
}
}
}
#Override
public void onFailure(Call<T> call, Throwable t) {
if (!emitter.isDisposed()) emitter.onError(t);
}
});
}
});
}
transforming 400-like responses into rx chain is pretty simple:
Call<Cat> request = catApi.getCat();
rxified(request, Cat.class).subscribe( (cat) -> println(cat) );
Here is the simplest solution,
If you want to handle the response from onFailure method:
#Override
public void onFailure(Call<T> call, Throwable t) {
HttpException httpException = (HttpException) t;
String errorBody = httpException.response().errorBody().string();
// use Gson to parse json to your Error handling model class
ErrorResponse errorResponse = Gson().fromJson(errorBody, ErrorResponse.class);
}
Or if you are using rxjava Observable with Kotlin, handle it from error body:
{ error ->
val httpException :HttpException = error as HttpException
val errorBody: String = httpException.response().errorBody()!!.string()
// use Gson to parse json to your Error handling model class
val errorResponse: ErrorResponse =
Gson().fromJson(errorBody, ErrorResponse::class.java)
}
Don't forget to properly handle json to class conversion (use try-catch if not sure).
simply use
if (throwable is HttpException && (throwable!!.code() == 400 || throwable!!.code()==404)){
var responseBody = throwable!!.response()?.errorBody()?.string()
val jsonObject = JSONObject(responseBody!!.trim())
var message = jsonObject.getString("message")
tvValMsg.set(message)
}
This is how you can handle the response message
I am handling for error 500 you can add as much you want
switch (response.code()) {
case HttpURLConnection.HTTP_OK:
break;
case HttpURLConnection.HTTP_UNAUTHORIZED:
callback.onUnAuthentic();
break;
case HttpURLConnection.HTTP_INTERNAL_ERROR:
try {
String errorResponse = response.errorBody().string();
JSONObject object = new JSONObject(errorResponse);
String message = "Error";
if (object.has("Message"))
message = String.valueOf(object.get("Message"));
callback.onError(message);
} catch (IOException e) {
e.printStackTrace();
}
break;
case HttpURLConnection.HTTP_GATEWAY_TIMEOUT:
case HttpURLConnection.HTTP_CLIENT_TIMEOUT:
default:
callback.onNetworkError();
break;
}
IF you are getting 400(Bad Request) by using retrofit first make sure are are setting input to API is Only Model class, If not then replace input request by Model class and then check you will get Success response.
#POST("api/users/CreateAccount")
Call<CreateAccount> createAccount(#Body CreateAccount model, #Header("Content-Type") String content_type);

Categories

Resources