2012-04-27 10 views
12

sto usando HttpClient per richieste HTTPS, che ha funzionato benissimo fino ad ora. Dopo l'aggiornamento a ICS, alcuni utenti segnalano problemi di connessione su connessioni 3G.Android: Scheme 'http' non registrata su ICS 4.0.4 w/procura

EDIT: La maggior parte di loro sembrano essere utilizzando un proxy, e posso riprodurre questo localmente con un T-Mobile SIM usando il loro proxy.

I registri hanno questa analisi dello stack:

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) 

L'end point è solo HTTPS, quindi non abbiamo un endpoint HTTP nel nostro SchemeRegistry apposta. Non c'è nessun luogo (AFAIK) in cui reindirizziamo a HTTP.

Ecco il codice che imposta il HttpClient per il cliente 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; 

Nota: Condividiamo questo caso HttpClient tra più thread.

risposta

3

Il problema sembrava essere che alcuni vettori stavano spingendo le definizioni non validi procura con l'aggiornamento 4.0.4. Questo ha rotto HTTPS ma HTTP ha funzionato correttamente (Google Play non ha funzionato, per esempio).

Una possibile soluzione (oltre che fissa il voce di proxy non valido) è quello di catturare IllegalStateException durante l'esecuzione HttpClient richieste e impostare una bandiera. Questo codice ignorerà tutti i proxy:

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

Che cos'è BYPASS_PROXY? Perché non possiamo usare sempre questo route planner? Questa soluzione è sicura (ad esempio, continuerà a utilizzare https)? –

+0

Il codice è il trucco. E 'appena iniziato all'improvviso per me solo su 3G (Telenor, Svezia). C'è qualche potenziale problema con questo sempre acceso? – apanloco

+0

Quindi c'è un problema nell'avere sempre acceso? –

1

Non vorrei creare un nuovo SchemeRegistry. Prenderò quello predefinito da ThreadSafeClientConnManager.getSchemeRegistry(). In questo modo, probabilmente contiene tutti i tipi di schemi già supportati.

La parte http può provenire dal proxy del corriere.

+0

Puoi condividere i dettagli? Non ho trovato un modo per ottenere il registro dello schema predefinito da Gestione connessione thread safe o singolo client. – apanloco

+0

cosa intendi? non 'manager.getSchemeRegistry()' lo raggiunge? – njzk2

+0

ThreadSafeClientConnManager e SingleClientConnManager RICHIEDONO uno SchemeRegistry nel costruttore, in modo da ottenere solo ciò che si DEVE dare in primo luogo. – apanloco

6

Dal stacktrace, vorrei suggerire che si registra entrambi (http, https) e vedere se questo non funziona.

Si dovrebbe essere in grado di eseguire il debug includendo vasi source Apache - il drill-down sulla traccia @ SchemeRegistry.getScheme().

This thread può aiutare.

Di seguito è testato su OK ICS ... Esempio SSL ConnectionMgr su androidhttpclient librerie:

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; 
}