Android - 交互式shell(Runtime.getRuntime()。exec())

时间:2015-07-08 14:56:37

标签: android shell process bufferedreader interactive

如何在android上运行交互式shell? (有根设备)

我需要接下来的步骤:

1 - 执行shell进程(onCreate)

Process p = Runtime.getRuntime().exec(String[]{"su","-c","sh"});

2 - 获取输出(onCreate)

BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream));
//dos is a field (a class attribute)
dos = new DataOutputStream(p.getOutputStream());
new Thread(new Runnable() {

    @Override
    public void run() {
         String l;
         //wait the console output and write it
         while((l = br.readLine()) != null) {
              Log.v("info", l);
         }
    }
}).start();

3 - 执行命令(按钮 - > onClick())

cmd("wpa_cli");

cmd方法是:

public void cmd(String cmd) {
   dos.writeBytes(cmd + "\n");
   dos.flush();
}

日志永远不会显示控制台输出。

下一步:

4 - 获取wpa_cli子命令的输出(另一个Button - > onClick())

cmd("help");

应该显示wpa_cli帮助,但它不起作用。
如果我按下按钮多次出现不完整的输出(帮助)

在创建活动时初始化流程的正确方法是什么,并使其保持活动状态以进行交互?

感谢。

POSTDATA
我更换了行Log.v("info", l);

fos.write(l);
Message msg = handlerTest.obtainMessage();
msg.obj = l;
handlerTest.sendMessage(msg);

fos - > FileOutputStream对象

Handler handlerTest = new Handler() {
    @Override
    handleMessage(Message msg) {
       if (msg != null) {
         //alert... (String)msg.obj;
       }
    }
}; 

仅显示来自直接命令的警报,例如help。命令status仅在关闭流时才起作用。 (执行cmd("quit");cmd("exit");后)

我不明白。 stdout多一点?我可以在不关闭流的情况下与输出进行交互吗?

使用adb shell我读取输出文件(关闭流后创建)并完成。

PostData2:

问题是缓冲区。在二进制文件(执行)输出和java进程之间我可以在不使用Native I / O的情况下禁用缓冲区吗? Android终端模拟器工作正常,它使用的是NIO吗?

1 个答案:

答案 0 :(得分:0)

OP解决方案。

在Android中没有使用{core(1)}(coreutils)工具,我找到了下一个解决方案:

我正在使用两个名为process1和process2的进程:两个 - > stdbuf

在第一个过程中,我运行new ProcessBuilder(new String[]{"su", "-c", "sh"}).start();

wpa_cli

在一个线程中,我等待5秒,然后在第二个进程中运行wpa_cli。

dos1.write("wpa_cli".getBytes());
dos1.flush();

要获取wpa_cli的输出,必须使用dos2.write("wpa_cli".getBytes()); dos2.flush();

关闭它
quit

适用于两个进程的主线程:

dos1.write("quit".getBytes());
dos1.flush();

重要:两个进程都具有此功能(创建进程时):

new Thread(new Runnable() {
                @Override
                public void run() {
                    boolean firstProcess = true;
                    while (follow) {
                        try {
                            Thread.sleep(5000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        if (follow) {
                            if (firstProcess) {
                                cmd("wpa_cli", dos2);
                                cmd("quit", dos1);
                            } else {
                                cmd("wpa_cli", dos1);
                                cmd("quit", dos2);
                            }
                            firstProcess = !firstProcess;
                        }
                    }
                }
            }).start();

处理程序new Thread(new Runnable() { @Override public void run() { BufferedReader br = new BufferedReader(new InputStreamReader(process1.getInputStream())); String l; try { Message msg; while ((l = br.readLine()) != null) { msg = handlerStdout.obtainMessage(); msg.obj = l; handlerStdout.sendMessage(msg); } } catch (IOException e) { e.printStackTrace(); } } }).start(); 执行所需的工作。它每5秒接收handlerStdout的输出:输出来自process1,process2来自

另一种解决方案是为Android编译coreutils或wpa_cli。或者从http://forum.xda-developers.com/showthread.php?t=2613243安装已编译的coreutils(因为stdbuf未找到),因此我无法工作stdbuf

使用libstdbuf.so输出不缓冲(缓冲区一行)。如果没有它,输出将被缓冲(4k)。