12

I am making an application which will implement some features of the "ping" command.The problem is, I have no idea of which library/libraries to use in ANDROID. anyone have any idea for it?

I have visited these stackoverflow links but they weren't very helpful.

Community
  • 1
  • 1

3 Answers3

22

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.

pomber
  • 23,132
  • 10
  • 81
  • 94
Sahil Mahajan Mj
  • 11,033
  • 8
  • 53
  • 100
  • Totally Helpful.... My half work id done ... still cant understand how can i format output? do u have any advice for that? –  Jan 30 '13 at 05:28
  • do u know how to format the output ? it will be more helpful... thanks in advance.... i don't know which library to use –  Jan 30 '13 at 05:35
  • what do you mean by ***how to format the output ?*** what exactly you want to do with it. – Sahil Mahajan Mj Jan 30 '13 at 05:37
  • In the output it all print together and i want to print it like this(everything in new line): [ipaddress] [packet sequence no] [ttl] [rtt] –  Jan 30 '13 at 05:40
  • I jist tried to call this function on a button click public void pingTheServer(View view){ txtStatus.setText(ping("http://www.blueleaftech.in")); } But it couldnt display returned string, i've already set uses-permission Internet.. – Prasanth A R Nov 13 '14 at 11:40
14

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.
Community
  • 1
  • 1
Evyatar Tamir
  • 141
  • 1
  • 5
  • How do you protect a socket created in native code using the java-based VpnService.protect() method, e.g. do you have to return the fd from native code back into java and then call protect() with it? Also, if ping_group_range shows as "0 2147483647", does that mean it is enabled for all? – LBC Nov 09 '18 at 05:13
  • 1
    Answered it myself: yes, just return the fd from native code and pass the int directly into VpnService.protect(). After protecting, now able to recv the ICMP response. – LBC Nov 09 '18 at 05:41
2

I implemented "ping" in pure Android Java and hosted it on gitlab. It's has a couple useful features like being able to bind to a given Network.

https://github.com/dburckh/AndroidPing

Dustin
  • 2,064
  • 1
  • 16
  • 12