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

  2. After a few hours of going thru the same things you went thru this saved me…THANKS!

  3. Thank you very much for your good sources.
    That are very helful for me.
    Thanks again.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.