HttpLoggingInterceptor not logging with retrofit 2 - android

Im trying to log all the requests (with a network interceptor) using refrofit2, kotlin and logging-interceptor:
retrofit: "2.0.2"
okhttp3 : "3.2.0"
com.squareup.okhttp3:logging-interceptor 3.2.0
like:
val interceptor = HttpLoggingInterceptor()
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
val okHttpClient = OkHttpClient.Builder()
.addNetworkInterceptor(interceptor) // same for .addInterceptor(...)
.connectTimeout(30, TimeUnit.SECONDS) //Backend is really slow
.writeTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build()
sRestAdapter = Retrofit.Builder()
.client(okHttpClient)
.baseUrl(if (host.endsWith("/")) host else "$host/")
.addConverterFactory(GsonConverterFactory.create(gson()))
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build()
It just print:
D/OkHttp: --> GET url...
D/OkHttp: --> END GET
What is happening?
--------------- EDIT --------
Errors doing requests on Main Thread are not showing by the logger, so be careful.

private val interceptor = run {
val httpLoggingInterceptor = HttpLoggingInterceptor()
httpLoggingInterceptor.apply {
httpLoggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
}
}
private val okHttpClient = OkHttpClient.Builder()
.addNetworkInterceptor(interceptor) // same for .addInterceptor(...)
.connectTimeout(30, TimeUnit.SECONDS) //Backend is really slow
.writeTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build()

Instead of
val okHttpClient = OkHttpClient.Builder()
.addNetworkInterceptor(interceptor)
...
you should have something like:
val okHttpClient = OkHttpClient.Builder()
.addInterceptor(interceptor)
...
as the addNetworkInterceptor() plays with interceptors that observe a single network request and response, while addInterceptor() adds interceptor that observes the full span of each call: from the connection is established (if any) until after the response source is selected (either the origin server, cache, or both).
EDIT
Errors doing requests on Main Thread are not showing by the logger, so be careful
Doing networking on main thread is not an "ordinary" error. It will result in your app being killed by the system with NetworkOnMainThreadException and this will happen before interceptor would be given any chance to run.

Related

addInterceptor intercept NullPointException. in Retrofit2

I got this error:
Fatal Exception: kotlin.KotlinNullPointerException
com.example.manager.helper.my_api.MyServiceGenerator$createService$$inlined$-addInterceptor$1.intercept (Interceptor.kt:81)
okhttp3.internal.http.RealInterceptorChain.proceed (RealInterceptorChain.kt:100)
okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp (RealCall.kt:197)
okhttp3.internal.connection.RealCall$AsyncCall.run (RealCall.kt:502)
java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1133)
java.lang.Thread.run (Thread.java:762)
And I have no idea why it caused.
What I implemented is:
val logging = HttpLoggingInterceptor()
if (BuildConfig.DEBUG) { // If Build is Debug Mode, Show Log
logging.level = HttpLoggingInterceptor.Level.BODY // Logs request and response lines and their respective headers and bodies (if present).
} else { // Otherwise, show nothing.
logging.level = HttpLoggingInterceptor.Level.NONE // No logs
}
val client = OkHttpClient.Builder()
client.addInterceptor {
val original = it.request()
val request = original.newBuilder()
.header("User-Agent", MyApp.httpUserAgent!!)
.build()
it.proceed(request)
}
client.addInterceptor(logging)
.connectTimeout(30, TimeUnit.SECONDS)
.callTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
You are not finished building of your client. That's why it's null. In general you forgot to call build() method.
That's how it have to be implemented.
val client = OkHttpClient.Builder()
.addInterceptor(logging)
.connectTimeout(30, TimeUnit.SECONDS)
.callTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.build()
If you're using !! in your codes you should use it with a null check. Like this
if(MyApp.httpUserAgent != null) {
val request = original.newBuilder()
.header("User-Agent", MyApp.httpUserAgent!!)
.build()
else {
//here do something in case of null
}
I have the same problem when upgrade logging-interceptor from 3.10.0 to 4.7.2
Debug find cause is ssl factory
// old code
builder.sslSocketFactory(sslSocketFactory)
change the code to new code
// new code
builder.sslSocketFactory(sslSocketFactory, x509TrustManager)

RxAndroid + Retrofit callTimeout doesn't trigger onError

I am using RxAndroid + Retrofit to make http request. Code looks like below:
Interceptor headerInterceptor = getHeaderInterceptor();
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.callTimeout(5, TimeUnit.SECONDS)
.addInterceptor(headerInterceptor)
.addInterceptor(httpLoggingInterceptor)
.build();
Gson gson = new GsonBuilder()
.setLenient()
.create();
sRetrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.client(client)
.build();
Use it like this:
ApiProvider.provideApi(MyApi.class)
.submit(id, mRequest)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
response -> {
Log.w("tag", "success");
},
throwable -> {
Log.w("tag", "error");
}
);
I set connectTimeout / readTimeout / writeTimeout to be 60 seconds, and set callTimeout to be 5 seconds.
I know this configuration may be not reasonable but I just want to get a timeout exception after 5 seconds, and the Log.w("tag", "error"); could be called.
However, I found this line will never be called for my testing. And if I set connectionTimeout to 1 second, then this line will be called immediately.
So what I should do if I want callTimeout to trigger the log error line?
As for as I can see, I think your problem maybe isn't from how many seconds you set for callTimeout(5, TimeUnit.SECONDS), I think your maybe Rx stream have already throw some errors, so stream just break you can get any response from here. However, you reset time seconds to 1s, and then you restart app, this time stream not break and you get error.
So simple re-test it again to make sure your stream won't break even before enter this subscribe.
And I have been test with some stupid implementations:
class MainActivity : AppCompatActivity() {
val delayInterceptor = object : Interceptor {
override fun intercept(chain: Interceptor.Chain): okhttp3.Response {
Thread.sleep(6000L)
return chain.proceed(chain.request())
}
}
val client: OkHttpClient = OkHttpClient.Builder()
.connectTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.callTimeout(5, TimeUnit.SECONDS)
.addInterceptor(delayInterceptor)
.build()
val retrofit: Retrofit = Retrofit.Builder()
.baseUrl("https://en.wikipedia.org/")
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
data class Wiki(
#SerializedName("type")
val type: String
)
interface WikiService {
#GET("api/rest_v1/page/random/summary")
fun getRandomSummary(): Single<Wiki>
}
#SuppressLint("CheckResult")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
retrofit.create(WikiService::class.java)
.getRandomSummary()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
Log.d("tag", "success")
}, {
Log.e("tag", "error")
})
}
}
I finally find the the cause.
I was using com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory, which had been deprecated per its readme: https://github.com/JakeWharton/retrofit2-rxjava2-adapter
This is now DEPRECATED!
Retrofit 2.2 and newer have a first-party call adapter for RxJava 2: https://github.com/square/retrofit/tree/master/retrofit-adapters/rxjava2
After switching to retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory, everything start working nicely.
And BTW for any guy who might be interested in what the differences are between them two? Attach the key info I found below:

Retrofit 2: Setting Timeouts With No Effect

i am using the following:
implementation "com.squareup.retrofit2:converter-gson:2.6.0"
fun getOkHTTPClient(time: Int, interceptor: Interceptor): OkHttpClient {
val client = OkHttpClient.Builder()
.addInterceptor(interceptor)
.connectTimeout(5, TimeUnit.SECONDS)
.writeTimeout(5, TimeUnit.SECONDS)
.readTimeout(5, TimeUnit.SECONDS)
.callTimeout(5, TimeUnit.SECONDS)
.retryOnConnectionFailure(false)
return client.build()
}
retrofit2.Retrofit.Builder()
.baseUrl("$url/")
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClient)
If i change the timeouts to 10 seconds, 20, 50, 500 etc.... the effect is the same. the call timeout is not obeying these rules.
Am i missing something?
Note: i am using Asynchronous requests if it helps in debugging the case

Retrofit: Can I re-use OkhttpClient?

I am developing an android app using external API servers.
Because I use 2 servers, I have 2 retrofit services.
In my "RemoteDataSource" class's constructor, I make the service objects like:
public RemoteDataSource() {
OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
.connectTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.build();
myService1 = new Retrofit.Builder()
.baseUrl(URL_1)
.client(okHttpClient)
.build()
.create(MyService1.class);
myService2 = new Retrofit.Builder()
.baseUrl(URL_2)
.client(okHttpClient) // my question is here!!!
.build()
.create(MyService2.class);
}
What I want to know is...
Can I use one "OkHttpClient" on both services?
Is there any network issue?
or Should I make another OkHttpClient object like "okHttpClient2" and assign it to "myService2"?

Retrofit socket timeout exception while uploading larger files using multipart

I am facing the issue of socket timeout exception while using retrofit 2.0.2 library and okhttp 2.3.0. I am trying to upload the image file which is between 500kb to 1.5mb it is uploading successfully.but when i tried to upload video file which is greater than 5mb i am getting this exception.
I used httpclient for connection settings as below.
public static OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(0, TimeUnit.SECONDS)
.writeTimeout(0, TimeUnit.SECONDS)
.readTimeout(0, TimeUnit.SECONDS)
.build();
please suggest me to upload larger files without this issue.Thanks in advance
you can provide the time in seconds as follows
public class ApiClient {
public static final String BASE_URL = "your_url";
public static Retrofit retrofit = null;
public static Retrofit getApiClient() {
if (retrofit == null) {
OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
.connectTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.build();
return new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
i've given 60 seconds
There can be two issues with this type of error.
Check Read & Write Timeout
val client = OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build()
Check the Mime type you are sending. The backend developer may have filtered the accepted Mime type at their end. instead of MediaType.parse("multipart/form-data"). write the valid mime type for files like image/jpg or video/mp4
MediaType.parse("image/png")

Categories

Resources