Как написать перехватчик для потока данных в OkHttp?
Или думаешь, что перехватчик для этого сценария применим?
Наше приложение использует OkHttp для загрузки файлов (новая версия приложения, ежедневные базы данных и т. Д.)
Иногда происходит сбой сервера только во время потоковой передачи байтов приложения (кстати, проблема в том, что recvfrom не удалось: ECONNRESET)
Так что, чтобы исправить это дело, я просто хотел написать перехватчик попыток OkHttp. Но, похоже, это подходит для операций, которые не являются потоковыми.
Есть ли решение (например, перехватчик) для обработки этого случая?
Чтобы сделать экспозицию более понятной
0%==============================100% (только начал потоковую передачу)
0%============================== 100% (10% выполнено)
0%============================== 100% (выполнено20%)
0%============================== 100% (ECONNRESET - сброс соединения по пиру)
В этот момент потоковая передача останавливается. Единственное, чего я желаю от OkHttp, это распознать эту ситуацию, а затем запустить поток с нуля (не с 20%).
Связанный код здесь, обратите внимание на комментарии
Call call = client.newCall(new Request.Builder().url(url).get().build());
Response response = call.execute();
// PROBLEM DOES NOT OCCUR THERE
// PROBLEM DOES NOT OCCUR THERE
// PROBLEM DOES NOT OCCUR THERE
if (response.code() == 200 || response.code() == 201) {
InputStream inputStream = null;
try {
long downloaded = 0;
byte[] buff = new byte[1024 * 4];
inputStream = response.body().byteStream();
long target = response.body().contentLength();
while (true) {
// EXCEPTION OCCURS THERE
// EXCEPTION OCCURS THERE
// EXCEPTION OCCURS THERE
int read = inputStream.read(buff);
if (read == -1) {
break;
}
downloaded += read;
}
...
} catch (IOException e) {
// EXCEPTION SAYS
// ECONNRESET - Connection reset by peer
...
}
}
3 ответа
Вы можете написать собственный перехватчик, как показано ниже:
OkHttp имеет перехватчики. Вам нужен пользовательский перехватчик, как показано ниже:
public class CustomResponseInterceptor implements Interceptor {
private final String TAG = getClass().getSimpleName();
@Override
public Response intercept(Object object) throws IOException {
Request request = chain.request();
Response response = chain.proceed(request);
if (response.code() != 200//Your error code here,) {
//Cancel your Request here
return something;
}
Log.d(TAG, "INTERCEPTED:$ " response.toString());
return response;
}
Показанный код извлечен из этой средней статьи о перехватчиках.
Вы также можете посмотреть на эту библиотеку, которая реализует перехватчики Retry, но вы можете изменить ее для своего использования.
Когда ECONNRESET - Connection reset by peer
происходит, почему бы вам не отменить текущий вызов в блоке перехвата и начать новый сетевой вызов для того же файла
catch (IOException e) {
// EXCEPTION SAYS
// ECONNRESET - Connection reset by peer
...
call.cancel();//something like this
startDownloadingFromScratch();//new network request to start from scratch
}
Попробуй это.
OkHttpClient client = new OkHttpClient();
client.setConnectTimeout(CONNECT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
client.setReadTimeout(READ_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
client.interceptors().add(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
// try the request
Response response = chain.proceed(request);
int tryCount = 0;
while (!response.isSuccessful() && tryCount < 3) {
Log.d("intercept", "Request is not successful - " + tryCount);
tryCount++;
// retry the request
response = chain.proceed(request);
}
// otherwise just pass the original response on
return response;
}
});
установите этот клиент в качестве вашего модифицированного клиента.
new Retrofit.Builder()
...other codes
.client(client)
...other codes
.build();
Удачи.