I found something strange when I add interceptor like this:
public ApiDefinition getService() {
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(chain -> {
System.out.println("into interceptor");
Request request = chain.request();
return chain.proceed(request);
})
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(UrlConfig.BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(client)
.build();
return retrofit.create(ApiDefinition.class);
}
Then when I do call a network, nothing print just like the interceptor did't work.
Observable observable = apiDefinition.getResponse();
observable.subscribe(....)
I am confused, was there anything wrong?
apiDefinition.getResponse(); you forgetting to subscribe api call. Just getting observable, but not observing it.
apiDefinition
.getResponse()
.subscribe(.......);
if you want to intercept Network request call and print them in logcat
you can do so by adding an HttpLoggingInterceptor like that:
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
// set your desired log level
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(logging)
.build();
Sorry guys, i make some mistakes when i user dagger2 to inject ApiDefinition, so this is solved.
Related
I have a problem,
How to wait for data from API?
I would write code like this:
List<User> userList = dataAPI.getAllUser();
I would have a list an use it wherever I want.
I don't want to Override any methods.
DataAPI:
public class DataAPI {
public DataAPI(){
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
userAPI = retrofit.create(UserService.class);
public class DataAPI {
[...]
private UsertService userAPI;
public DataAPI(){
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
userAPI = retrofit.create(UserService.class);
}
Observable<List<User>> getAllUser() {
return userAPI.getAllUser();
}
}
UserService
#GET("/user/all")
Observable<List<User>> getAllUser();
It could be done with rxJava, for more details: read
You just need to set timeout and increase it as you need to wait for the response coming from service. (Give priority to writeTimeout)
OkHttpClient client = new OkHttpClient.Builder();
client .connectTimeout(10, TimeUnit.SECONDS);
client .writeTimeout(30, TimeUnit.SECONDS);
client .readTimeout(40, TimeUnit.SECONDS);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://api.yourapp.com/")
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
#Kubek, what you need to do is subscribe to the observable.
What you should probably do is:
userAPI.getAllUser()
.subscribeOn(Schedulers.IO)
.observeOn(AndroidSchedulers.Main)
.subscribe(
// do some stuff
)
For documentation on how to use subscribe method, refer: http://reactivex.io/documentation/operators/subscribe.html
I am learning to use retrofit, to consume Webservices, I have no problems in executing the #GET, #POST methods but now I have to execute a service where the token is sent, I really do not know how to do it, but I use POSTMAN where this field token I send from Headers in the Authorization key. I have seen other examples where OkHttpClient is used but I can not think of how to implement it.
So I execute my service with retrofit, to this same one the token in the head should be sent to him.
#GET(Constants.Retrofit.SURE_DO_YOU_LIKE_PRODUCTS)
Call<List<RelatedProducts>> getProductSureDoYouLike();
and this is my service in POSTMAN.
Like this:
#GET(Constants.Retrofit.SURE_DO_YOU_LIKE_PRODUCTS)
Call<List<RelatedProducts>> getProductSureDoYouLike(#Header("Content-Type") String contentType, #Header("Authorization") String auth);
If all requests require a Content-Type you could modify your Retrofit builder to include the header on every request:
OkHttpClient client;// = new OkHttpClient();
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.connectTimeout(5, TimeUnit.MINUTES)
.writeTimeout(5, TimeUnit.MINUTES)
.readTimeout(5, TimeUnit.MINUTES)
.addInterceptor(chain -> {
Request request = chain.request().newBuilder()
//Add this to include header in every request
.addHeader("Content-Type", "application/json").build();
return chain.proceed(request);
}).build();
client = builder.build();
retrofit = new Retrofit.Builder()
.baseUrl(NetworkConstants.BASE_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
}
Then your request would be:
#GET(Constants.Retrofit.SURE_DO_YOU_LIKE_PRODUCTS)
Call<List<RelatedProducts>> getProductSureDoYouLike(#Header("Authorization") String auth);
You would then call like so:
apiService.getProductSureDoYouLike("token");
I'm using Retrofit 2, I want to know the values or Structure of sending the value to the server. Is there any way where can I put 'system.out.print' so that I can know what Am I sending?
first add this
impletemtaion "com.squareup.okhttp3:logging-interceptor:LATEST_VERSION";
add this
#Provides
#Singleton
public OkHttpClient provideClient(Context mContext, CacheInterceptor cacheInterceptor, HeaderInterceptor headerInterceptor) {
//***************
HttpLoggingInterceptor logger = new HttpLoggingInterceptor();
logger.setLevel(HttpLoggingInterceptor.Level.BODY);
//***************
return new okhttp3.OkHttpClient.Builder()
.addInterceptor(logger)
.addInterceptor(headerInterceptor)
.connectTimeout(Constant.CONNECTTIMEOUT, TimeUnit.SECONDS)
.readTimeout(Constant.READTIMEOUT, TimeUnit.SECONDS)
.writeTimeout(Constant.WRITETIMEOUT, TimeUnit.SECONDS)
.build();
}
Refer to this for HTTPLogging Interceptor for Retrofit 2
https://futurestud.io/tutorials/retrofit-2-log-requests-and-responses
I need to make HTTP DELETE request to my server with body provided.
I build the retrofit object in the following way:
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.retryOnConnectionFailure(true)
.connectTimeout(2, TimeUnit.MINUTES)
.readTimeout(5, TimeUnit.MINUTES)
.writeTimeout(5, TimeUnit.MINUTES)
.build();
Gson gson = new GsonBuilder()
.registerTypeAdapter(Date.class, new GsonUTCDateAdapter())
.registerTypeAdapter(LocalDate.class, new GsonLocalDateAdapter())
.create();
return new Retrofit.Builder()
.baseUrl(AppConfig.API_BASE_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
My Retrofit service method is:
#HTTP(method = "DELETE", path = "selfie/{publicId}/action/1", hasBody = true)
Observable<SimpleResponseModel> unlike(
#Path("publicId") String publicId,
#Body AuthorisedRequestModel model
);
I handle retrofit request/response in following way:
NetworkHelper
.getRetrofit()
.create(SelfieService.class)
.unlike(selfieModel.getPublicId(), new AuthorisedRequestModel())
.subscribeOn(Schedulers.io())
.subscribe(new CustomSubscriber<SimpleResponseModel>() {
#Override
public void onNext(SimpleResponseModel simpleResponseModel) {
ErrorHelper.handleServerError(simpleResponseModel);
}
});
I should mention, that all another requests GET,POST and PUT are working, but all DELETE requests are return me following error, from log:
HTTP FAILED: java.io.IOException: unexpected end of stream on okhttp3.Address#c6ec992c
So the request don't reach the server.
When I used Retrofit without rxandroid and made queries in AsyncTasks everything worked well.
Caused by:
Caused by: java.io.EOFException: \n not found: size=0 content=…
at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:215)
at okhttp3.internal.http.Http1xStream.readResponse(Http1xStream.java:186)
It is an issue. You can see it on GitHub:
https://github.com/square/okhttp/issues/1517
Is there any possibility to compare a Call URL with a String in Retrofit 2?
For example we can take this baseUrl:
https://www.google.com
And this Call:
public interface ExampleService {
#GET("dummy/{examplePartialUrl}/")
Call<JsonObject> exampleList(#Path("examplePartialUrl") String examplePartialUrl;
}
with this request:
Call<JsonObject> mCall = dummyService.exampleList("partialDummy")
There's a way to obtain https://www.google.com/dummy/partialDummy or also dummy/partialDummy before getting the response from the call?
Assuming you're using OkHttp alongside Retrofit, you could do something like:
dummyService.exampleList("partialDummy").request().url().toString()
which according to the OkHttp docs should print:
https://www.google.com/dummy/partialDummy
Log.d(TAG, "onResponse: ConfigurationListener::"+call.request().url());
Personally I found another way to accomplish this by using retrofit 2 and RxJava
First you need to create an OkHttpClient object
private OkHttpClient provideOkHttpClient()
{
//this is the part where you will see all the logs of retrofit requests
//and responses
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
return new OkHttpClient().newBuilder()
.connectTimeout(500, TimeUnit.MILLISECONDS)
.readTimeout(500,TimeUnit.MILLISECONDS)
.addInterceptor(logging)
.build();
}
after creating this object, the next step is just use it in retrofit builder
public Retrofit provideRetrofit(OkHttpClient client, GsonConverterFactory convertorFactory,RxJava2CallAdapterFactory adapterFactory)
{
return new Retrofit.Builder()
.baseUrl(mBaseUrl)
.addConverterFactory(convertorFactory)
.addCallAdapterFactory(adapterFactory)
.client(client)
.build();
}
one of the attributes you can assign to Retrofit builder is the client, set the client to the client from the first function.
After running this code you could search for OkHttp tag in the logcat and you will see the requests and responses you made.