Почему вызов Http с использованием Retrofit2 (и наблюдателя rxjava) всегда ждет 5 секунд в Wi-Fi (Android M Nexus 6)

На Nexus 6 Android M (v23) вызов HTTP Api с использованием Retrofit ожидает около 5 секунд, прежде чем запрос будет отправлен на сервер. И телефон, и сервер подключены к одному Wi-Fi. Из браузера на другой рабочей станции в том же Wi-Fi вы получаете результаты мгновенно (~ 40-60 мс). Открытие того же API из Android Chrome на том же мобильном телефоне также занимает 5 секунд. В чем может быть проблема с отложенным HTTP-вызовом?

Код: Retrofit2/Okhttp service Factory

public class ApiGenerator {
    public static String TAG = ApiGenerator.class.getSimpleName();
    public static final String API_BASE_URL = BuildConfig.API_ENDPOINT;
    public static final Gson gson = new GsonBuilder()
        .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
        .create();
    private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder()
        .connectTimeout(15, TimeUnit.SECONDS)
        .writeTimeout(15, TimeUnit.SECONDS)
        .readTimeout(15, TimeUnit.SECONDS)
        .addInterceptor(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                Response response = chain.proceed(request);
                return response;
            }
        }).addInterceptor(new LoggingInterceptor());

    private static Retrofit.Builder builder =
        new Retrofit.Builder()
                .baseUrl(API_BASE_URL)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create());
                .....

Служба модернизации 2

public interface AuthService {

    @GET("/api/v1/auth")
    public void authenticate(@Query("token") String token);

    @POST("/api/v1/signup")
    Call<Object> signup();
}

Вызов службы поддержки –

Observable<Response<SignupV1Response>> observable = service.signupRx(signupReq);
    observable.subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .unsubscribeOn(Schedulers.io())
            .subscribe(new Subscriber<Response<SignupV1Response>>() {
                @Override
                public void onCompleted() {
                    ...
                }

                @Override
                public void onError(Throwable e) {
                    ...
                }

                @Override
                public void onNext(Response<SignupV1Response> response) {
                    if (response != null) {
                        final int statusCode = response.code();
                        if (response.isSuccess()) {
                            // Do something
                        } else {
                            ResponseBody errorBody = response.errorBody();
                            // Show error
                        }
                    }
                }
            });

person Ravi Kumar    schedule 05.02.2016    source источник
comment
...пожалуйста, предоставьте свой код?   -  person David Medenjak    schedule 05.02.2016


Ответы (1)


Наконец-то обнаружил, что это не имеет ничего общего с Okhttp и Retrofit. Проблема с сетью Android, в которой включен IPv6, на Android L (v21) и выше. Если сеть Wi-Fi неправильно обрабатывает IPv6 (большинство маршрутизаторов, включая последние выпуски), этим клиентским библиотекам HTTP потребуется несколько секунд, прежде чем они получат ответ. Сослаться на проблему – https://code.google.com/p/android/issues/detail?id=79576

В качестве обходного пути вы можете туннелировать локальный сервер разработки в Amazon EC2 с помощью ssh или использовать ngrok. Отлично работает с этим подходом.

person Ravi Kumar    schedule 12.02.2016