3

私は Android アプリを開発していますが、Android のバージョンが異なれば、Http(s)URLConnections (http://stackoverflow.com/q/9556316/151682) の処理方法も異なることがわかっています。

Android 4 が HTTPS 経由で POST リクエストを適切に実行し、以下のコードを実行すると Content-Type などのヘッダーが自動的に追加されるという問題に遭遇しました。

ただし、Android 2.3.5 (デバイスとエミュレーター) では、出力ストリームへの書き込みは無視されるようです。Web プロキシ Charles でデバッグしましたが、すべてのヘッダーが送信されている間、出力ストリームに書き込まれたデータは送信されません。 ...

誰でもこれを解決する方法を知っていますか?

注: 私が開発している API には自己署名証明書しかないため、現時点では証明書の検証を無効にする必要があります。

ティア、パトリック

更新 それまでの間、次のことも試みましたが、役に立ちませんでした:

  • BufferedOutputStream での呼び出しclose()後の呼び出しflush()
  • close()OutputStream と BufferedOutputStream の両方での呼び出し
  • 代わりに OutputStreamWriter を使用する
  • 電話close()する前に電話しないgetInputStream()

    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    connection.setConnectTimeout(CONNECT_TIMEOUT);
    
    connection.setDoOutput(true); // Triggers POST.
    connection.setRequestMethod("POST");
    int contentLength = 0;
    if(body != null) {
        contentLength = body.getBytes().length;
    }
    
    // Workarounds for older Android versions who do not do that automatically (2.3.5 for example)
    connection.setRequestProperty(HTTP.TARGET_HOST, url.getHost());
    connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
    
    // Set SSL Context -- Development only
    if(context != null && connection instanceof HttpsURLConnection){
        HttpsURLConnection conn = (HttpsURLConnection)connection;
        conn.setSSLSocketFactory(context.getSocketFactory());
        conn.setHostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        });
    }
    
    try{
        // Add headers
        if(headers != null){
            for (NameValuePair nvp : headers) {
                if(nvp != null){
                    connection.setRequestProperty(nvp.getName(), nvp.getValue());
                }
            }
        }
    
        connection.setFixedLengthStreamingMode(contentLength);
        OutputStream outputStream = null;
        try {
            if(body != null){
                outputStream = connection.getOutputStream();
                BufferedOutputStream stream = new BufferedOutputStream(outputStream);
                stream.write(body.getBytes()); // <<<< No effect ?!
                stream.flush();
    
            }
        } finally {
            if (outputStream != null) 
                try { 
                    outputStream.close(); 
                }
            catch (IOException logOrIgnore) {
                // ...
            }
        }
    
        InputStream inputStream = connection.getInputStream();
    
        // .... Normal case ....
    
    }
    catch(IOException e){
        // ... Exception! Check Error stream and the response code ...
    
    
    }
    finally{
        connection.disconnect();
    }
    

    }

4

2 に答える 2

6

私には、あなたが呼び出す順序DoSetOutputなどが奇妙な動作の理由のようです...

Android での HTTP POST の動作コードを含むいくつかのリンク/ソース:

于 2012-04-14T06:58:50.240 に答える
4

あ、やっと見つけた。間違った場所を探しています...問題はヘッダーでした:

上記のコードは実際には問題なく動作します。原因は、Base64 でエンコードされたヘッダーを含めたことです。私の Android 2.3.5 では、指定されたオプション ( Base64.DEFAULT) が最後に余分な改行を挿入しているようで、リクエストが途中で終了し、実際の本文を送信する時間がありません。Android 4 では、以下のリンク先の投稿で説明されているように、デフォルトが BASE64.NO_WRAP のようなものに変更されているようです...

これは実際にはすでに回答されています here

ご尽力いただきありがとうございます。

于 2012-04-21T18:39:23.380 に答える