Question

I work on an application that can make ping or traceroute requests from the android shell and my application reads the result and post it to the user. My problem is that I can not get the whole result (message) from the command. For example, the traceroute displays the initial message just before showing the HOPS and ping only works for 1 packet properly. Otherwise (for many packets) I get the initial part of ping request and not the results. I have a rooted device and installed busybox in order to have traceroute command.

The code is the following

    package com.example.commandshelltest;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.TextView;

public class MainActivity extends Activity {

    TextView tv1;
    String out = new String();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
    String result=execute_reboot();
    TextView tv1=(TextView)findViewById(R.id.textView1);
    //tv1.setText(Integer.toString(result.length())); // i can see that while increasing the number of icmp packets in ping the length stays the same
    tv1.setText(result);

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    String execute_reboot()
    {
        Process process1;
        try {
            int BUFF_LEN =1024;
            process1=Runtime.getRuntime().exec("su");
              DataOutputStream os = 
                  new DataOutputStream(process1.getOutputStream());
                //os.writeBytes("traceroute 8.8.8.8\n");
                os.writeBytes("ping -c 1 8.8.8.8\n");
                os.flush();
                InputStream stdout = process1.getInputStream();
                byte[] buffer = new byte[BUFF_LEN];
                int read;

                while((read=stdout.read(buffer))>0)
                while(true){
                    read = stdout.read(buffer);
                    out += new String(buffer, 0, read);
                    if(read<BUFF_LEN){
                        //we have read everything
                        break;
                    }
                }

                  os.writeBytes("exit\n");
                  os.flush();

                process1.waitFor();

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return out;

    }

}
Was it helpful?

Solution

For everyone having the same problem.... I used as a code the example from Run shell commands from android program The use of threads and sleep time solved the problem for me

public void runAsRoot(String[] cmds) throws Exception {
        Process p = Runtime.getRuntime().exec("su");
        DataOutputStream os = new DataOutputStream(p.getOutputStream());
        InputStream is = p.getInputStream();
        for (String tmpCmd : cmds) {
            os.writeBytes(tmpCmd+"\n");
            int readed = 0;
            byte[] buff = new byte[4096];
            boolean cmdRequiresAnOutput = true;
            if (cmdRequiresAnOutput) {
                while( is.available() <= 0) {
                    try { Thread.sleep(5000); } catch(Exception ex) {}
                }

                while( is.available() > 0) {
                    readed = is.read(buff);
                    if ( readed <= 0 ) break;
                    String seg = new String(buff,0,readed);   
                    result=seg; //result is a string to show in textview
                }
            }
        }        
        os.writeBytes("exit\n");
        os.flush();

the important part is the Thread.sleep(5000); For "ls" the sleep time is not important. But for commands like ping or traceroute you need time and you have to wait for the results, hence 5000ms=5seconds is enough to get a response for a ping HOP.

OTHER TIPS

You can't be sure that this is true:

                 if(read<BUFF_LEN){
                     //we have read everything
                     break;

The implementation may return before the buffer is filled entirely to avoid too long waiting.

Additionally the line

            while((read=stdout.read(buffer))>0)

may eat up some parts of the input. I don't understand what it is good for.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top