1

Android で非常に奇妙な動作が発生しています。私たちのネットワーク スタック (REST サーバーと対話する) は、大規模な POST を実行した直後に GET を実行する場合を除いて、ほぼすべての状況で正常に動作します。発生しているように見えるのは、出力ストリームがフラッシュされておらず、新しいソケットが開かれたときにそこにあった最後の行を送信してしまうことです。各接続は作成された新しいオブジェクトであるため、これは予期しない動作であることに注意してください。まず、出力ストリームを指しているように見えるエラー コードです。これらはサーバー ログからのものです。

10.1.8.195 - - [07/11/2012:13:36:28 -0700] "POST /iou/lender HTTP/1.1" 200 28 "-" "Android" 10.1.8.195 - - [2012 年 11 月 7 日: 13:36:36 -0700] "------------V2ymHFg03ehbqgZCaKO6jy" 400 173 "-" "-"

その後の試行は、POST を介して追加された新しいエントリを含むデータをサーバーからプルする GET である必要があります。ただし、取得できるのは、POST からの出力ストリームの最後の行のように見えるものだけです。これがネットワーク スタックのコア コードです。周囲のコードがさらに必要な場合はお知らせください。

public Object serverConnect(String url, String method,
        Hashtable<String, Object> params) {

    HttpConnection c = null;
    InputStream is = null;
    OutputStream out = null;
    ByteArrayOutputStream postDataByteArrayImage = new ByteArrayOutputStream();
    byte[] data;
    String boundry = "----------V2ymHFg03ehbqgZCaKO6jy";
    try {
        if (!url.startsWith("/")) {
            url = "/" + url;
        }
        String uri = Control.URL_Secure + Control.dtserver + ":"
                + Control.port + url;
        ByteArrayOutputStream postDataByteArray = new ByteArrayOutputStream();

        params.put("sessionId", Control.sessionId);

        if (method.equals("GET")) {
            uri = uri + "?";
            Enumeration enumParams = params.keys();
            while (enumParams.hasMoreElements()) {
                if (!uri.endsWith("?")) {
                    uri = uri + "&";
                }
                String key = (String) enumParams.nextElement();
                uri = uri
                        + key
                        + "="
                        + java.net.URLEncoder.encode((String) params
                                .get(key));

            }
        } else if (method.equals("POST")) {
            Enumeration enumParams = params.keys();
            postDataByteArray.write(("--").getBytes());
            postDataByteArray.write((boundry).getBytes());
            postDataByteArray.write(("\r\n").getBytes());
            while (enumParams.hasMoreElements()) {
                String key = (String) enumParams.nextElement();
                if (!key.equals("image")){
                    postDataByteArray
                            .write(("Content-Disposition: form-data; name=\"")
                                    .getBytes());
                    postDataByteArray.write((key).getBytes());
                    postDataByteArray.write(("\"").getBytes());
                    postDataByteArray.write(("\r\n\r\n").getBytes());
                    postDataByteArray.write(((String) params.get(key))
                            .getBytes());
                    postDataByteArray.write(("\r\n").getBytes());
                    postDataByteArray.write(("--").getBytes());
                    postDataByteArray.write(boundry.getBytes());
                    postDataByteArray.write(("\r\n").getBytes());
                }
            }
            postDataByteArray.close();

        }
        Log.i("URL", uri);
        URL urltoConenct = new URL(uri);
        URLConnection connection = urltoConenct.openConnection();
        HttpURLConnection urlConnection = (HttpURLConnection) connection;

        URLConnection.setDefaultRequestProperty("Method", method); // default
        urlConnection.setRequestProperty("User-Agent", "Android");
        if (method.equals("POST")) {
            urlConnection.setDoOutput(true);
            urlConnection.setFixedLengthStreamingMode(postDataByteArray.toByteArray().length + postDataByteArrayImage.toByteArray().length);
            urlConnection.setRequestProperty("Content-Type",
                    "multipart/form-data; boundary=" + boundry);
            out = urlConnection.getOutputStream();
            out.write(postDataByteArray.toByteArray());
            out.write(postDataByteArrayImage.toByteArray());
            out.close();
        }
        int response = 0;
        try {
            response = urlConnection.getResponseCode();
        } catch (IOException e) {
            if (e.toString()
                    .equals("java.io.IOException: Received authentication challenge is null"))
                throw new RESTException(401, "Invalid Phone or Pin");
            else
                throw e;
        }

        if (response == HttpURLConnection.HTTP_OK) {

            is = urlConnection.getInputStream();
            if (is == null) {
                return new IOException(
                        "Cannot open HTTP InputStream, aborting");
            }

            ByteArrayOutputStream bo = new ByteArrayOutputStream();
            int ch;
            int count = 0;

            while ((ch = is.read()) != -1) {
                bo.write(ch);
                count++;

            }
            data = bo.toByteArray();

            return new String(data);
        } else if (response == 500) {
            return new RESTException(500, "Internal server error");
        } else {
            RESTException x = new RESTException();
            x.setCode(response);
            try {
                is = urlConnection.getInputStream();
                if (is == null) {
                    x.setMessage("Unable to retrieve message");
                    return x;
                }

                ByteArrayOutputStream bo = new ByteArrayOutputStream();
                int ch;
                int count = 0;

                while ((ch = is.read()) != -1) {
                    bo.write(ch);
                    count++;
                }
                data = bo.toByteArray();

                String output = new String(data);
                JSONObject obj;

                try {

                    obj = new JSONObject(output);
                    JSONObject err = obj.getJSONArray("errors")
                            .getJSONObject(0);
                    x.setMessage(err.getString("message"));
                } catch (JSONException e) {
                    Log.e("stuff", output);
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            } catch (FileNotFoundException e) {
                // Damn you android! I'm using a REST service here, stop
                // trying to interpret my errors!
                x.setMessage("Unable to retrieve message");
            }
            return x;
        }
    } catch (Exception x) {
        x.printStackTrace();
        /*
         * if (!retried && x.toString().equals(
         * "java.io.IOException: Persistent connection dropped after first chunk sent, cannot retry"
         * )) { retry = true; } if (!retry) { return x; }
         */
        return x;
    } finally {
        try {
            out.close();
        } catch (Exception x) {

        }
        try {
            is.close();
        } catch (Exception x) {

        }
        try {
            c.close();
        } catch (Exception x) {

        }
        params.clear();

    }

    // return null;
  }
4

1 に答える 1

0

非常に長い間フラストレーションを感じていた後、接続で.close()を手動で呼び出した場合でも、Androidが接続を維持しようとしていることがわかりました。これはGETメソッドでは正常に機能しましたが、POSTメソッドはソケットをGETを処理できない状態のままにしました。以下を追加すると、すべての問題が修正されました。

urlConnection.setRequestProperty("connection", "close");
于 2012-11-19T13:10:53.690 に答える