1

我在一个可以从 android shell 发出 ping 或 traceroute 请求的应用程序上工作,我的应用程序读取结果并将其发布给用户。我的问题是我无法从命令中获得整个结果(消息)。例如,traceroute 在显示 HOPS 之前显示初始消息,并且 ping 仅适用于 1 个数据包。否则(对于许多数据包)我得到 ping 请求的初始部分而不是结果。我有一个根设备并安装了busybox,以便使用traceroute 命令。

代码如下

    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;

    }

}
4

2 回答 2

2

对于每个有同样问题的人....我使用了来自android程序的运行shell命令的示例作为代码 使用线程和睡眠时间为我解决了这个问题

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

重要的部分是Thread.sleep(5000); 对于“ls”来说,睡眠时间并不重要。但是对于像 ping 或 traceroute 这样的命令,您需要时间并且必须等待结果,因此 5000ms=5 秒足以获得 ping HOP 的响应。

于 2013-05-15T11:22:53.783 回答
0

你不能确定这是真的:

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

实现可能会在缓冲区完全填满之前返回,以避免等待太久。

另外这条线

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

可能会吃掉输入的某些部分。我不明白它有什么好处。

于 2013-05-14T21:58:06.533 回答