I am using retrofit to post the request to server but it is posting data twice. I have checked code, I made only on call. I know retrofit trying to connect server again and again until it connected or timeout but if once data posted to server and I get the response from server than why retrofit making again call for the same.
Call<LoanSaveResponse> call = apiService.saveLoan(loan);
call.enqueue(new retrofit2.Callback<LoanSaveResponse>() {
#Override
public void onResponse(Call<LoanSaveResponse> call, Response<LoanSaveResponse> response) {
customProgressBar.stopProgressBar();
Log.e(" response", new Gson().toJson(response));
if (response != null) {
if (response.body() != null) {
// Showing Alert Message
showDialog(response.body().loan_id);
}
}
}
#Override
public void onFailure(Call<LoanSaveResponse> call, Throwable t) {
customProgressBar.stopProgressBar();
Log.e("Failed", t.toString());
}
});
}
public class ApiClient {
/*http://172.16.40.1:8080/loyalty/*/
//:http://54.83.7.62:8080/loyalty/userAnswer
private static Retrofit retrofit = null;
public static Retrofit getClient() {
if (retrofit==null) {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
retrofit = new Retrofit.Builder()
.baseUrl(GlobalBaseUrl.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
}
return retrofit;
}
}
For Retrofit 2
Define a listener in your web service instance:
public interface OnConnectionTimeoutListener {
void onConnectionTimeout();
}
Add an interceptor to your web service:
public WebServiceClient() {
OkHttpClient client = new OkHttpClient();
client.setConnectTimeout(10, TimeUnit.SECONDS);
client.setReadTimeout(30, TimeUnit.SECONDS);
client.interceptors().add(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
return onOnIntercept(chain);
}
});
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
webService = retrofit.create(WebService.class);
}
Enclose your intercept code with the try-catch block and notify the listener when an exception happens:
private Response onOnIntercept(Chain chain) throws IOException {
try {
Response response = chain.proceed(chain.request());
String content =
UtilityMethods.convertResponseToString(response);
Log.d(TAG, lastCalledMethodName + " - " + content);
return;
response.newBuilder().body
(ResponseBody.create
(response.body().contentType(), content))
.build();}
catch (SocketTimeoutException exception) {
exception.printStackTrace();
if(listener != null)
listener.onConnectionTimeout();
}
return chain.proceed(chain.request());
}
Related
I'm using retrofit to fetch some data from a remote server, when the response code is something other than 200 for success, the body returns as null.
I found out in this case I should get my result from response.errorBody() but it returned in a raw JSON form of course, is there anyway to map it automatically using the GsonConverterFactory that I included in my retrofit instance?
mApiServices.register(builder.build()).enqueue(new Callback<LoginModel>() {
#Override
public void onResponse(Call<LoginModel> call, Response<LoginModel> response) {
if (response.code() == 200 && response.body() != null && response.body().getStatus() == 1) {
LoginModel.Data data = response.body().getData();
mDataLiveData.setValue(data);
saveToSharedPref(data);
} else {
String errorBody = null;
try {
errorBody = response.errorBody().string();
} catch (IOException e) {
e.printStackTrace();
}
}
resetIsLoading();
}
#Override
public void onFailure(Call<LoginModel> call, Throwable t) {
mGeneralError.setValue(t.getMessage());
resetIsLoading();
}
});
And here's how I instantiated the Retrofit instance
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request().newBuilder().addHeader("lang", PreferenceUtils.getLocaleKey(context)).build();
return chain.proceed(request);
}
}).build();
retrofit = new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
return retrofit;
I'm new to android development and trying to learn it. I recently ran into an issue, when I use get method I get a response as below:
As there is a status given as '0' from the backend I'm unable to catch the "response_data" array.
Could anyone please guide me how can I catch the response.
Thanks.
API CLIENT:
public class ApiClient {
private final static String BASE_URL = "http://api.xxxxxx.com/app/";
public static ApiClient apiClient;
private Retrofit retrofit = null;
public static ApiClient getInstance() {
if (apiClient == null) {
apiClient = new ApiClient();
}
return apiClient;
}
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;
}
}
MAIN ACTIVITY:
public class MainActivity extends AppCompatActivity {
TextView tvResponse;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvResponse=findViewById(R.id.tvResponse);
ApiInterface apiInterface = ApiClient.getInstance().getClient().create(ApiInterface.class);
Call<ResponseData> responseDataCall=apiInterface.getData();
responseDataCall.enqueue(new Callback<ResponseData>() {
#Override
public void onResponse(Call<ResponseData> call, Response<ResponseData> response) {
if (response.isSuccessful() && response.body()!=null && response!=null){
List<ResponseDataItem> data=response.body().getResponseData();
}
}
#Override
public void onFailure(Call<ResponseData> call, Throwable t) {
t.printStackTrace();
}
});
}
}
RESPONSE DATA:
public class ResponseData {
#SerializedName("response_data")
private List<ResponseDataItem> responseData;
#SerializedName("status")
private int status;
public void setResponseData(List<ResponseDataItem> responseData){
this.responseData = responseData;
}
public List<ResponseDataItem> getResponseData(){
return responseData;
}
public void setStatus(int status){
this.status = status;
}
public int getStatus(){
return status;
}
}
In this case you need to let Gson know how you want to parse your json.
You can add many specific TypeAdapter's for each specific class case or you can create one TypeAdapterFactory that will be used to parse all your jsons. Remember to add it to your Retrofit builder.
This code example is a TypeAdapterFactory that will ignore status and parse only response_data to your object.
class ResponseDataTypeAdapterFactory implements TypeAdapterFactory {
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);
TypeAdapter<JsonElement> elementTypeAdapter = gson.getAdapter(JsonElement.class);
return new TypeAdapter<T>() {
public void write(JsonWriter out, T value) throws IOException {
delegate.write(out, value);
}
public T read(JsonReader reader) throws IOException {
JsonElement jsonElement = elementTypeAdapter.read(reader);
if (jsonElement.isJsonObject()) {
JsonObject jsonObject = jsonElement.getAsJsonObject();
if (jsonObject.has("response_data")) {
jsonElement = jsonObject.get("response_data");
}
}
return delegate.fromJsonTree(jsonElement);
}
};
}
}
And on your Retrofit builder
Gson gson = new GsonBuilder()
.registerTypeAdapterFactory(ResponseDataTypeAdapterFactory())
.create();
new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client.build())
.addConverterFactory(new GsonConverterFactory.create(gson))
.build();
And at the Retrofit interface, you only need to call the class that corresponds with response_datamapping.
public interface ApiInterface {
#GET("/product-data")
Call<List<ResponseDataItem>> fetchData();
}
With this implementation, you can remove your ResponseData class and care only about the important model.
Make an interface
public interface ApiInterface {
#GET
Call<JsonElement> getTimeDifference(#Url String url);
}
Crate an Retrofit client calss
public class RetrofitClient {
private static final String TAG = "RetrofitClient";
public static Retrofit geBaseUrl() {
Retrofit retrofit = null;
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
if (BuildConfig.DEBUG) {
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
}else{
interceptor.setLevel(HttpLoggingInterceptor.Level.NONE);
} OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl("...your base url...")
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
String endpoint = "...your end point...";
ApiInterface ret = RetrofitClient.geBaseUrl(url).create(ApiInterface.class);
Call<JsonElement> call = ret.getTimeDifference(endpoint);
call.enqueue(new Callback<JsonElement>() {
#Override
public void onResponse(Call<JsonElement> call, Response<JsonElement> response) {
try {
Log.d("String", "onResponse: response" + response.body().toString());
} catch (Exception e) {
}
}
#Override
public void onFailure(Call<JsonElement> call, Throwable t) {
Log.d("response", "onFailure: " + t + " " + call);
}
});
For Catching response you use interceptor like HttpLoggingInterceptor ,stetho,chuck
Creating the Retrofit instance
// Add the interceptor to OkHttpClient
OkHttpClient client=new OkHttpClient().newBuilder()
.addNetworkInterceptor(new StethoInterceptor()) \\ StethoInterceptor
.addInterceptor(new ChuckInterceptor(context)) \\ ChuckInterceptor
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(5, TimeUnit.MINUTES)
.writeTimeout(5, TimeUnit.MINUTES)
.build();
public static final String BASE_URL = "http://api.myservice.com/";
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
for stetho interceptor
implementation 'com.facebook.stetho:stetho:1.5.0'
implementation 'com.facebook.stetho:stetho-okhttp3:1.5.0'
for chuck
debugImplementation 'com.readystatesoftware.chuck:library:1.1.0'
releaseImplementation 'com.readystatesoftware.chuck:library-no-op:1.1.0'
Below are the files for retrofit.
While passing the data in the form of JSON I am getting a null response.
Could anyone guide where can be the issue occurring?
I am trying to post the data in the form of JSON using the retrofit library. Can you suggest me the right approach?
My code:
public class ApiSellarClient {
public static final String BASE_URL = "Constant.BASE_URL";// it is from constant file..
private static Retrofit retrofit = null;
public static Retrofit getClient() {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
public class ApiSellarConnection {
public static Call<String> getSignInData(JSONObject json) {
return ApiSellarClient.getClient().create(ApiSellarInterface.class).getSignInData(json);
}
}
public interface ApiSellarInterface {
#Headers("Content-Type: application/json")
#POST("integration/customer/token")
Call<String> getSignInData(#Body JSONObject json);
}
// Below is the controller class.
JSONObject paramObject = new JSONObject();
try {
paramObject.put("username", etUserName.getText().toString());
paramObject.put("password", etPassword.getText().toString());
ApiSellarConnection.getSignInData(paramObject).enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
Log.d("tag", "helper" + response.body());
}
#Override
public void onFailure(Call<String> call, Throwable t) {
}
});
} catch (JSONException e) {
e.printStackTrace();
}
I am trying to use an Interceptor to add a header when using Retrofit. I think I have created my Interceptor in the right way but I don't know what should I do to call it and connect it with my GET Retrofit method.
This is my Interceptor:
public class HeaderInterceptor
implements Interceptor {
#Override
public Response intercept(Chain chain)
throws IOException {
Request request = chain.request();
request = request.newBuilder()
.addHeader(Constants.VersionHeader.NAME, Constants.VersionHeader.VALUE)
.addHeader("Authorization", "Bearer " + token)
.addHeader("Origin","MY URL")
.build();
Response response = chain.proceed(request);
return response;
}
}
And this is my interface:
public interface CategoryService {
#GET("/v3/projects/{projectId}/categories/")
Call<ArrayList<Category2>> getProjectCategories(#Path("projectId") String projectId);
}
I also have this client which I don't know if I should use it anymore considering that I am using an Interceptor:
public class CategoryClient {
public static final String BASE_URL = "MY URL";
private static Retrofit retrofit = null;
public static Retrofit getClient() {
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
So I have this GET method getProjectCategories, where I pass the projectID and it returns the contents. What I want to know is how can I call the method using the Interceptor and be able to get the results from the request.
I was able to fix my problem by creating a method called SendNetworkRequest sending the projectId as a parameter, and inside this class I created my OkHttpClient, my Interceptor and my retrofit builder to handle everything that i needed.
private void SendNetworkRequest(String projectID) {
OkHttpClient.Builder okhttpBuilder = new OkHttpClient.Builder();
okhttpBuilder.addInterceptor(new Interceptor() {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Request.Builder newRequest = request.newBuilder().header("Authorization", "Bearer " + token);
return chain.proceed(newRequest.build());
}
});
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl("MY URL")
.client(okhttpBuilder.build())
.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.build();
CategoryService category = retrofit.create(CategoryService.class);
Call<ArrayList<Category2>> call = category.getProjectCategories(projectID, token);
call.enqueue(new Callback<ArrayList<Category2>>() {
#Override
public void onResponse(Call<ArrayList<Category2>> call, Response<ArrayList<Category2>> response) {
listCategories = response.body();
listCategories.remove(response.body().size() - 1);
if (response.body().size() > 0){
add_category_layout.setVisibility(View.VISIBLE);
layout_bar.setVisibility(View.VISIBLE);
message_body.setVisibility(View.INVISIBLE);
message_title.setVisibility(View.INVISIBLE);
edit_image.setVisibility(View.INVISIBLE);
adapter2 = new CategoryAdapter2(getApplicationContext(), listCategories);
recyclerView.setAdapter(adapter2);
recyclerView.setVisibility(View.VISIBLE);
}
}
#Override
public void onFailure(Call<ArrayList<Category2>> call, Throwable t) {
// Log error here since request failed
Log.e(TAG, t.toString());
}
});
}
Callback is not working on some screens sometimes while many times it's working perfectly. I have almost done project with this library. So kindly help
My ApiClient code is:
public class ApiClient {
public static final String BASE_URL = AppUtils.MainURL;
private static Retrofit retrofit = null;
public static Retrofit getClient(final String token) {
OkHttpClient defaultHttpClient = new OkHttpClient.Builder()
.addInterceptor(
new Interceptor() {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request().newBuilder()
.addHeader("AccessToken", token).build();
return chain.proceed(request);
}
}).retryOnConnectionFailure(true).connectTimeout(1, TimeUnit.MINUTES)
.readTimeout(1, TimeUnit.MINUTES)
.writeTimeout(1, TimeUnit.MINUTES).build();
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(defaultHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
and calling method is:
ApiInfo apiService =
ApiClient.getClient(preference.getToken()).create(ApiInfo.class);
Call<JobDetailsResponse> responseCall = apiService.getJobDetails(preference.getLoginId(), preference.getToken(), "" + jobId);
responseCall.enqueue(new Callback<JobDetailsResponse>() {
#Override
public void onResponse(Call<JobDetailsResponse> call, Response<JobDetailsResponse> response) {
progressDialog.dismiss();
JobDetailsResponse jobDetailsResponse = response.body();
}
#Override
public void onFailure(Call<JobDetailsResponse> call, Throwable t) {
progressDialog.dismiss();
}
});