Monday, January 30, 2012

Android ICMP ping


Is there a way to ping a host (standard Android or via NDK implementation), and get detailed info on the response? (time, ttl, lost packages, etc..) I was thinking of some open source app that has this feature but can't find any...



Thanks

1 comment:

  1. Afaik, sending ICMP ECHO requests needs root (i.e. the app that does it needs to be setuid) - and that's not currently possible in "stock" Android (hell, even the InetAddress#isReachable() method in Android is a joke that doesn't work according to spec).

    A very basic example using /usr/bin/ping & Process - reading the ping results, using an AsyncTask:

    public class PingActivity extends Activity {
    PingTask mTask;
    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    }

    @Override
    protected void onResume() {
    super.onResume();
    mTask = new PingTask();
    // Ping the host "android.com"
    mTask.execute("android.com");
    }

    @Override
    protected void onPause() {
    super.onPause();
    mTask.stop();
    }

    class PingTask extends AsyncTask<String, Void, Void> {
    PipedOutputStream mPOut;
    PipedInputStream mPIn;
    LineNumberReader mReader;
    Process mProcess;
    TextView mText = (TextView) findViewById(R.id.text);
    @Override
    protected void onPreExecute() {
    mPOut = new PipedOutputStream();
    try {
    mPIn = new PipedInputStream(mPOut);
    mReader = new LineNumberReader(new InputStreamReader(mPIn));
    } catch (IOException e) {
    cancel(true);
    }

    }

    public void stop() {
    Process p = mProcess;
    if (p != null) {
    p.destroy();
    }
    cancel(true);
    }

    @Override
    protected Void doInBackground(String... params) {
    try {
    mProcess = new ProcessBuilder()
    .command("/system/bin/ping", params[0])
    .redirectErrorStream(true)
    .start();

    try {
    InputStream in = mProcess.getInputStream();
    OutputStream out = mProcess.getOutputStream();
    byte[] buffer = new byte[1024];
    int count;

    // in -> buffer -> mPOut -> mReader -> 1 line of ping information to parse
    while ((count = in.read(buffer)) != -1) {
    mPOut.write(buffer, 0, count);
    publishProgress();
    }
    out.close();
    in.close();
    mPOut.close();
    mPIn.close();
    } finally {
    mProcess.destroy();
    mProcess = null;
    }
    } catch (IOException e) {
    }
    return null;
    }
    @Override
    protected void onProgressUpdate(Void... values) {
    try {
    // Is a line ready to read from the "ping" command?
    while (mReader.ready()) {
    // This just displays the output, you should typically parse it I guess.
    mText.setText(mReader.readLine());
    }
    } catch (IOException t) {
    }
    }
    }
    }

    ReplyDelete