Using
com.squareup.retrofit2:retrofit:2.9.0
com.squareup.okhttp3:okhttp:4.4.0
com.google.firebase:firebase-perf-ktx (bom version is 29.0.4)
I'm unable to see any network requests inside the Firebase Performance network requests section. Custom traces work fine but the network requests are empty. I also cannot see any I/FirebasePerformance logcat logs suggesting that http requests are being logged.
The app uses a simple retrofit service to make requests which looks like:
Retrofit.Builder()
.baseUrl("https://myurl.com")
.client(get())
.addConverterFactory(MoshiConverterFactory.create(get()))
.build()
.create(MyService::class.java)
The OkHttpClient :
OkHttpClient.Builder()
.addInterceptor(UserAgentHeaderInterceptor())
.addInterceptor(HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
})
.build()
I have already tried the following:
Been through Firebase's trouble shooting guide for this issue.
Downgraded my okHttp version to 3.12.
Related
I'm currently building a Retrofit object as follows:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
I don't need to pass it a client, i.e. no need to deal with the internals.
Now I would like to set a timeout, but all the examples I found involve creating an okHttpClient and assigning it to the Retrofit object.
Does it mean that okHttp is the de-facto client used by the system in all the situations?
Does it mean that okHttp is the de-facto client used by the system in all the situations?
Yes. Retrofit uses OkHttp for its network I/O. For example, in the Retrofit documentation, they mention in the section on R8/Proguard:
You might also need rules for OkHttp and Okio which are dependencies of this library
We've been using okhttpClient in our android app, and noticed that OkHttpClient lib is quietly retrying requests, with the config retryOnConnectionFailure boolean in OkHttpClient class.
Is there any way to log the retries? is there a callback or lambda we can use?
I looked into the source code of okhttpClient and did some research, but was not lucky, didn't find anything.
You log requests via interceptor.
in your *.gradle add
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.1'
and to your OK client:
httpClient.addNetworkInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
Now, there are 2 places to hook an interceptor, addInterceptor and addNetworkInterceptor. The difference is that regular interceptor shows all requests, including ones served from local cache and network interceptors shows only traffic to a server.
Analyzing some previously written code I have some questions concerning the set up with OkHttpClient. We did create a single OkHttpClient instance and reuse it for all of our HTTP calls. We execute REST API calls and caching is not needed.
However I do see some code in an interceptor
request = request.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=${120}").build()
Question 1: Would this have any effect if caching is not enabled?
Secondly there is one API call that fetches configuration data and I feel it can benefit from caching.
Question 2: Can we enable caching for just one call, say, if we customize the client using newBuilder()?
It could have an effect on caches between yourself and the remote service. But this specific interceptor seems designed to force the request to only use the local cache, and not attempt to use the network.
https://square.github.io/okhttp/4.x/okhttp/okhttp3/-cache-control/only-if-cached/
To rephrase my question slightly ...if no cache is set on the original call then the request with the cache-control will not do anything right?
Typically you would not need an interceptor, instead you would apply the cache settings to the request.
https://square.github.io/okhttp/4.x/okhttp/okhttp3/-cache/
Request request = new Request.Builder()
.cacheControl(new CacheControl.Builder().noCache().build())
.url("http://publicobject.com/helloworld.txt")
.build();
Not sure this addresses the second question. I'm asking if we have set up one single OkHttpClient instance can we have only some requests cached or the fact that we turn on cache for one request turns it on for all other requests onward?
I am facing a very strange issue in my Android app with OkHttp3 Interceptor where I set different logging levels to different build variants.
I have setup an OkHttp3 Interceptor in my app to intercept API requests, and if any API returns 401 error, the interceptor gets the refreshed token from backend and updates the header of original request with the new token and repeats it. Let's call this RefreshTokenInterceptor. I add this interceptor when building my OKHttpClient. Besides this, I also add an HttpLoggingInterceptor to log the API requests and responses or stop logging in case of release builds. Let's call this LoggingInterceptor
Here is the code where I build my OkHttpClient. This code should be enough because the refresh mechanism works fine if the logging level is changed.
val loggingInterceptor = HttpLoggingInterceptor()
// changing level to Level.BODY in the below solves the issue,
// but I don't want to log the results
when {
BuildConfig.DEBUG -> loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
else -> loggingInterceptor.level = HttpLoggingInterceptor.Level.NONE
}
val httpClientBuilder = OkHttpClient.Builder()
.readTimeout(READ_TIMEOUT, TimeUnit.MILLISECONDS)
.writeTimeout(WRITE_TIMEOUT, TimeUnit.MILLISECONDS)
.addInterceptor(ConnectivityInterceptor())
.addInterceptor(TokenRefreshInterceptor())
.addInterceptor(loggingInterceptor)
.connectTimeout(CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS)
When I set the logging level of the LoggingInterceptor in both cases to Level.BODY, everything works fine. But in case of logging level set to Level.NONE, the token refresh mechanism stops working.
To be more specific, in this case, this is what happens in RefreshTokenInterceptor: when a request returns 401, the refresh call is made, but nothing happens afterwards. No success or failure case gets called (Maybe the interceptor Chain breaks but who knows).
Here is what I have tried so far
Removing the LoggingInterceptor altogether -> does not work
Setting logging level to Level.NONE for all build variants -> does
not work
Setting logging level to Level.BODY for all build variants -> works
like magic
I also searched a lot today on this, but could not find any link between logging levels messing up other interceptors. Any help would be appreciated, and if you need more code, I can post it.
The problem was being caused by a memory leak which happened because an OkHttp3 Response object in the TokenRefreshInterceptor which was not being closed. I got to know about this leak on Firebase Console. Closing this Response after consuming it solved the issue. But I'm still unsure why it worked fine when I enabled body-level logging.
I have been using retrofit1 + robospice to make API requests. You can check sample here. In this framework, I used to make request like this
getSpiceManager().execute(request, CACHE_KEY, DurationInMillis.ONE_MINUTE(CACHE_TIME), new ResponseListener());
Above statement will make sure that it will return the cached response for one minute from the time I requested(with the same cache key).But currently, robospice does not support retrofit v2. My Question is that is there any cache mechanism for retrofit v2 to implement like this. I googled for some time but I could not find what exactly I want.
the proper way to cache responses in android is using OkHttp (and it combines with Retrofit as well)
use the cache method :
OkHttpClient client = new OkHttpClient.Builder()
.cache(new Cache(cacheDir, MAX_SIZE))
.build()
Retrofit retrofit = new Retrofit.Builder()
.client(okHttpClient)
.build()