Ping Application in Android
I have used following code to ping.
public String ping(String url) {
String str = "";
try {
Process process = Runtime.getRuntime().exec(
"/system/bin/ping -c 8 " + url);
BufferedReader reader = new BufferedReader(new InputStreamReader(
process.getInputStream()));
int i;
char[] buffer = new char[4096];
StringBuffer output = new StringBuffer();
while ((i = reader.read(buffer)) > 0)
output.append(buffer, 0, i);
reader.close();
// body.append(output.toString()+"\n");
str = output.toString();
// Log.d(TAG, str);
} catch (IOException e) {
// body.append("Error\n");
e.printStackTrace();
}
return str;
}
Here in the url, you need to pass the address, on which you want to ping.
Thank you for researching the issue. The questions you've linked to (and many others on SO) all lead to the solutions of using either the system's ping executable or trying the dubious InetAddress.isReachable method. There is, however, a third alternative - if you're willing to add a little native code.
I have recently implemented ICMP Echo (ping) functionality for an Android VPN application. I couldn't use the system "ping" executable as the ICMP packets it sends were caught by my VPN, and at any rate I wanted to be able to forward ICMP packets from my network to the outside world and receive the replies.
The InetAddress.isReachable method didn't work for me at all (always returned false), as has been discussed thoroughly in SO, e.g. here and here.
The solution I arrived at is using native code to create an ICMP socket, which I used to send and receive ICMP packets (Echo requests and replies for "ping"). The Linux kernel supports (since 2011) the creation of ICMP sockets without any special privileges. A new ICMP socket is created as a Datagram socket with the protocol PROT_ICMP. A good implementation example in C can be seen in this answer.
The ICMP socket functionality has been ported to Android as well, and even used in the "ping" program. In fact it has been suggested that it can be used to fix the implementation of InetAddress.isReachable().
Java API does not support this functionality, but using native code it is possible to open ICMP sockets. I used JNA to access the libC functions I needed (socket(), close(), sendto(), recvfrom(), poll(), etc.). I suppose JNI would work just as well.
To get around the VPN limitation, the socket file descriptor needs to be protected using VpnService.protect(int).
There are a couple of caveats, as explained in the LWN article:
- Remember to verify that your system allows ICMP sockets, by reading (and possibly setting) the contents of "/proc/sys/net/ipv4/ping_group_range".
- The kernel modifies the "identifier" field in the ICMP header, you will have to reset it (and recompute the checksum) if you intend to forward the reply packet to the original requester.