Retrofit: Retrofit 2 with RxJava - HttpLoggingInterceptor, java.lang.NoSuchMethodError: okhttp3.internal.Platform.log

Created on 30 Sep 2016  路  3Comments  路  Source: square/retrofit

I'm not sure is it bug or I'm doing something wrong. I explained my problem http://stackoverflow.com/q/39782868/513413 but didn't receive an answer.

In my other project, I'm not using RxJava and I'm able to see Retrofit logs however error throws in RxJava.

package com.my.package.network;

import com.facebook.stetho.okhttp3.StethoInterceptor;
import com.sakurasky.viewlorium.BuildConfig;
import com.sakurasky.viewlorium.ViewloriumApp;

import java.io.File;
import java.io.IOException;
import java.util.Locale;
import java.util.concurrent.TimeUnit;

import javax.inject.Singleton;

import dagger.Module;
import dagger.Provides;
import okhttp3.Cache;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.converter.scalars.ScalarsConverterFactory;

@Module
public class NetworkModule {

    private static final long CONNECTION_TIMEOUT = 60 * 1000; // one minute
    private static final long CACHE_TIME = 432000; // 5days

    private File cacheFile;

    public NetworkModule(File cacheFile) {
        this.cacheFile = cacheFile;
    }

    @Provides
    @Singleton
    Retrofit provideCall() {
        return new Retrofit.Builder()
                .baseUrl(BuildConfig.VIEWLORIUM_API_URL_BASE)
                .client(getHttpClientBuilder())
                .addConverterFactory(GsonConverterFactory.create())
                .addConverterFactory(ScalarsConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
    }

    private OkHttpClient getHttpClientBuilder() {
        // Setup caching file
        Cache cache = null;
        try {
            cache = new Cache(cacheFile, 10 * 1024 * 1024);
        } catch (Exception e) {
            e.printStackTrace();
        }

        // Setup Logging interceptor
        HttpLoggingInterceptor mLoggingInterceptor = new HttpLoggingInterceptor();
        mLoggingInterceptor.setLevel(ViewloriumApp.DEBUG ? HttpLoggingInterceptor.Level.BODY :
                HttpLoggingInterceptor.Level.NONE);

        // Setup OkHttpClient
        OkHttpClient.Builder builder = new OkHttpClient.Builder()
                .connectTimeout(CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS) //
                .addInterceptor(mLoggingInterceptor)
                .addNetworkInterceptor(new MyInterceptor())
                .cache(cache);

        // Add StethoInterceptor to display server requests/responses in chrome://inspect/#devices
        if (ViewloriumApp.DEBUG) {
            builder.addNetworkInterceptor(new StethoInterceptor());
        }

        return builder.build();
    }

    @Provides
    @Singleton
    @SuppressWarnings("unused")
    public NetworkService providesNetworkService(Retrofit retrofit) {
        return retrofit.create(NetworkService.class);
    }

    @Provides
    @Singleton
    @SuppressWarnings("unused")
    public Service providesService(NetworkService networkService) {
        return new Service(networkService);
    }

    private class MyInterceptor implements Interceptor {

        @Override
        public Response intercept(Chain chain) throws IOException {
            Request original = chain.request();

            // Customize the request
            Request request = original.newBuilder()
                    .header("Content-Type", "application/json")
                    .removeHeader("Pragma")
                    .header("Cache-Control", String.format(Locale.US, "max-age=%d", CACHE_TIME))
                    .build();

            okhttp3.Response response = chain.proceed(request);
            response.cacheResponse();
            // Customize or return the response
            return response;
        }
    }
}

and this is what I get

E/AndroidRuntime: FATAL EXCEPTION: RxIoScheduler-2
        Process: com.my.package, PID: 3105
        java.lang.IllegalStateException: Fatal Exception thrown on Scheduler.Worker thread.
        at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:62)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
        at java.util.concurrent.FutureTask.run(FutureTask.java:237)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
        at java.lang.Thread.run(Thread.java:841)

    Caused by: java.lang.NoSuchMethodError: okhttp3.internal.Platform.log
        at okhttp3.logging.HttpLoggingInterceptor$Logger$1.log(HttpLoggingInterceptor.java:109)
        at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:157)
        at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:190)
        at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:163)
        at okhttp3.RealCall.execute(RealCall.java:57)
        at retrofit2.OkHttpCall.execute(OkHttpCall.java:174)
        at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$RequestArbiter.request(RxJavaCallAdapterFactory.java:171)
        at rx.internal.operators.OperatorSubscribeOn$1$1$1.request(OperatorSubscribeOn.java:80)
        at rx.Subscriber.setProducer(Subscriber.java:211)
        at rx.internal.operators.OperatorSubscribeOn$1$1.setProducer(OperatorSubscribeOn.java:76)
        at rx.Subscriber.setProducer(Subscriber.java:205)
        at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:152)
        at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:138)
        at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:50)
        at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
        at rx.Observable.unsafeSubscribe(Observable.java:8666)
        at rx.internal.operators.OperatorSubscribeOn$1.call(OperatorSubscribeOn.java:94)
        at rx.internal.schedulers.CachedThreadScheduler$EventLoopWorker$1.call(CachedThreadScheduler.java:220)
        at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)聽
        at java.util.concurrent.FutureTask.run(FutureTask.java:237)聽
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)聽
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)聽
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)聽
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)聽
        at java.lang.Thread.run(Thread.java:841)

This is the way I'm calling my API

public interface NetworkService {

    @FormUrlEncoded
    @POST("api/video/signup")
    Observable<SignupResponse> getSignupAPI(@Field("fName") String firstName,
                                            @Field("lName") String lastName,
                                            @Field("login") String login,
                                            @Field("password") String password);
}

public class Service {

    private final NetworkService networkService;

    public Service(NetworkService networkService) {
        this.networkService = networkService;
    }

    public interface GeneralCallback {
        void onSuccess(SignupResponse signupResponse);
        void onError(NetworkError networkError);
    }

    public Subscription getSignupAPI(final GeneralCallback callback) {
        return networkService.getSignupAPI("hesam", "kamalan", "[email protected]", "1234")
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .onErrorResumeNext(new Func1<Throwable, Observable<? extends SignupResponse>>() {
                    @Override
                    public Observable<? extends SignupResponse> call(Throwable throwable) {
                        return Observable.error(throwable);
                    }
                })
                .subscribe(new Subscriber<SignupResponse>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {
                        callback.onError(new NetworkError(e));
                    }

                    @Override
                    public void onNext(SignupResponse signupResponse) {
                        callback.onSuccess(signupResponse);
                    }
                });
    }
}

When I delete (or comment out) the line, .addInterceptor(mLoggingInterceptor) then application works fine and I'm able to get response from server (but I'm not able to see logs).

Most helpful comment

the latest version is : compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'

you also can try it.

All 3 comments

I updated the Logging lib to version 3.3.0 and problem fixed.

compile 'com.squareup.okhttp3:logging-interceptor:3.3.0'

the latest version is : compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'

you also can try it.

Hey there,
I have to Integrate Module to another Project as sub Module and at that time i faced this error with latest version as
implementation 'com.squareup.okhttp3:logging-interceptor:3.14.1'
still found this error
ClassNotFoundException: Didn't find class "okhttp3.logging.HttpLoggingInterceptor"

Was this page helpful?
0 / 5 - 0 ratings