Подтвердить что ты не робот

Android: схема "http" не зарегистрирована в ICS 4.0.4 с прокси-сервером

Я использую HttpClient для HTTPS-запросов, которые до сих пор работали нормально. После обновления до ICS некоторые пользователи сообщают о проблемах, связанных с подключением 3G.

EDIT: большинство из них, похоже, используют прокси-сервер, и я могу воспроизвести его локально с помощью T-Mobile SIM, используя свой прокси-сервер.

В журналах есть трассировка стека:

java.lang.IllegalStateException: Scheme 'http' not registered.
org.apache.http.conn.scheme.SchemeRegistry.getScheme(SchemeRegistry.java:80)
org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:126)
org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360)
org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)

Наша конечная точка - только HTTPS, поэтому мы не регистрируем конечную точку HTTP в нашей системе SchemeRegistry. Нет нигде (AFAIK), где мы перенаправляем HTTP.

Вот код, который устанавливает HttpClient для клиента HTTPS:

    DefaultHttpClient ret = null;

    // sets up parameters
    HttpParams params = new BasicHttpParams();
    HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
    HttpProtocolParams.setContentCharset(params, "utf-8");
    params.setBooleanParameter("http.protocol.expect-continue", false);

    HttpConnectionParams.setConnectionTimeout(params, DEFAULT_CONN_TIMEOUT_MSEC);
    HttpConnectionParams.setSoTimeout(params, timeoutMsec);
    HttpConnectionParams.setStaleCheckingEnabled(params, true);

    SchemeRegistry registry = new SchemeRegistry();
    final SocketFactory sslSocketFactory = getPreferredSSLSocketFactory();
    registry.register(new Scheme("https", sslSocketFactory, 443));

    ThreadSafeClientConnManager manager = new ThreadSafeClientConnManager(params, registry);
    ret = new DefaultHttpClient(manager, params);
    // for preemptive authentication
    // http://dlinsin.blogspot.com/2009/08/http-basic-authentication-with-android.html
    ret.addRequestInterceptor(preemptiveAuth, 0);
    ret.setCookieStore(communalCookieJar);

    SimpleCredentialsProvider credProvider = new SimpleCredentialsProvider(getAccountPreferences());
    ret.setCredentialsProvider(credProvider);

    return ret;

Примечание. Мы делим этот экземпляр HttpClient между несколькими потоками.

4b9b3361

Ответ 1

Похоже, проблема заключалась в том, что некоторые носители нажимали неверные определения прокси с обновлением 4.0.4. Это нарушило HTTPS, но HTTP работал правильно (например, Google Play не работал).

Одно возможное исправление (помимо исправления недействительной записи прокси) заключается в том, чтобы поймать IllegalStateException при выполнении запросов HttpClient и установить флаг. Этот код будет обходить любые прокси:

    hc = new DefaultHttpClient(manager, params);
    if (BYPASS_PROXY)
        hc.setRoutePlanner(new DefaultHttpRoutePlanner(registry));

Ответ 2

Из вашего stacktrace, я бы предложил вам зарегистрировать оба (http, https) и посмотреть, не работает ли это.

Вы должны уметь отлаживать его, включив в него исходные банки apache - развернитесь по трассе @SchemeRegistry.getScheme().

Этот поток может помочь.

Ниже проверено OK на ICS... Пример SSL ConnectionMgr на androidhttpclient libs:

static X509TrustManager tm = new X509TrustManager() {

        public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException {
        }

        public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException {
        }

        public X509Certificate[] getAcceptedIssuers() {
        return null;
        }
};

MyConnectionManager(SchemeRegistry scheme){
    super(scheme);
}

public static MyConnectionManager getInstance() {
    if (instance == null){

        SSLContext ctx=null;
        try {
            ctx = SSLContext.getInstance("TLS");
            ctx.init(null, new TrustManager[]{tm}, null);
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (KeyManagementException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }                   
        SchemeRegistry schemeRegistry = new SchemeRegistry();
        schemeRegistry.register( new Scheme("http", 80,PlainSocketFactory.getSocketFactory()));
        schemeRegistry.register(new Scheme("https", 443, SSLSocketFactory.getSocketFactory()));
        instance = new MyConnectionManager(schemeRegistry);
         // Increase max total connection to 200
         instance.setMaxTotal(15);
         // Increase default max connection per route to 20
         instance.setDefaultMaxPerRoute(15);
         // Increase max connections for localhost:80 to 50
         HttpHost localhost = new HttpHost("picasaweb.google.com", 443);
         instance.setMaxForRoute(new HttpRoute(localhost), 10);
    }
    return instance;
}

Ответ 3

Я бы не создал новый SchemeRegistry. Я бы взял значение по умолчанию из ThreadSafeClientConnManager.getSchemeRegistry(). Таким образом, он, вероятно, содержит всевозможные уже поддерживаемые схемы.

http-часть может поступать от вашего прокси-сервера.