63

I am developing a Ping application for Android 2.2.

I try my code and it works, but only in local IPs, that's my problem I want to do ping to external servers too.

Here is my code:

  private OnClickListener milistener = new OnClickListener() {
    public void onClick(View v) {
        TextView info = (TextView) findViewById(R.id.info);
        EditText edit = (EditText) findViewById(R.id.edit);
        Editable host = edit.getText();
        InetAddress in;
        in = null;
        // Definimos la ip de la cual haremos el ping
        try {
            in = InetAddress.getByName(host.toString());
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        // Definimos un tiempo en el cual ha de responder
        try {
            if (in.isReachable(5000)) {
                info.setText("Responde OK");
            } else {
                info.setText("No responde: Time out");
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            info.setText(e.toString());
        }
    }
};

Ping 127.0.0.1 -> OK
Ping 8.8.8.8 (Google DNS) -> Time Out

I put the following line at Manifest XML too:

<uses-permission android:name="android.permission.INTERNET"></uses-permission>

Can anyone suggest me where I'm doing wrong?

swiftBoy
  • 35,607
  • 26
  • 136
  • 135
Luks89
  • 631
  • 1
  • 6
  • 6
  • More information too ^^ Do you test it in the Emulator or on a real device? Do you have internet connection enabled? i.e. on a real device make sure the "mobile network" is activated and that you have an internet connection – Tseng Oct 11 '10 at 10:41
  • I tested in the Emulator and on a Real Device connected to the internet. Thanks. – Luks89 Oct 11 '10 at 10:44
  • Did you come right with this issue? I am having the same problem. If you got around this problem, could you also advise me. Regards Sanjay –  Jun 10 '11 at 16:09
  • I am also facing same problem can you please provide solution to this if you found! – User7723337 Mar 19 '12 at 08:47
  • 1
    got to this link , i got answer from this, http://stackoverflow.com/questions/14576710/ping-application-in-android/ –  Jan 30 '13 at 05:37

12 Answers12

61

I tried following code, which works for me.

private boolean executeCommand(){
        System.out.println("executeCommand");
        Runtime runtime = Runtime.getRuntime();
        try
        {
            Process  mIpAddrProcess = runtime.exec("/system/bin/ping -c 1 8.8.8.8");
            int mExitValue = mIpAddrProcess.waitFor();
            System.out.println(" mExitValue "+mExitValue);
            if(mExitValue==0){
                return true;
            }else{
                return false;
            }
        }
        catch (InterruptedException ignore)
        {
            ignore.printStackTrace();
            System.out.println(" Exception:"+ignore);
        } 
        catch (IOException e) 
        {
            e.printStackTrace();
            System.out.println(" Exception:"+e);
        }
        return false;
    }
Al Lelopath
  • 6,448
  • 13
  • 82
  • 139
krishna5688
  • 1,130
  • 1
  • 11
  • 19
  • I found this is the only reliable way to check ICMP echo on 4.1. – pipacs Feb 01 '14 at 11:38
  • 2
    Do you need special permissions to run this? – htellez Oct 31 '15 at 05:02
  • 1
    Can someone please explain this? How does checking for "mExitValue" makes sure that ping was successful? – shshnk Mar 15 '16 at 06:25
  • 2
    Checking the exit value of a command is useful because exit 0 generically means the command was successful. Any other value suggests an issue. – Benjamin Castor Jun 03 '16 at 16:28
  • 12
    This leaks memory when put into service and recursively call it! You need to manually close stdin, stdout and stderr file descriptors. runtime.getInputStream().close(); runtime.getOutputStream().close(); runtime.getErrorStream().close(); Use this command to check for pipe leaks: adb shell ls -l /proc//fd. Please edit the answer and add stream closes, I crashed at this intended behaviour for days.. – Ako Jun 13 '16 at 09:27
  • Correct me if I am wrong, but this will always return true right? Doesn't ping always executes successfully regardless of the connection? It is just the output that changes. I thought. But I could be wrong. – Chad Bingham Oct 13 '16 at 22:58
  • @ChadBingham Well, for me `ping` returns `1` if it was unable to reach the server, so it would appear that the exit code does in fact change, at least on Ubuntu 16.04 – You'reAGitForNotUsingGit Jul 15 '17 at 19:13
23

This is a simple ping I use in one of the projects:

public static class Ping {
    public String net = "NO_CONNECTION";
    public String host = "";
    public String ip = "";
    public int dns = Integer.MAX_VALUE;
    public int cnt = Integer.MAX_VALUE;
}

public static Ping ping(URL url, Context ctx) {
    Ping r = new Ping();
    if (isNetworkConnected(ctx)) {
        r.net = getNetworkType(ctx);
        try {
            String hostAddress;
            long start = System.currentTimeMillis();
            hostAddress = InetAddress.getByName(url.getHost()).getHostAddress();
            long dnsResolved = System.currentTimeMillis();
            Socket socket = new Socket(hostAddress, url.getPort());
            socket.close();
            long probeFinish = System.currentTimeMillis();
            r.dns = (int) (dnsResolved - start);
            r.cnt = (int) (probeFinish - dnsResolved);
            r.host = url.getHost();
            r.ip = hostAddress;
        }
        catch (Exception ex) {
            Timber.e("Unable to ping");
        }
    }
    return r;
}

public static boolean isNetworkConnected(Context context) {
    ConnectivityManager cm =
            (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
}

@Nullable
public static String getNetworkType(Context context) {
    ConnectivityManager cm =
            (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    if (activeNetwork != null) {
        return activeNetwork.getTypeName();
    }
    return null;
}

Usage: ping(new URL("https://www.google.com:443/"), this);

Result: {"cnt":100,"dns":109,"host":"www.google.com","ip":"212.188.10.114","net":"WIFI"}

Alexander M.
  • 3,308
  • 2
  • 20
  • 31
  • This pings a specific port while the other solutions use the ICMP ping (not port specific). So this is an interesting alternative. I guess, root permissions are not required? – monok Mar 15 '19 at 09:50
  • Root access is not required but ``should be in the manifest. – Alexander M. Apr 17 '19 at 03:46
11

Run the ping utility in Android's command and parse output (assuming you have root permissions)

See the following Java code snippet:

executeCmd("ping -c 1 -w 1 google.com", false);

public static String executeCmd(String cmd, boolean sudo){
    try {

        Process p;
        if(!sudo)
            p= Runtime.getRuntime().exec(cmd);
        else{
            p= Runtime.getRuntime().exec(new String[]{"su", "-c", cmd});
        }
        BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));

        String s;
        String res = "";
        while ((s = stdInput.readLine()) != null) {
            res += s + "\n";
        }
        p.destroy();
        return res;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return "";

}
Dylan Knowles
  • 2,726
  • 1
  • 26
  • 52
Jim Huang
  • 401
  • 5
  • 9
  • I'm doing ping -c 10 (10 pings averaged) Would it be possible to display line by line? I tried having it append s to a TextView where it would normally append s to res but that didn't work. – sajattack Aug 21 '12 at 23:43
9

In my case ping works from device but not from the emulator. I found this documentation: http://developer.android.com/guide/developing/devices/emulator.html#emulatornetworking

On the topic of "Local Networking Limitations" it says:

"Depending on the environment, the emulator may not be able to support other protocols (such as ICMP, used for "ping") might not be supported. Currently, the emulator does not support IGMP or multicast."

Further information: http://groups.google.com/group/android-developers/browse_thread/thread/8657506be6819297

this is a known limitation of the QEMU user-mode network stack. Quoting from the original doc: Note that ping is not supported reliably to the internet as it would require root privileges. It means you can only ping the local router (10.0.2.2).

Eugene van der Merwe
  • 4,390
  • 1
  • 35
  • 48
4

Ping for the google server or any other server

public boolean isConecctedToInternet() {

    Runtime runtime = Runtime.getRuntime();
    try {
        Process ipProcess = runtime.exec("/system/bin/ping -c 1 8.8.8.8");
        int     exitValue = ipProcess.waitFor();
        return (exitValue == 0);
    } catch (IOException e)          { e.printStackTrace(); }
    catch (InterruptedException e) { e.printStackTrace(); }
    return false;
}
4

I implemented "ping" in pure Android Java and hosted it on gitlab. It does the same thing as the ping executable, but is much easier to configure. 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
2

This is what I implemented myself, which returns the average latency:

/*
Returns the latency to a given server in mili-seconds by issuing a ping command.
system will issue NUMBER_OF_PACKTETS ICMP Echo Request packet each having size of 56 bytes
every second, and returns the avg latency of them.
Returns 0 when there is no connection
 */
public double getLatency(String ipAddress){
    String pingCommand = "/system/bin/ping -c " + NUMBER_OF_PACKTETS + " " + ipAddress;
    String inputLine = "";
    double avgRtt = 0;

    try {
        // execute the command on the environment interface
        Process process = Runtime.getRuntime().exec(pingCommand);
        // gets the input stream to get the output of the executed command
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));

        inputLine = bufferedReader.readLine();
        while ((inputLine != null)) {
            if (inputLine.length() > 0 && inputLine.contains("avg")) {  // when we get to the last line of executed ping command
                break;
            }
            inputLine = bufferedReader.readLine();
        }
    }
    catch (IOException e){
        Log.v(DEBUG_TAG, "getLatency: EXCEPTION");
        e.printStackTrace();
    }

    // Extracting the average round trip time from the inputLine string
    String afterEqual = inputLine.substring(inputLine.indexOf("="), inputLine.length()).trim();
    String afterFirstSlash = afterEqual.substring(afterEqual.indexOf('/') + 1, afterEqual.length()).trim();
    String strAvgRtt = afterFirstSlash.substring(0, afterFirstSlash.indexOf('/'));
    avgRtt = Double.valueOf(strAvgRtt);

    return avgRtt;
}
sorry_I_wont
  • 639
  • 1
  • 9
  • 16
1

Maybe ICMP packets are blocked by your (mobile) provider. If this code doesn't work on the emulator try to sniff via wireshark or any other sniffer and have a look whats up on the wire when you fire the isReachable() method.

You may also find some info in your device log.

Luminger
  • 2,144
  • 15
  • 22
  • I have tested in a Android 2.2 Tablet connected via Wifi i dont use any Momile Provider. Thanks. – Luks89 Oct 11 '10 at 11:08
  • Then your next step should be to sniff the traffic (not) generated by your device. There are many things which could went wrong here... – Luminger Oct 11 '10 at 11:12
  • It's unlikely that it's cause by blocked ICMP, as the Android documentation says that `InetAddress.isReachable` first tries to ping via ICMP if that fails it tries to ping on TCP port 7 (Echo) – Tseng Oct 11 '10 at 13:37
  • 1
    According to http://android.git.kernel.org/?p=platform/libcore.git;a=blob;f=luni/src/main/java/java/net/InetAddress.java;hb=HEAD ICMP will not be used if you don't specify an interface. isReachable only uses the TCP Echo stuff, seems to be some strange behavior or a firewalling problem or something else... Are you sure you are able to access the internet from your application? Ever tried to recieve a file via HTTP? – Luminger Oct 11 '10 at 15:02
  • 1
    how can I test that my app can access to the internet?? – Luks89 Oct 11 '10 at 17:33
  • Seems that the "isReachableByMultiThread" doesn't even try ICMP at the moment. Comment in code: "Spec violation! This implementation doesn't attempt an ICMP; it skips right to TCP echo." - Shame... – Andrioid Mar 17 '11 at 11:47
  • @Andrioid, for raw socket (ICMP) you need root to do it, it's the same in java. the ping command both on *nix/windows actually runs w/ root/admin priviliges – bestsss Aug 16 '11 at 10:37
1

Here is simple code to get latency in kotlin: less if, using ip:String as input, using regex to split format, using avg for latency in ms

    var avg = LATENCY_ERROR
    val process = Runtime.getRuntime().exec("/system/bin/ping -c 1 $ip")
    BufferedReader(InputStreamReader(process.inputStream)).forEachLine {
        // it: "PING 194.194.194.194 (194.194.194.194) 56(84) bytes of data."
        // it: "rtt min/avg/max/mdev = 326.137/326.137/326.137/0.000 ms"
        if (it.contains("rtt ")) {
            avg = Regex("\\d+\\.\\d+").findAll(it).toList()[1].value.toFloat().roundToInt()
        }
    }
0

To get the boolean value for the hit on the ip

public Boolean getInetAddressByName(String name)
    {
        AsyncTask<String, Void, Boolean> task = new AsyncTask<String, Void, Boolean>()
        {

            @Override
            protected Boolean doInBackground(String... params) {
                try
                {
                    return InetAddress.getByName(params[0]).isReachable(2000);
                }
                catch (Exception e)
                {
                    return null;
                }
            }
        };
        try {
            return task.execute(name).get();
        }
        catch (InterruptedException e) {
            return null;
        }
        catch (ExecutionException e) {
            return null;
        }

    }
-2

Use this Code: this method works on 4.3+ and also for below versions too.

   try {

         Process process = null;

        if(Build.VERSION.SDK_INT <= 16) {
            // shiny APIS 
               process = Runtime.getRuntime().exec(
                    "/system/bin/ping -w 1 -c 1 " + url);


        } 
        else 
        {

                   process = new ProcessBuilder()
                 .command("/system/bin/ping", url)
                 .redirectErrorStream(true)
                 .start();

            }



        BufferedReader reader = new BufferedReader(new InputStreamReader(
                process.getInputStream()));

        StringBuffer output = new StringBuffer();
        String temp;

        while ( (temp = reader.readLine()) != null)//.read(buffer)) > 0)
        {
            output.append(temp);
            count++;
        }

        reader.close();


        if(count > 0)
            str = output.toString();

        process.destroy();
     } catch (IOException e) {
         e.printStackTrace();
    }

    Log.i("PING Count", ""+count);
    Log.i("PING String", str);
Ahmad Arslan
  • 4,498
  • 8
  • 38
  • 59
-2

Pink ip Address

  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;
}
   Ping a host and return an int value of 0 or 1 or 2 0=success, 1=fail,
   * 2=error
Sunil Tale
  • 37
  • 1
  • 4