0

I have an issue in an app I developed - various users report that they are having issues with connectivity (only with my app). For example:

  • Other apps seem to be able to access the internet, though mine cannot at the same time
  • It only works over WiFi, but not over the mobile data connection.

My app connects via HttpUrlConnection (HTTPS) to a REST-based API.

A mistake of mine is that I don't really have a possibility to know which network errors occurred on a users phone (the error message says a generic 'No network'). I already implemented a limited retry to compensate for the issue, but I am at a loss what could be wrong otherwise.

My main network code is attached below, my questions to all experienced networking programmers:

  1. Is there something wrong with my code?
  2. Are the timeouts set realistically? (15sec for connect / read each)
  3. What kind of best practices are there to show or the cause of networking errors to the user or to diagnose it post-release?

-> Please NO advice "Use HTTPClient instead of HttpUrlConnection"

Code for creating a POST request:

public static HTTPURLResponseHolder doHTTPPost(URL url, List<NameValuePair> headers, String body, String charset, boolean followRedirect,
        SSLContext context) throws IOException {
    HttpURLConnection connection = getConfiguredConnection(url, headers, charset, context, true);

    // WORKAROUND for recycling issue...
    // http://stackoverflow.com/questions/19258518/
    connection.setRequestProperty("Connection", "close");

    connection.setRequestMethod("POST");
    int contentLength = 0;
    if (body != null) {
        contentLength = body.getBytes().length;
    }

    try {
        connection.setFixedLengthStreamingMode(contentLength);
        BufferedOutputStream stream = null;
        try {
            OutputStream outputStream = null;
            if (body != null) {
                outputStream = connection.getOutputStream();
                stream = new BufferedOutputStream(outputStream);
                stream.write(body.getBytes());
                stream.flush();
            }
        } finally {
            close(stream);
        }

        InputStream inputStream = connection.getInputStream();
        HTTPURLResponseHolder holder = new HTTPURLResponseHolder();

        int responseCode = connection.getResponseCode();
        holder.setResponseCode(responseCode);

        // Normal case:
        String o = StreamUtility.inputStreamToString(inputStream, charset);
        close(inputStream);
        holder.setOutput(o);
        return holder;
    } catch (IOException e) {
        return handleIOException(url, headers, charset, false, context, connection);
    } finally {
        connection.disconnect();
    }
}

static HttpURLConnection getConfiguredConnection(URL url, List<NameValuePair> httpHeaders, String charset, SSLContext context, boolean doOutput)
        throws IOException {
    if (url == null || url.getProtocol() == null || !url.getProtocol().toLowerCase(Locale.US).startsWith("http")) {
        throw new IllegalArgumentException("Invalid HTTP URL: " + url);
    }

    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    connection.setConnectTimeout(15000);
    connection.setReadTimeout(15000);
    connection.setDoInput(true); // Read
    if (doOutput) {
        connection.setDoOutput(doOutput);
    }

    // Workaround for older Android versions who do not do that automatically (2.3.5 for example)
    connection.setRequestProperty(HTTP.TARGET_HOST, url.getHost());
    connection.setRequestProperty("Accept-Encoding", charset);

    // Langauge
    String language = Locale.getDefault().getLanguage();
    if (StringUtility.isNullOrEmpty(language)) {
        language = Locale.US.getLanguage();
    }
    connection.setRequestProperty("Accept-Language", language);

    // Add the headers, if they exist
    if (httpHeaders != null) {
        for (NameValuePair nvp : httpHeaders) {
            if (nvp != null) {
                connection.setRequestProperty(nvp.getName(), nvp.getValue());
            }
        }
    }
    return connection;
}
Patrick
  • 4,720
  • 4
  • 41
  • 71
  • the problem might be related to problem with 4.4 and connection, I had problem with streaming and recording internet radio. And the first real solution was to use HttpOK library. http://stackoverflow.com/questions/21812483/unexpected-status-line-icy-200-ok-for-url-openstream-method – deadfish Jun 09 '14 at 18:34
  • @deadfish OkHttp would have been my last resort, but I don't want to capitulate to that networking code - yet ;) – Patrick Jun 10 '14 at 11:28

0 Answers0