Coding for a mobile platform has always been a frustrating experience ever since J2ME. Right now I really hope, that Jolla Mobile will succeed and roll their thingie to the market, since both iOS and android are smoking crap. But for now – I choose droid as a lesser evil.
So, a few days ago I needed to ping the internets from my app, to check if the connection is live. It’s been less than a week since a friend told me of all the ‘fun’ he had with SCNetworkCheckReachabilityByName on iOS for that purpose.
So, after giving the specs a read, I quickly threw up an activity, a broadcast receiver, moved the actual pings to a different thread placed in a service, to keep render thread clean responsive. I ended up with the following code.
(Please note, that despite I write apps in java for droid, used to write J2ME apps quite a few times, I’m NOT a java coder, so it may look like crap)
/* proper way. works on local ips, sucks on 8.8.8.8 */
public int doInAvaliable(int count, int delay, String host) {
InetAddress in;
in = null;
int ok = 0;
int i;
for (i = 0; i < count; i++) {
if (!active)
return ok;
try {
in = InetAddress.getByName(host);
} catch (UnknownHostException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
if (in.isReachable(delay)) {
Log.d(TAG, "Network looks fine");
doBroadcast(scanResultsReceiver.action_ping_ok);
ok++;
} else {
Log.d(TAG, "Timeout, it's dead");
doBroadcast(scanResultsReceiver.action_ping_fail);
}
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (IOException e) {
Log.d(TAG, "Caught an exception: " + e.toString());
}
}
return ok;
}
So, it's simple, ping a few times, send results in broadcasts to the GUI. However, it worked when pinging a router IP, but failed with google's 8.8.8.8. Just fail.
Thinking for a while, reading more specs, stackoverflow, calling {Google, Oracle, Sun} and others retarted... You know, usual 'hate-driven development'... I managed to squeeze this code:
/* Is crappy, doesn't work at all */
public int doSocket(int count, int delay, String host) {
Socket socket = null;
boolean reachable = false;
int i, ok = 0;
for (i = 0; i < count; i++) {
if (!active)
return ok;
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
socket = new Socket(host, 80);
ok++;
doBroadcast(scanResultsReceiver.action_ping_ok);
} catch (IOException e) {
doBroadcast(scanResultsReceiver.action_ping_fail);
} finally {
if (socket != null)
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return ok;
}
And got another fail. After trying a few more solutions, I ended up with the most ugly and dumb way that actually worked for me.
public int doPing(int count, int delay, String host) {
int i, r;
int ok = 0;
for (i = 0; i < count; i++) {
r = 3;
if (!active)
return 0;
try {
Thread.sleep(delay);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
r = pingHost(host, delay);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (r == 0) {
doBroadcast(scanResultsReceiver.action_ping_ok);
ok++;
} else
doBroadcast(scanResultsReceiver.action_ping_fail);
}
return ok;
}
/**
* Ping a host and return an int value of 0 or 1 or 2 0=success, 1=fail,
* 2=error
*
* Does not work in Android emulator and also delay by '1' second if host
* not pingable In the Android emulator only ping to 127.0.0.1 works
*
* @param String
* host in dotted IP address format
* @return
* @throws IOException
* @throws InterruptedException
*/
public static int pingHost(String host, int timeout) throws IOException,
InterruptedException {
Runtime runtime = Runtime.getRuntime();
timeout /= 1000;
String cmd = "ping -c 1 -W " + timeout + " " + host;
Process proc = runtime.exec(cmd);
Log.d(TAG, cmd);
proc.waitFor();
int exit = proc.exitValue();
return exit;
}
And despite being a dirty hack, it worked like a charm.
Leave a Reply