Frage

Ich scheine in ein besonderes Problem auf Android 1.5 ausgeführt werden, wenn eine Bibliothek I (Wegweiser 1.1-SNAPSHOT) bin mit, macht zwei aufeinanderfolgenden Verbindungen zu einem Remote-Server. Die zweite Verbindung nicht immer mit einem HttpURLConnection.getResponseCode() von -1

Hier ist ein Testfall, der das Problem aussetzt:

// BROKEN
public void testDefaultOAuthConsumerAndroidBug() throws Exception {
    for (int i = 0; i < 2; ++i) {
        final HttpURLConnection c = (HttpURLConnection) new URL("https://api.tripit.com/oauth/request_token").openConnection();
        final DefaultOAuthConsumer consumer = new DefaultOAuthConsumer(api_key, api_secret, SignatureMethod.HMAC_SHA1);
        consumer.sign(c);                             // This line...
        final InputStream is = c.getInputStream();
        while( is.read() >= 0 ) ;                     // ... in combination with this line causes responseCode -1 for i==1 when using api.tripit.com but not mail.google.com
        assertTrue(c.getResponseCode() > 0);
    }
}

Grundsätzlich, wenn ich den Antrag unterschreiben und verbrauchen dann den gesamten Eingangsstrom, wird die nächste Anforderung mit einem Resultcode von -1 scheitern. Der Fehler scheint nicht zu passieren, wenn ich nur ein Zeichen aus dem Eingangsstrom gelesen.

Beachten Sie, dass dies nicht für jede URL geschieht -. Nur bestimmte Urls wie die oben

Auch wenn ich mit Httpclient statt HttpURLConnection wechseln, funktioniert alles einwandfrei:

// WORKS
public void testCommonsHttpOAuthConsumerAndroidBug() throws Exception {
    for (int i = 0; i < 2; ++i) {
        final HttpGet c = new HttpGet("https://api.tripit.com/oauth/request_token");
        final CommonsHttpOAuthConsumer consumer = new CommonsHttpOAuthConsumer(api_key, api_secret, SignatureMethod.HMAC_SHA1);
        consumer.sign(c);
        final HttpResponse response = new DefaultHttpClient().execute(c);
        final InputStream is = response.getEntity().getContent();
        while( is.read() >= 0 ) ;
        assertTrue( response.getStatusLine().getStatusCode() == 200);
    }
}

Ich habe Referenzen gefunden zu dem, was zu sein scheint ein ähnliches Problem an anderer Stelle, aber bisher keine Lösungen. Wenn sie wirklich das gleiche Problem sind, dann ist wahrscheinlich das Problem ist nicht mit Schild, da die anderen Referenzen keinen Hinweis auf sie zu machen.

Irgendwelche Ideen?

War es hilfreich?

Lösung

Versuchen Sie, diese Eigenschaft festgelegt, um zu sehen, ob es hilft,

http.keepAlive=false

ich ähnliche Probleme sah, als Server-Antwort nicht von URLConnection und Client verstanden wird / Server nicht synchronisiert wird.

Wenn dies Ihr Problem löst, müssen Sie eine HTTP-Spur zu erhalten, genau zu sehen, was über die Antwort Besonderes.

EDIT: Diese Änderung bestätigt nur meine Vermutung. Es löst nicht Ihr Problem. Es verbirgt sich nur das Symptom.

Wenn die Antwort von der ersten Anfrage 200 ist, brauchen wir eine Spur. Ich benutze normalerweise Ethereal / Wireshark die TCP-Spur zu erhalten.

Wenn Sie Ihre erste Reaktion nicht 200 ist, ich ein Problem in Ihrem Code sehen. Mit OAuth, die Fehlerreaktion (401) tatsächlich Daten zurückgibt, die ProblemAdvice enthält, Signature Basis String usw. Sie Debug helfen. Sie müssen alles von Fehlerstrom lesen. Ansonsten, es geht nächste Verbindung zu verwirren und das ist die Ursache von -1. Beispiel folgenden sehen Sie, wie Fehler richtig zu handhaben,

public static String get(String url) throws IOException {

    ByteArrayOutputStream os = new ByteArrayOutputStream();
    URLConnection conn=null;
    byte[] buf = new byte[4096];

    try {
        URL a = new URL(url);
        conn = a.openConnection();
        InputStream is = conn.getInputStream();
        int ret = 0;
        while ((ret = is.read(buf)) > 0) {
            os.write(buf, 0, ret);
        }
        // close the inputstream
        is.close();
        return new String(os.toByteArray());
    } catch (IOException e) {
        try {
            int respCode = ((HttpURLConnection)conn).getResponseCode();
            InputStream es = ((HttpURLConnection)conn).getErrorStream();
            int ret = 0;
            // read the response body
            while ((ret = es.read(buf)) > 0) {
                os.write(buf, 0, ret);
            }
            // close the errorstream
            es.close();
            return "Error response " + respCode + ": " + 
               new String(os.toByteArray());
        } catch(IOException ex) {
            throw ex;
        }
    }
}

Andere Tipps

Ich habe das gleiche Problem auftreten, wenn ich nicht in allen Daten aus dem Inputstream gelesen habe, bevor es zu schließen und eine zweite Verbindung zu öffnen. Es wurde auch entweder mit System.setProperty("http.keepAlive", "false"); fixiert oder einfach nur Looping, bis ich den Rest des Input gelesen haben.

Nicht ganz zu Ihrem Problem verwendet, aber hoffen, dass dies jemanden mit einem ähnlichen Problem hilft.

Google bereitgestellt eine elegante Abhilfe, da sie nur vor Froyo passiert:

private void disableConnectionReuseIfNecessary() {
    // HTTP connection reuse which was buggy pre-froyo
    if (Integer.parseInt(Build.VERSION.SDK) < Build.VERSION_CODES.FROYO) {
        System.setProperty("http.keepAlive", "false");
    }
}

Cf. http://android-developers.blogspot.ca/2011/09 /androids-http-clients.html

Alternativ können Sie HTTP-Header in der Verbindung gesetzt (HttpURLConnection):

conn.setRequestProperty("Connection", "close");

Können Sie bestätigen, dass die Verbindung nicht geschlossen zu werden, bevor Sie die Antwort gelesen haben? Vielleicht Httpclient den Code Antwort parst sofort und speichert sie für zukünftige Abfragen jedoch könnte HttpURLConnection sein liefert -1, wenn die Verbindung geschlossen wird?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top