Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IP fallback in android

I'm accessing a server for web service calls. When I'm developing on the same network as the server, I can access the web service by its internal IP address but not its external IP address. However, if I'm not on the network, I can only access it by its external IP address. What's the best way to try one of the IP addresses and then fall back on the other?

Here's a sample of my code for accessing only one or the other:

protected String retrieve() {
    Log.v(TAG, "retrieving data from url: " + getURL());

    HttpPost request = new HttpPost(getURL());
    try {
        StringEntity body = new StringEntity(getBody());
        body.setContentType(APPLICATION_XML_CONTENT_TYPE);
        request.setEntity(body);            

        HttpConnectionParams.setConnectionTimeout(client.getParams(), CONNECTION_TIMEOUT);
        HttpConnectionParams.setSoTimeout(client.getParams(), SOCKET_TIMEOUT);

        HttpResponse response = client.execute(request);
        final int statusCode = response.getStatusLine().getStatusCode();


        if (statusCode != HttpStatus.SC_OK) {
            Log.e(TAG, "the URL " + getURL() + " returned the status code: " + statusCode + ".");
            return null;
        }

        HttpEntity getResponseEntity = response.getEntity();

        if (getResponseEntity != null) {
            return EntityUtils.toString(getResponseEntity);
        }
    } catch (IOException e) {
        Log.e(TAG, "error retrieving data.", e);
        request.abort();
    }

    return null;
}   

/*
 * @return the URL which should be called.
 */
protected String getURL() {
    return INTERNAL_SERVER_URL + WEB_APP_PATH;
}
like image 480
Zack Marrapese Avatar asked May 13 '11 20:05

Zack Marrapese


4 Answers

Look at own IP address of your android. You can get it like stated here.

Then you can decide:

  • if you are in subnet of your office (e.g. 192.168.0.0/16) - use internal address
  • if you are in other subnet - use external address
like image 78
Andrey Regentov Avatar answered Nov 12 '22 08:11

Andrey Regentov


Building on the very good comment by harism, I would simply use a static boolean to choose the IP and thus avoid pinging the wrong IP every time:

public static final Boolean IS_DEBUG = true; // or false

// all your code here

if (DEBUG)
    ip = xxx.xxx.xxx.xxx;
else
    ip = yyy.yyy.yyy.yyy;
like image 34
Aleadam Avatar answered Nov 12 '22 09:11

Aleadam


This isn't exactly something you can easily fix in software. The right answer I think is fixing the filters/configuration that route traffic to your internal web server or by properly configuring DNS to return the proper IP depending on where you are (inside or outside the network). More information can be found here:

Accessing internal network resource using external IP address

http://www.astaro.org/astaro-gateway-products/network-security-firewall-nat-qos-ips-more/6704-cant-acces-internal-webserver-via-external-ip.html

and by Googling something like "external IP doesn't work on internal network"

like image 3
Pedantic Avatar answered Nov 12 '22 08:11

Pedantic


You could put retry code in the catch clause for IOException

protected String retrieve(String url) {
    Log.v(TAG, "retrieving data from url: " + url);

    HttpPost request = new HttpPost(url);
    try {
        StringEntity body = new StringEntity(getBody());
        body.setContentType(APPLICATION_XML_CONTENT_TYPE);
        request.setEntity(body);            

        HttpConnectionParams.setConnectionTimeout(client.getParams(), CONNECTION_TIMEOUT);
        HttpConnectionParams.setSoTimeout(client.getParams(), SOCKET_TIMEOUT);

        HttpResponse response = client.execute(request);
        final int statusCode = response.getStatusLine().getStatusCode();


        if (statusCode != HttpStatus.SC_OK) {
            Log.e(TAG, "the URL " + getURL() + " returned the status code: " + statusCode + ".");
            return null;
        }

        HttpEntity getResponseEntity = response.getEntity();

        if (getResponseEntity != null) {
            return EntityUtils.toString(getResponseEntity);
        }
    } catch (IOException e) {
        if(url.equals(EXTERNAL_URL){
            return retrieve(INTERNAL_URL);
        }

        Log.e(TAG, "error retrieving data.", e);
        request.abort();
    }

    return null;
}   

Note: Like most people have said, this probably is not a great solution for a production release, but for testing it would probably work just fine.

like image 3
walta Avatar answered Nov 12 '22 08:11

walta