2012-01-30 22 views
5

¿Hay alguna manera de hacer ping a un host (Android estándar oa través de la implementación de NDK) y obtener información detallada sobre la respuesta? (Tiempo, TTL, pierde paquetes, etc ..) estaba pensando en alguna aplicación de código abierto que tiene esta característica, pero no puede encontrar ninguna ...Android ICMP ping

Gracias

Respuesta

13

Que yo sepa, el envío de ICMP ECHO solicita necesidades raíz (es decir, la aplicación que necesita ser setuid) - y eso es no es posible en "stock" Android (demonios, incluso el método InetAddress#isReachable() en Android es un joke que no funciona según las especificaciones).

Un ejemplo muy básico utilizando/usr/bin/ping & Proceso - lectura de los resultados de ping, utilizando un 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) { 
      } 
     } 
    } 
} 
+0

no. Tengo el teléfono sin rootear, la aplicación Net Ping funciona como está diseñada. –

+1

entonces probablemente esté ejecutando el comando ping usando [java.lang.Process] (http://developer.android.com/reference/java/lang/Process.html) - ese comando es setuid y puede darle el TTL si analizar el resultado - hacerlo directamente desde Java no va a funcionar (el ejemplo en Process de hecho está ejecutando el comando ping). – Jens

+0

¿puedes ejecutar el comando 'ping' con java.lang.Process sin root? –

0

He encontrado una manera de ejecutar comando ping sin raíz.
genera un proceso 'sh' en primer lugar, y luego ejecutar 'ping' en esa cáscara, el código:

p = new ProcessBuilder("sh").redirectErrorStream(true).start(); 

DataOutputStream os = new DataOutputStream(p.getOutputStream()); 
os.writeBytes("ping -c 10 " + host + '\n'); 
os.flush(); 

// Close the terminal 
os.writeBytes("exit\n"); 
os.flush(); 

// read ping replys 
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream())); 
String line; 

while ((line = reader.readLine()) != null) { 
    System.out.println(line); 
} 

Funciona bien en mi dispositivo HTC con CyanogenMod 7.1.0 (Android 2.3.7)

+1

Sin -w <# seconds> en el comando ping me cuelgo si potencialmente imposible - Sólo una advertencia para aquellos que intentan esto ... –

+1

-1 Es un diseño pobre para crear un caparazón, luego iniciar ping. Implica más análisis y más dificultad para pasar datos. Es mejor iniciar ping directamente. –