2017-01-20 5 views
2

Увидев следующий стек на старых версиях Android (4.3 и выше):IncompatibleClassChangeError из okhttp3.internal.Util.closeQuietly()

Caused by: java.lang.IncompatibleClassChangeError: interface not implemented 
at okhttp3.internal.Util.closeQuietly(Util.java:100) 
at okhttp3.internal.connection.StreamAllocation.streamFailed(StreamAllocation.java:332) 
at okhttp3.internal.http.RetryAndFollowUpInterceptor.recover(RetryAndFollowUpInterceptor.java:209) 
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:132) 
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92) 
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67) 
at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:212) 
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92) 
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67) 
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:179) 
at okhttp3.RealCall.execute(RealCall.java:63) 

Это наводит на мысль, несовместимость между okhttp и Java 6, где java.net.Socket не реализует Closeable.

И проблема возникает, прежде всего, в результате отказавшего потока. Это было трудно воспроизвести, пока мы не начали называть эту страницу PHP (заимствованную из https://stackoverflow.com/a/141026/315702), что заставляет сбой потока на стороне клиента:

<?php 
ob_end_clean(); 
header("Connection: close"); 
ignore_user_abort(true); // just to be safe 
ob_start(); 
echo('Text the user will see'); 
$size = ob_get_length(); 
header("Content-Length: $size"); 
ob_end_flush(); // Strange behaviour, will not work 
flush(); // Unless both are called ! 
sleep(30); 
echo('Text user will never see'); 
?> 

ответ

2

Это, как представляется, ошибка с текущей okhttp 3.6.0-SNAPSHOT строить. Я подал bug report на сайт okhttp github. Исключение возникает, когда соединение неожиданно закрывается. [Обновление: ошибка была быстро исправлена ​​заменой Closeable на Socket для обратной совместимости с Java 6 в этом pull request.]

В нашем случае настоящей проблемой было то, что мы не хотели использовать okhttp 3.6. 0-SNAPSHOT в первую очередь. В нашем build.gradle мы указали 3.4.1. Оказалось, один из наших сторонних библиотек имели зависимость от okhttp: +, который мы обнаружили с помощью следующей Gradle команды:

./gradlew -q :app:dependencyInsight --dependency okhttp --configuration compile

Из-за этого, мы тянули в то, что происходит, чтобы быть последним версия okhttp. В нашем случае криптографическая библиотека была расширением okhttp для exoplayer. Исключив нежелательную зависимость модуля на okhttp: +, мы смогли избежать загрузки 3.6.0-SNAPSHOT:

compile('com.google.android.exoplayer:extension-okhttp:r2.0.4') { 
    exclude module: 'okhttp' 
} 
+2

FWIW, похоже, они перестали использовать '+' по времени 'r2.1.1'. BTW, хороший анализ! – CommonsWare

+0

Потребовалось коллективное IQ нескольких разработчиков, чтобы добраться до сути этого. И спасибо - я собирался проверить, была ли исправлена ​​ошибка '+'! – markproxy

+2

Исправлено: https://github.com/square/okhttp/pull/3125 –

 Смежные вопросы

  • Нет связанных вопросов^_^