开发者

How to Ping External IP from Java Android

开发者 https://www.devze.com 2023-01-19 06:52 出处:网络
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.

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?


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


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

}


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


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


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


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


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.


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

    }


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()
        }
    }


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


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
0

精彩评论

暂无评论...
验证码 换一张
取 消