13

HTTPS リクエストに HttpClient を使用していますが、これまでは問題なく動作していました。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)

エンドポイントは HTTPS のみであるため、SchemeRegistry に意図的に HTTP エンドポイントを登録しません。HTTPにリダイレクトする場所はどこにもありません(AFAIK)。

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;

注: この HttpClient インスタンスを複数のスレッドで共有します。

4

3 に答える 3

6

スタック トレースから、両方 ( http 、 https ) を登録し、それが機能しないかどうかを確認することをお勧めします。

Apache ソース jar を含めることでデバッグできるはずです。トレース @SchemeRegistry.getScheme() をドリルダウンします。

このスレッドが役立つ場合があります。

以下は ICS で問題なくテストされています... androidhttpclientライブラリでの 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;
}
于 2012-04-28T16:01:21.973 に答える
3

問題は、一部の通信事業者が 4.0.4 アップデートで無効なプロキシ定義をプッシュしていたことにあるようです。これにより HTTPS は壊れましたが、HTTP は正常に機能しました (たとえば、Google Play は機能しませんでした)。

1 つの可能な修正 (無効なプロキシ エントリの修正以外) は、HttpClient 要求の実行時に IllegalStateException をキャッチし、フラグを設定することです。このコードはプロキシをバイパスします。

    hc = new DefaultHttpClient(manager, params);
    if (BYPASS_PROXY)
        hc.setRoutePlanner(new DefaultHttpRoutePlanner(registry));
于 2012-05-10T19:08:59.337 に答える
2

新しい SchemeRegistry は作成しません。ThreadSafeClientConnManager.getSchemeRegistry() からデフォルトのものを取得します。このように、すでにサポートされているあらゆる種類のスキームが含まれている可能性があります。

http の部分は、キャリアのプロキシから取得できます。

于 2012-04-27T16:14:30.850 に答える