Search code examples
androidproxyhttpconnection

Proper way to make a HTTP request in Android


Which is the best way to make a HTTP connection. I mean using proxies and so on. Now I'm using this one:

StringBuilder entity = new StringBuilder();
entity.append("request body");

AndroidHttpClient httpClient = AndroidHttpClient.newInstance(null);

String proxyHost = android.net.Proxy.getDefaultHost();
int proxyPort = android.net.Proxy.getDefaultPort();
if (proxyHost != null && proxyPort > 0) {
    HttpHost proxy = new HttpHost(proxyHost, proxyPort);
    ConnRouteParams.setDefaultProxy(httpClient.getParams(), proxy);
}
HttpPost httpPost = new HttpPost("https://w.qiwi.ru/term2/xmlutf.jsp");
httpPost.setEntity(new StringEntity(entity.toString(), "UTF-8"));
httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");
HttpParams params = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(params, 15000);
HttpConnectionParams.setSoTimeout(params, 30000);
httpPost.setParams(params);
HttpResponse httpResponse = httpClient.execute(httpPost);

int responseCode = httpResponse.getStatusLine().getStatusCode();
if (responseCode == HttpStatus.SC_OK) {
    // parsing response
}

I'm not really sure if that's ok, because one of my clients tells me he has an IllegalArgumentException right after setting proxy in his APN settings.


Solution

  • Use one method called executeRequest which makes the actual call to the host API_REST_HOST, this way (API_REST_HOST can be a value like "api.flickr.com" for flickr's rest api. The HTTP and the port get added)

     private void executeRequest(HttpGet get, ResponseHandler handler) throws IOException {
        HttpEntity entity = null;
        HttpHost host = new HttpHost(API_REST_HOST, 80, "http");
        try {
            final HttpResponse response = mClient.execute(host, get);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                entity = response.getEntity();
                final InputStream in = entity.getContent();
                handler.handleResponse(in);
            }
        } catch (ConnectTimeoutException e) {
            throw new ConnectTimeoutException();
        } catch (ClientProtocolException e) {
            throw new ClientProtocolException();
        } catch (IOException e) {
            e.printStackTrace();
            throw new IOException();
        } 
        finally {
            if (entity != null) {
                try {
                    entity.consumeContent();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    

    Call this API from here this way:

    final HttpGet get = new HttpGet(uri.build().toString());
        executeRequest(get, new ResponseHandler() {
            public void handleResponse(InputStream in) throws IOException {
                parseResponse(in, new ResponseParser() {
                    public void parseResponse(XmlPullParser parser)
                            throws XmlPullParserException, IOException {
                        parseToken(parser, token, userId);
                    }
                });
            }
        });
    

    Where your uri is constructed like this:

    final Uri.Builder builder = new Uri.Builder();
    builder.path(ANY_PATH_AHEAD_OF_THE_BASE_URL_IF_REQD);
    builder.appendQueryParameter(PARAM_KEY, PARAM_VALUE);
    

    Your mClient is declared as a class level variable this way

    private HttpClient mClient;
    

    and finally your parseResponse can be done in this way(say you want to parse XML data)

    private void parseResponse(InputStream in, ResponseParser responseParser) throws IOException {
        final XmlPullParser parser = Xml.newPullParser();
        try {
            parser.setInput(new InputStreamReader(in));
    
            int type;
            while ((type = parser.next()) != XmlPullParser.START_TAG &&
                    type != XmlPullParser.END_DOCUMENT) {
                // Empty
            }
    
            if (type != XmlPullParser.START_TAG) {
                throw new InflateException(parser.getPositionDescription()
                        + ": No start tag found!");
            }
    
            String name = parser.getName();
            if (RESPONSE_TAG_RSP.equals(name)) {
                final String value = parser.getAttributeValue(null, RESPONSE_ATTR_STAT);
                if (!RESPONSE_STATUS_OK.equals(value)) {
                    throw new IOException("Wrong status: " + value);
                }
            }
    
            responseParser.parseResponse(parser);
    
        } catch (XmlPullParserException e) {
            final IOException ioe = new IOException("Could not parse the response");
            ioe.initCause(e);
            throw ioe;
        }
    }
    

    This code takes care of all of the possible exceptions and shows how to properly parse response coming from an input stream out of a HTTP connection.

    As you already know please make sure you use this in a separate thread and not in the UI thread. That's it :)