Sometimes Retrofit 2.1.0 callback is not working - android

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();
}
});

Related

How to catch response on get method android 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'

Posting data on django api from retrofit 2 android

I am working on a project which will retrieve and send data to server through django api. I am facing problem to POST data through the api. My codes are given below. Executing this code give 401 Error in response in android studio but the api works fine in postman or web browser. TIA for the help.
Class to set retrofit instance:
public class ApiClient {
public static final String BASE_URL = "https://myapilink.com/";
private static Retrofit retrofit = null;
public static Retrofit getClient() {
final OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
// Request customization: add request headers
Request.Builder requestBuilder = original.newBuilder()
.header("Authorization", "auth-value"); // <-- this is the important line
Request request = requestBuilder.build();
return chain.proceed(request);
}
});
final OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(60, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
// Request customization: add request headers
Request.Builder requestBuilder = original.newBuilder()
.header("Authorization", "Basic YWRtaW46MTIzNA=="); // <-- this is the important line
Request request = requestBuilder.build();
return chain.proceed(request);
}
})
.build();
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
.client(okHttpClient)
.build();
}
return retrofit;
}
Retrofit interface:
public interface ApiInterface {
#Headers("Content-Type: application/json")
#POST("/api/auth/login/")
Call<LoginModel> getLoginResponseWithRetrofit(#Body LoginBody loginBody);
}
LoginBody model:
public class LoginBody {
String email;
String password;
public LoginBody(String email, String password){
this.email=email;
this.password=password;
}
}
Main api calling method:
public void postDataWithRetrofit(String email, String password){
//modelFromIDProvider.add(InternalDataProvider.getInstance().getAgentDataModelList());
int selectedPosition,id;
LoginBody loginBody = new LoginBody(email, password);
ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class);
Call<LoginModel> call;
Map<String, String> formData = new HashMap<>();
formData.put("email", email);
formData.put("password", password);
Log.d(TAG,"formdata "+formData.toString());
//call = apiService.getLoginResponseWithRetrofit(email, password);
call = apiService.getLoginResponseWithRetrofit(loginBody);
call.enqueue(new Callback<LoginModel>() {
#Override
public void onResponse(Call<LoginModel> call, Response<LoginModel> response) {
Log.d(TAG,"isSuccessful "+response.isSuccessful()+" code "+response.code());
Log.d(TAG,"Data from response : "+response.body());
if(!response.isSuccessful()) {
dialog.dismiss();
return;
}
LoginModel responseModel = response.body();
InternalDataProvider.getInstance().setLoginDataModel(responseModel);
Log.d(TAG,"Data from response : "+response.body());
}
#Override
public void onFailure(Call<LoginModel> call, Throwable t) {
if(call.isCanceled()){
Log.d(TAG," call cancelled "+t.toString());
return;
}
Log.d(TAG," inside onFailure "+t.toString());
}
});
}

Efficient Token Refresh using Retrofit

I have a class to handle token refreshes once they expire. The code is below:
public class TokenAuthenticator implements Authenticator {
#Nullable
#Override
public synchronized Request authenticate(#NonNull Route route, #NonNull Response response) throws IOException {
ApiInterface apiInterface = ApiClient.getClient().create(ApiInterface.class);
Call<User> call = apiInterface.refreshTokens(new ClientRequest(Songa.getContext().getString(R.string.client_id),
App.getContext().getString(R.string.client_secret),
App.getContext().getString(R.string.grant_type), getRAGUser().getRefreshToken()));
User ragUser = call.execute().body();
if (ragUser != null) {
Gson gson = new Gson();
String user = gson.toJson(ragUser);
PrefUtils.putString(Constants.USER, user);
long tokenExpiryPeriod = System.currentTimeMillis() + Long.parseLong(ragUser.getExpiryPeriod());
PrefUtils.putLong(Constants.TOKEN_EXPIRY_PERIOD, tokenExpiryPeriod);
return response.request().newBuilder().header("Authorization", "Bearer " + ragUser.getAccessToken()).build();
} else {
if (responseCount(response) >= 3) {
Log.e("TokenAuthenticator", String.valueOf(responseCount(response)));
//we have failed 3 times; log the user out
EventBus.getDefault().post(new LogoutEvent());
return null;
}
}
return null;
}
private int responseCount(Response response) {
int result = 1;
while ((response = response.priorResponse()) != null) {
result++;
}
return result;
}
}
My intention is that once a token expires, the authenticator should retry a maximum of three times before giving up and logging out the user. However, the code below executes each request three times, even with a valid token.
I've always assumed that the Authenticator class only steps in when the token expires but from my logs, I can see that it is called every time a new request is made.
The following is the code from my Retrofit client:
public class RestClient {
private static final String BASE_URL = "https://my.base.url/api/v3/";
private static String token = "Bearer " + getAccessToken();
private static Retrofit retrofit = null;
public RestClient() {
}
public static Retrofit getClient() {
if (retrofit == null) {
TokenAuthenticator tokenAuthenticator = new TokenAuthenticator();
Dispatcher dispatcher = new Dispatcher();
dispatcher.setMaxRequests(1);
Gson gson = new GsonBuilder()
.setExclusionStrategies(new ExclusionStrategy() {
#Override
public boolean shouldSkipField(FieldAttributes f) {
return f.getDeclaringClass().equals(RealmObject.class);
}
#Override
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
}).create();
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient okClient = new OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.authenticator(tokenAuthenticator)
.addInterceptor(loggingInterceptor)
.addInterceptor(chain -> {
Request original = chain.request();
Request request = original.newBuilder()
.addHeader("Authorization", token)
.addHeader("Content-Type", "application/json")
.build();
return chain.proceed(request);
})
.addInterceptor(loggingInterceptor)
.dispatcher(dispatcher)
.build();
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addCallAdapterFactory(RxErrorHandlingCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.client(okClient)
.build();
}
return retrofit;
}
}
Is there a better way of implementing token authentication with my requirements; 3 retries before logout?

Using Interceptors to customize header in Retrofit calls

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());
}
});
}

Retrofit and OkHttp basic authentication

I am trying to add basic authentication (username and password) to a Retrofit OkHttp client. This is the code I have so far:
private static Retrofit createMMSATService(String baseUrl, String user, String pass) {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build();
return retrofit;
}
I am using Retrofit 2.2 and this tutorial suggests using AuthenticationInterceptor, but this class is not available.
Where is the correct place to add the credentials? Do I have to add them to my interceptor, client or Retrofit object? And how do I do that?
Find the Solution
1.Write a Interceptor class
import java.io.IOException;
import okhttp3.Credentials;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
public class BasicAuthInterceptor implements Interceptor {
private String credentials;
public BasicAuthInterceptor(String user, String password) {
this.credentials = Credentials.basic(user, password);
}
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Request authenticatedRequest = request.newBuilder()
.header("Authorization", credentials).build();
return chain.proceed(authenticatedRequest);
}
}
2.Finally, add the interceptor to an OkHttp client
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new BasicAuthInterceptor(username, password))
.build();
Retrofit 2
public class ServiceGenerator {
public static final String API_BASE_URL = "https://your.api-base.url";
private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
private static Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create());
private static Retrofit retrofit = builder.build();
public static <S> S createService(Class<S> serviceClass) {
return createService(serviceClass, null, null);
}
public static <S> S createService(
Class<S> serviceClass, String username, String password) {
if (!TextUtils.isEmpty(username)
&& !TextUtils.isEmpty(password)) {
String authToken = Credentials.basic(username, password);
return createService(serviceClass, authToken);
}
return createService(serviceClass, null);
}
public static <S> S createService(
Class<S> serviceClass, final String authToken) {
if (!TextUtils.isEmpty(authToken)) {
AuthenticationInterceptor interceptor =
new AuthenticationInterceptor(authToken);
if (!httpClient.interceptors().contains(interceptor)) {
httpClient.addInterceptor(interceptor);
builder.client(httpClient.build());
retrofit = builder.build();
}
}
return retrofit.create(serviceClass);
}
}
Retrofit 1.9
public class ServiceGenerator {
public static final String API_BASE_URL = "https://your.api-base.url";
private static RestAdapter.Builder builder = new RestAdapter.Builder()
.setEndpoint(API_BASE_URL)
.setClient(new OkClient(new OkHttpClient()));
public static <S> S createService(Class<S> serviceClass) {
return createService(serviceClass, null, null);
}
public static <S> S createService(Class<S> serviceClass, String username, String password) {
if (username != null && password != null) {
// concatenate username and password with colon for authentication
String credentials = username + ":" + password;
// create Base64 encodet string
final String basic =
"Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);
builder.setRequestInterceptor(new RequestInterceptor() {
#Override
public void intercept(RequestFacade request) {
request.addHeader("Authorization", basic);
request.addHeader("Accept", "application/json");
}
});
}
RestAdapter adapter = builder.build();
return adapter.create(serviceClass);
}
}
AuthenticationInterceptor.java
public class AuthenticationInterceptor implements Interceptor {
private String authToken;
public AuthenticationInterceptor(String token) {
this.authToken = token;
}
#Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
Request.Builder builder = original.newBuilder()
.header("Authorization", authToken);
Request request = builder.build();
return chain.proceed(request);
}
}
Usage
Retrofit 2
Interface
public interface LoginService {
#POST("/login")
Call<User> basicLogin();
}
Requester
LoginService loginService =
ServiceGenerator.createService(LoginService.class, "user", "secretpassword");
Call<User> call = loginService.basicLogin();
call.enqueue(new Callback<User >() {
#Override
public void onResponse(Call<User> call, Response<User> response) {
if (response.isSuccessful()) {
// user object available
} else {
// error response, no access to resource?
}
}
#Override
public void onFailure(Call<User> call, Throwable t) {
// something went completely south (like no internet connection)
Log.d("Error", t.getMessage());
}
}
Retrofit 1.9
Interface
public interface LoginService {
#POST("/login")
void basicLogin(Callback<User> cb);
}
Requester
LoginService loginService =
ServiceGenerator.createService(LoginService.class, "user", "secretpassword");
loginService.basicLogin(new Callback<User>() {
#Override
public void success(User user, Response response) {
// user object available
}
#Override
public void failure(RetrofitError error) {
// handle errors, too
}
});
More information see here.
add header interceptor
public class HeaderInterceptor implements Interceptor {
private PreferencesRepository mPrefs;
private String mAuth;
public HeaderInterceptor(PreferencesRepository p) {
mPrefs = p;
}
#Override
public Response intercept(Chain chain) throws IOException {
mAuth = (mPrefs.getAuthToken() != null)?mPrefs.getAuthToken():"";
Request r = chain.request()
.newBuilder()
.addHeader("Accept", "application/json")
// authorization token here
.addHeader("Authorization", "Bearer" + mAuth)
.build();
return chain.proceed(r);
}
}
add cacheinterceptor (optional)
public class CacheInterceptor implements Interceptor {
Context mContext;
public CacheInterceptor(Context context) {
this.mContext = context;
}
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
if (request.method().equals("GET")) {
if (DeviceUtils.isConnected(mContext)) {
request = request.newBuilder()
.header(Constant.CACHE_CONTROL, "only-if-cached")
.build();
} else {
request = request.newBuilder()
.header(Constant.CACHE_CONTROL, "public, max-stale=2419200")
.build();
}
}
Response originalResponse = chain.proceed(request);
return originalResponse.newBuilder()
.header(Constant.CACHE_CONTROL, "max-age=600")
.build();
}
}
implement it
HttpLoggingInterceptor logger = new HttpLoggingInterceptor();
logger.setLevel(HttpLoggingInterceptor.Level.BODY);
long SIZE_OF_CACHE = 10 * 1024 * 1024; // 10 MiB
Cache cache = new Cache(new File(mContext.getCacheDir(), "http"), SIZE_OF_CACHE);
new OkHttpClient.Builder()
.addInterceptor(logger)
.addInterceptor(new HeaderInterceptor(u))
.cache(cache)
.addNetworkInterceptor(new CacheInterceptor(mContext))
.connectTimeout(Constant.CONNECTTIMEOUT, TimeUnit.SECONDS)
.readTimeout(Constant.READTIMEOUT, TimeUnit.SECONDS)
.writeTimeout(Constant.WRITETIMEOUT, TimeUnit.SECONDS)
.build();
Of course using auth interceptor is correct way (as explained in other answers). Although, if you need basic authentication only for single call, then auth header can be added directly in Retrofit request:
import okhttp3.Credentials
// Create credentials
val login = "some login"
val password = "some password"
// Below code will create correct Base64 encoded Basic Auth credentials
val credentials = Credentials.basic(login, password)
// Then in your Retrofit API interface
interface MyApi {
#POST("get_user")
fun getUser(#Header("Authorization") credentials: String): ResponseBody
}

Categories

Resources