Simple things that look complex: ping from android

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.

3 thoughts on “Simple things that look complex: ping from android”

  1. It would be helpful if you could post a full java class or a better tutorial.. for example the function of dobroadcast is not clear.. or if you could provide a source code to this

Leave a Reply