Кодинг под мобильные платформы, это то еще удовольствие. Наверное, начиная с времен J2ME. С надеждой жду, когда Jolla Mobile выкатит свою продукцию на рыкок, ибо iOS и android это та еще пакость. Ну а пока выбираю дройд, как меньшее из зол и более вменяемое.
Потребовалось мне на днях пингануть приложением интернеты, проверить живо ли оно да в зависимости от этого пошаманствовать. Свежа история, на прошлой неделе человек рассказывал мне про лютые извращения с SCNetworkCheckReachabilityByName на iOS для этой цели, пришла теперь моя очередь познакомиться с этим адом в контексте андроеда.
Раскурив документацию, наваяв активити, ресивер броадкастов и вытащив пинг в отдельный тред, который стартовал из службы, дабы не блокировать рендер гуи, я нарисовал нижеследующий код.
(Сразу предупреждаю, я системный программер, знающий жабу чуть менее, чем никак, потому оно вполне может быть достойно занесения на говнокод)
/* 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;
}
Все просто, пингуем десять раз посылая уведомления броадкастами гую. И все бы хорошо, даже пинганул IP роутера. Да вот сетевой узел для пинга, 8.8.8.8 так и не осилил пингануть. Фейл, да и все тут.
Чешем голову, читаем документацию, stackoverflow, материм {Гугл, Oracle, Sun}, и выдавливаем методом частичной копипасты из себя такой код:
/* 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;
}
На выходе получаем еще один фейл. Не, ну не вызывать же из жабы консольную утилиту ping и не парсить ее exit code? А пришлось.
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;
}
И это будучи хоть и грязным хаком, но заработало без проблем.
Leave a Reply