2012-01-30 20 views
5

C'è un modo per eseguire il ping di un host (Android standard o tramite implementazione NDK) e ottenere informazioni dettagliate sulla risposta? (Tempo, TTL, pacchetti persi, ecc ..) Stavo pensando a qualche app open source che ha questa caratteristica, ma non riesce a trovare alcun ...Ping ICMP Android

Grazie

risposta

13

AFAIK, l'invio di ICMP ECHO chiede esigenze root (ovvero l'app che deve essere impostata) - e questo è non attualmente possibile in "stock" Android (diavolo, anche il metodo InetAddress#isReachable() in Android è un joke che non funziona secondo le specifiche).

Un esempio molto semplice utilizzando/usr/bin/ping & processo - la lettura dei risultati ping, utilizzando 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. Ho un telefono non sradicato, l'app Net Ping funziona come progettata. –

+1

quindi probabilmente sta eseguendo il comando ping usando [java.lang.Process] (http://developer.android.com/reference/java/lang/Process.html) - questo comando è setuid e può darti il ​​TTL se analizzare l'output - farlo direttamente da Java non funzionerà (l'esempio in Process sta infatti eseguendo il comando ping). – Jens

+0

puoi eseguire il comando 'ping' con java.lang.Process senza root? –

0

Ho trovato un modo per eseguire il comando ping, senza radici.
genera un processo 'sh' prima, e poi eseguire 'ping' in quel guscio, il codice:

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

Funziona bene sul mio dispositivo HTC con CyanogenMod 7.1.0 (Android 2.3.7)

+1

Senza -w <# seconds> sul comando ping Ottengo un blocco se potenzialmente non modificabile - Solo un avvertimento per chi prova questo .. –

+1

-1 È un design scarso creare una shell, quindi lanciare ping. Coinvolge più parsing e più difficoltà a passare in input. È meglio lanciare il ping direttamente. –