Android - 交互式 shell (Runtime.getRuntime().exec())
Android - Interactive shell (Runtime.getRuntime().exec())
如何在 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 的子命令的输出(另一个按钮 -> onClick())
cmd("help");
应该显示 wpa_cli 帮助,但它不起作用。
如果我多次按下按钮出现输出不完整(帮助)
在 Activity 正在创建并保持其活动以进行交互时初始化进程的正确方法是什么?
谢谢。
邮政数据
我替换了行 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?
OP 的解决方案。
在 Android 中没有使用工具 stdbuf
(coreutils 的)我找到了下一个解决方案:
我正在使用名为 process1 和 process2 的两个进程:两者 -> new ProcessBuilder(new String[]{"su", "-c", "sh"}).start();
在第一个过程中我运行wpa_cli
dos1.write("wpa_cli".getBytes());
dos1.flush();
在一个线程中我等待 5 秒,在第二个进程中 运行 wpa_cli。
dos2.write("wpa_cli".getBytes());
dos2.flush();
要从 wpa_cli 获取输出,必须用 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();
处理程序 handlerStdout
完成了所需的工作。它每 5 秒接收一次 wpa_cli
的输出:输出来自 process1 和 process2 交替
另一种解决方案是为 Android 编译 coreutils 或 stdbuf
。或者从 http://forum.xda-developers.com/showthread.php?t=2613243 安装已编译的 coreutils(对我来说不起作用 stdbuf
因为找不到 libstdbuf.so
)
stdbuf -oL wpa_cli
输出不缓冲(缓冲一行)。没有它,输出会被缓冲 (4k)。
如何在 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 的子命令的输出(另一个按钮 -> onClick())
cmd("help");
应该显示 wpa_cli 帮助,但它不起作用。
如果我多次按下按钮出现输出不完整(帮助)
在 Activity 正在创建并保持其活动以进行交互时初始化进程的正确方法是什么?
谢谢。
邮政数据
我替换了行 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?
OP 的解决方案。
在 Android 中没有使用工具 stdbuf
(coreutils 的)我找到了下一个解决方案:
我正在使用名为 process1 和 process2 的两个进程:两者 -> new ProcessBuilder(new String[]{"su", "-c", "sh"}).start();
在第一个过程中我运行wpa_cli
dos1.write("wpa_cli".getBytes());
dos1.flush();
在一个线程中我等待 5 秒,在第二个进程中 运行 wpa_cli。
dos2.write("wpa_cli".getBytes());
dos2.flush();
要从 wpa_cli 获取输出,必须用 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();
处理程序 handlerStdout
完成了所需的工作。它每 5 秒接收一次 wpa_cli
的输出:输出来自 process1 和 process2 交替
另一种解决方案是为 Android 编译 coreutils 或 stdbuf
。或者从 http://forum.xda-developers.com/showthread.php?t=2613243 安装已编译的 coreutils(对我来说不起作用 stdbuf
因为找不到 libstdbuf.so
)
stdbuf -oL wpa_cli
输出不缓冲(缓冲一行)。没有它,输出会被缓冲 (4k)。