[java] How to Ping External IP from Java Android

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?

This question is related to java android

The answer is


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;
    }

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;
}

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"}


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


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;
}

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

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 "";

}

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);

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).


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;
        }

    }

this worked for me, no root,Android 6.0, Android Studio, Acatel U3:

    private boolean Ping(String IP){
    System.out.println("executeCommand");
    Runtime runtime = Runtime.getRuntime();
    try
    {
        Process  mIpAddrProcess = runtime.exec("/system/bin/ping -c 1 " + IP);
        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;
}

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.