2017-02-05 9 views
7

Я пытаюсь выполнить вызов POST с использованием HttpUrlConnection, но без успеха. Я часто получаю сообщение об ошибке «IllegalStateException: already connected». Меня не интересует повторное использование соединения. Пожалуйста, проверьте мой код и скажите мне, если я делаю что-то неправильно:Android POST-запрос с использованием HttpUrlConnection «уже подключен»

public static final int CONNECTION_TIME_OUT = 10000; 

public SimpleResponse callPost(String urlTo, Map<String, String> params) { 
    System.setProperty("http.keepAlive", "false"); 
    HttpURLConnection conn = null; 
    SimpleResponse response = new SimpleResponse(0, null); 
    try { 
     URL url = new URL(urlTo); 
     conn = (HttpURLConnection) url.openConnection(); 
     conn.setUseCaches(false); 
     conn.setAllowUserInteraction(false); 
     conn.setConnectTimeout(CONNECTION_TIME_OUT); 
     conn.setReadTimeout(CONNECTION_TIME_OUT); 
     conn.setInstanceFollowRedirects(false); 
     conn.setRequestMethod("POST"); 
     conn.setRequestProperty("Connection", "close"); 
     conn.setRequestProperty("Content-type", "application/x-www-form-urlencoded"); 
     conn.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length)); 
     conn.setDoOutput(true); 

     OutputStream os = conn.getOutputStream(); 
     BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8")); 
     writer.write(paramsToString(params)); 
     writer.flush(); 
     writer.close(); 
     os.close(); 

     int responseCode = conn.getResponseCode(); 
     if (responseCode == HttpURLConnection.HTTP_OK) { 
      InputStream in = conn.getInputStream(); 
      String result = StringUtils.fromInputStream(in); 
      response = new SimpleResponse(responseCode, result); 
      in.close(); 
     } else { 
      response = new SimpleResponse(responseCode, null); 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    if (conn != null) { 
     conn.disconnect(); 
    } 
    return response; 
} 

private String paramsToString(Map<String, String> params) { 
     if (params == null || params.isEmpty()) { 
      return ""; 
     } 
     Uri.Builder builder = new Uri.Builder(); 
     for (Map.Entry<String, String> entry : params.entrySet()) { 
      builder.appendQueryParameter(entry.getKey(), entry.getValue()); 
     } 
     return builder.build().getEncodedQuery(); 
    } 

Update:

Работы иногда, а иногда и не делает!
Работы над некоторыми проектами, на других нет!
Точно такой же код и каждый раз одно и то же исключение: Уже подключено
Почему я не могу получить новое новое соединение каждый раз?

+0

Конечно, есть проблема с деятельностью, пожалуйста, добавьте свой код. – W4R10CK

+0

@ W4R10CK Я просто звоню внутри AsyncTask –

+0

@HamzehSoboh, какая линия уже запущена? –

ответ

3

Я думаю, ваша проблема заключается в следующем:

 conn.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length)); 

Я не могу видеть, где postDataBytes объявлена, но так как вы обрабатываете параметры в paramsToString, я думаю, что они не имеют никакого отношения.

Теперь я не эксперт по RFC 2616 (HTTP), но я думаю, что длина postDataBytes больше вашего размера запроса, поэтому сервер не отключает сокет на своем конце. Те объекты URLConnection объединены, поэтому, когда вы идете, чтобы получить объект соединения, его значения были очищены для повторного использования, но фактическое соединение все еще открыто.

Вот код, я думаю, вам стоит попробовать. Если это не исправить вашу проблему, я не получаю бонус респ, но это все-таки определенно более правильным, чем то, что у вас есть:

private static final String CHARSET = "ISO-8859-1"; // or try "UTF-8" 

public SimpleResponse callPost(String urlTo, Map<String, String> params) { 

// get rid of this... 
// System.setProperty("http.keepAlive", "false"); 

    HttpURLConnection conn = null; 
    SimpleResponse response = new SimpleResponse(0, null); 
    try { 
     URL url = new URL(urlTo); 
     conn = (HttpURLConnection) url.openConnection(); 
     conn.setUseCaches(false); 
     conn.setAllowUserInteraction(false); 
     conn.setConnectTimeout(CONNECTION_TIME_OUT); 
     conn.setReadTimeout(CONNECTION_TIME_OUT); 
     conn.setInstanceFollowRedirects(false); 
     conn.setRequestMethod("POST"); 
// ... and get rid of this 
//  conn.setRequestProperty("Connection", "close"); 
     conn.setRequestProperty("Content-type", "application/x-www-form-urlencoded; charset=" + CHARSET); 

     String content = paramsToString(params); 
     int length = content.getBytes(Charset.forName(CHARSET)).length; 
     conn.setRequestProperty("Content-Length", Integer.toString(length)); 
     conn.setDoOutput(true); 

     OutputStream os = conn.getOutputStream(); 
     BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, CHARSET)); 
     writer.write(content); 
     writer.flush(); 
     writer.close(); 
     os.close(); 

     int responseCode = conn.getResponseCode(); 
     if (responseCode == HttpURLConnection.HTTP_OK) { 
      InputStream in = conn.getInputStream(); 
      String result = StringUtils.fromInputStream(in); 
      response = new SimpleResponse(responseCode, result); 
      in.close(); 
     } else { 
      response = new SimpleResponse(responseCode, null); 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    if (conn != null) { 
     conn.disconnect(); 
    } 
    return response; 
} 

Я извиняюсь за любые ошибки компиляции. Я бесполезен без IDE. Я доказал это как можно лучше.

Я использовал кодировку Latin-1. Если это не поможет вам, вы можете попробовать UTF-8.

Другая вещь, которую вы можете попробовать это отказ от длины содержания в целом и вызывая

 conn.setChunkedStreamingMode(0); 

И да, я понимаю, что getBytes() вызов и OutputStreamWriter дублируют один и тот же процесс. Вы можете работать над этим, как только вы устраните эту проблему.

+0

Th спасибо за ваш ответ! Но можете ли вы представить, что ваш код и моя авария на «conn.setUseCaches» и по первому запросу! Я начал полагать, что запрос третьей стороны не отключен. Я импортирую отчеты о сбоях в firebase и аналитику google в свой проект. Но я не уверен, что это причина. Что заставляет меня думать, так это то, что когда я создаю новый проект и выполняю тот же самый точный код, он работает безупречно! –

+0

Если ваш код работает сам по себе в новом проекте, то вам нужно взять этот проект и добавить свой код firebase или analytics немного за раз, пока не найдете изменения, которые приводят к сбою вашего кода. * Что-то * заставляет открытые подключения возвращаться в пул соединений, вам нужно выяснить, что это такое. –

+0

OK kris, вы получили баллы, но я не принял ответ, так как он все еще анонимный мне, что вызывает эту проблему и почему это происходит случайно! Благодарю. –

0

Я не могу понять, почему вы получаете «уже связанную ошибку», но вот код, который я использую для выполнения запросов POST. Я закрыть потоки ввода/вывода и соединение после отправки запроса, который может помочь вам (хотя я не уверен точно)

try { 
     URL url = new URL(stringURL); 
     HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 
     connection.setRequestMethod("POST"); 
     connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8"); 
     connection.setRequestProperty("Accept","application/json"); 
     //connection.setRequestProperty("Content-Length", Integer.toString(urlParameters.getBytes().length)); 
     //connection.setRequestProperty("Connection", "Keep-Alive"); 
     connection.setReadTimeout(10*1000); 
     connection.setUseCaches(false); 
     connection.setDoInput(true); 
     connection.setDoOutput(true); 

     //Request 
     DataOutputStream wr = new DataOutputStream(connection.getOutputStream()); 
     wr.writeBytes(params[1]); 
     wr.flush(); 
     wr.close(); 

     //Response 
     InputStream is = connection.getInputStream(); 
     BufferedReader rd = new BufferedReader(new InputStreamReader(is)); 
     String line; 
     response = new StringBuffer(); 
     //Expecting answer of type JSON single line {"json_items":[{"status":"OK","message":"<Message>"}]} 
     while ((line = rd.readLine()) != null) { 
      response.append(line); 
     } 
     rd.close(); 
     System.out.println(response.toString()+"\n"); 
     connection.disconnect(); // close the connection after usage 

    } catch (Exception e){ 
     System.out.println(this.getClass().getSimpleName() + " ERROR - Request failed"); 
    } 
0

Существует несколько Tuts в Интернете, которые могут помочь вам

  1. Android HttpURLConnection сообщение и получить запрос учебник here

  2. Как использовать HttpURLConnection данные POST на веб-сервер?here

  3. Android POST и GET запрос с использованием HttpURLConnection Учебник here