Android:Scheme'http'未在ICS 4.0.4 w/proxy上注册

seh*_*ugg 12 android apache-httpclient-4.x

我正在使用HttpClient进行HTTPS请求,到目前为止一直运行良好.升级到ICS后,一些用户报告连接3G连接时出现问题.

编辑:他们中的大多数似乎使用代理,我可以使用他们的代理在本地使用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)
Run Code Online (Sandbox Code Playgroud)

我们的端点仅限HTTPS,因此我们不会故意在SchemeRegistry中注册HTTP端点.我们没有任何地方(AFAIK)重定向到HTTP.

以下是为HTTPS客户端设置HttpClient的代码:

    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;
Run Code Online (Sandbox Code Playgroud)

注意:我们在多个线程之间共享此HttpClient实例.

Rob*_*ree 6

从您的堆栈跟踪,我建议您注册(http,https)并查看是否不起作用.

您应该能够通过包含apache源jar来调试它 - 向下钻取trace @ SchemeRegistry.getScheme().

这个帖子可能有帮助.

下面在ICS上测试OK ...在androidhttpclient libs 上示例SSL ConnectionMgr :

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;
}
Run Code Online (Sandbox Code Playgroud)


seh*_*ugg 3

问题似乎是一些运营商在 4.0.4 更新中推送了无效的代理定义。这破坏了 HTTPS,但 HTTP 工作正常(例如,Google Play 无法工作)。

一种可能的修复(除了修复无效的代理条目之外)是在执行 HttpClient 请求时捕获 IllegalStateException 并设置一个标志。此代码将绕过任何代理:

    hc = new DefaultHttpClient(manager, params);
    if (BYPASS_PROXY)
        hc.setRoutePlanner(new DefaultHttpRoutePlanner(registry));
Run Code Online (Sandbox Code Playgroud)

  • 什么是 BYPASS_PROXY?为什么我们不能总是使用这个路线规划器?这个解决方案安全吗(例如它仍然使用https)吗? (7认同)